VirtualBox

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

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

VMM/HMVMXR0: Nested VMX: bugref:9180 Add HMVMX_ALWAYS_SAVE_RO_GUEST_STATE and hmR0VmxReadAllRoFieldsVmcs.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 734.1 KB
Line 
1/* $Id: HMVMXR0.cpp 79872 2019-07-19 09:05:38Z 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_RO_GUEST_STATE
51# define HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE
52# define HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
53# define HMVMX_ALWAYS_CLEAN_TRANSIENT
54# define HMVMX_ALWAYS_CHECK_GUEST_STATE
55# define HMVMX_ALWAYS_TRAP_ALL_XCPTS
56# define HMVMX_ALWAYS_TRAP_PF
57# define HMVMX_ALWAYS_FLUSH_TLB
58# define HMVMX_ALWAYS_SWAP_EFER
59#endif
60
61
62/*********************************************************************************************************************************
63* Defined Constants And Macros *
64*********************************************************************************************************************************/
65/** Use the function table. */
66#define HMVMX_USE_FUNCTION_TABLE
67
68/** Determine which tagged-TLB flush handler to use. */
69#define HMVMX_FLUSH_TAGGED_TLB_EPT_VPID 0
70#define HMVMX_FLUSH_TAGGED_TLB_EPT 1
71#define HMVMX_FLUSH_TAGGED_TLB_VPID 2
72#define HMVMX_FLUSH_TAGGED_TLB_NONE 3
73
74/**
75 * Flags to skip redundant reads of some common VMCS fields that are not part of
76 * the guest-CPU or VCPU state but are needed while handling VM-exits.
77 */
78#define HMVMX_READ_IDT_VECTORING_INFO RT_BIT_32(0)
79#define HMVMX_READ_IDT_VECTORING_ERROR_CODE RT_BIT_32(1)
80#define HMVMX_READ_EXIT_QUALIFICATION RT_BIT_32(2)
81#define HMVMX_READ_EXIT_INSTR_LEN RT_BIT_32(3)
82#define HMVMX_READ_EXIT_INTERRUPTION_INFO RT_BIT_32(4)
83#define HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE RT_BIT_32(5)
84#define HMVMX_READ_EXIT_INSTR_INFO RT_BIT_32(6)
85#define HMVMX_READ_GUEST_LINEAR_ADDR RT_BIT_32(7)
86#define HMVMX_READ_GUEST_PHYSICAL_ADDR RT_BIT_32(8)
87
88/** All the VMCS fields required for processing of exception/NMI VM-exits. */
89#define HMVMX_READ_XCPT_INFO ( HMVMX_READ_EXIT_INTERRUPTION_INFO \
90 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE \
91 | HMVMX_READ_EXIT_INSTR_LEN \
92 | HMVMX_READ_IDT_VECTORING_INFO \
93 | HMVMX_READ_IDT_VECTORING_ERROR_CODE)
94
95/** Assert that all the given fields have been read from the VMCS. */
96#ifdef VBOX_STRICT
97# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) \
98 do { \
99 uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead); \
100 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); \
101 Assert((fVmcsFieldRead & (a_fReadFields)) == (a_fReadFields)); \
102 } while (0)
103#else
104# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) do { } while (0)
105#endif
106
107/**
108 * Subset of the guest-CPU state that is kept by VMX R0 code while executing the
109 * guest using hardware-assisted VMX.
110 *
111 * This excludes state like GPRs (other than RSP) which are always are
112 * swapped and restored across the world-switch and also registers like EFER,
113 * MSR which cannot be modified by the guest without causing a VM-exit.
114 */
115#define HMVMX_CPUMCTX_EXTRN_ALL ( CPUMCTX_EXTRN_RIP \
116 | CPUMCTX_EXTRN_RFLAGS \
117 | CPUMCTX_EXTRN_RSP \
118 | CPUMCTX_EXTRN_SREG_MASK \
119 | CPUMCTX_EXTRN_TABLE_MASK \
120 | CPUMCTX_EXTRN_KERNEL_GS_BASE \
121 | CPUMCTX_EXTRN_SYSCALL_MSRS \
122 | CPUMCTX_EXTRN_SYSENTER_MSRS \
123 | CPUMCTX_EXTRN_TSC_AUX \
124 | CPUMCTX_EXTRN_OTHER_MSRS \
125 | CPUMCTX_EXTRN_CR0 \
126 | CPUMCTX_EXTRN_CR3 \
127 | CPUMCTX_EXTRN_CR4 \
128 | CPUMCTX_EXTRN_DR7 \
129 | CPUMCTX_EXTRN_HWVIRT \
130 | CPUMCTX_EXTRN_HM_VMX_MASK)
131
132/**
133 * Exception bitmap mask for real-mode guests (real-on-v86).
134 *
135 * We need to intercept all exceptions manually except:
136 * - \#AC and \#DB are always intercepted to prevent the CPU from deadlocking
137 * due to bugs in Intel CPUs.
138 * - \#PF need not be intercepted even in real-mode if we have nested paging
139 * support.
140 */
141#define HMVMX_REAL_MODE_XCPT_MASK ( RT_BIT(X86_XCPT_DE) /* always: | RT_BIT(X86_XCPT_DB) */ | RT_BIT(X86_XCPT_NMI) \
142 | RT_BIT(X86_XCPT_BP) | RT_BIT(X86_XCPT_OF) | RT_BIT(X86_XCPT_BR) \
143 | RT_BIT(X86_XCPT_UD) | RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_DF) \
144 | RT_BIT(X86_XCPT_CO_SEG_OVERRUN) | RT_BIT(X86_XCPT_TS) | RT_BIT(X86_XCPT_NP) \
145 | RT_BIT(X86_XCPT_SS) | RT_BIT(X86_XCPT_GP) /* RT_BIT(X86_XCPT_PF) */ \
146 | RT_BIT(X86_XCPT_MF) /* always: | RT_BIT(X86_XCPT_AC) */ | RT_BIT(X86_XCPT_MC) \
147 | RT_BIT(X86_XCPT_XF))
148
149/** Maximum VM-instruction error number. */
150#define HMVMX_INSTR_ERROR_MAX 28
151
152/** Profiling macro. */
153#ifdef HM_PROFILE_EXIT_DISPATCH
154# define HMVMX_START_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitDispatch, ed)
155# define HMVMX_STOP_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitDispatch, ed)
156#else
157# define HMVMX_START_EXIT_DISPATCH_PROF() do { } while (0)
158# define HMVMX_STOP_EXIT_DISPATCH_PROF() do { } while (0)
159#endif
160
161/** Assert that preemption is disabled or covered by thread-context hooks. */
162#define HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu) Assert( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
163 || !RTThreadPreemptIsEnabled(NIL_RTTHREAD))
164
165/** Assert that we haven't migrated CPUs when thread-context hooks are not
166 * used. */
167#define HMVMX_ASSERT_CPU_SAFE(a_pVCpu) AssertMsg( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
168 || (a_pVCpu)->hm.s.idEnteredCpu == RTMpCpuId(), \
169 ("Illegal migration! Entered on CPU %u Current %u\n", \
170 (a_pVCpu)->hm.s.idEnteredCpu, RTMpCpuId()))
171
172/** Asserts that the given CPUMCTX_EXTRN_XXX bits are present in the guest-CPU
173 * context. */
174#define HMVMX_CPUMCTX_ASSERT(a_pVCpu, a_fExtrnMbz) AssertMsg(!((a_pVCpu)->cpum.GstCtx.fExtrn & (a_fExtrnMbz)), \
175 ("fExtrn=%#RX64 fExtrnMbz=%#RX64\n", \
176 (a_pVCpu)->cpum.GstCtx.fExtrn, (a_fExtrnMbz)))
177
178/** Log the VM-exit reason with an easily visible marker to identify it in a
179 * potential sea of logging data. */
180#define HMVMX_LOG_EXIT(a_pVCpu, a_uExitReason) \
181 do { \
182 Log4(("VM-exit: vcpu[%RU32] %85s -v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-\n", (a_pVCpu)->idCpu, \
183 HMGetVmxExitName(a_uExitReason))); \
184 } while (0) \
185
186
187/*********************************************************************************************************************************
188* Structures and Typedefs *
189*********************************************************************************************************************************/
190/**
191 * VMX per-VCPU transient state.
192 *
193 * A state structure for holding miscellaneous information across
194 * VMX non-root operation and restored after the transition.
195 */
196typedef struct VMXTRANSIENT
197{
198 /** The host's rflags/eflags. */
199 RTCCUINTREG fEFlags;
200#if HC_ARCH_BITS == 32
201 uint32_t u32Alignment0;
202#endif
203 /** The guest's TPR value used for TPR shadowing. */
204 uint8_t u8GuestTpr;
205 /** Alignment. */
206 uint8_t abAlignment0[7];
207
208 /** The basic VM-exit reason. */
209 uint16_t uExitReason;
210 /** Alignment. */
211 uint16_t u16Alignment0;
212 /** The VM-exit interruption error code. */
213 uint32_t uExitIntErrorCode;
214 /** The VM-exit exit code qualification. */
215 uint64_t uExitQual;
216 /** The Guest-linear address. */
217 uint64_t uGuestLinearAddr;
218 /** The Guest-physical address. */
219 uint64_t uGuestPhysicalAddr;
220
221 /** The VM-exit interruption-information field. */
222 uint32_t uExitIntInfo;
223 /** The VM-exit instruction-length field. */
224 uint32_t cbInstr;
225 /** The VM-exit instruction-information field. */
226 VMXEXITINSTRINFO ExitInstrInfo;
227 /** Whether the VM-entry failed or not. */
228 bool fVMEntryFailed;
229 /** Whether we are currently executing a nested-guest. */
230 bool fIsNestedGuest;
231 /** Alignment. */
232 uint8_t abAlignment1[2];
233
234 /** The VM-entry interruption-information field. */
235 uint32_t uEntryIntInfo;
236 /** The VM-entry exception error code field. */
237 uint32_t uEntryXcptErrorCode;
238 /** The VM-entry instruction length field. */
239 uint32_t cbEntryInstr;
240
241 /** IDT-vectoring information field. */
242 uint32_t uIdtVectoringInfo;
243 /** IDT-vectoring error code. */
244 uint32_t uIdtVectoringErrorCode;
245
246 /** Mask of currently read VMCS fields; HMVMX_READ_XXX. */
247 uint32_t fVmcsFieldsRead;
248
249 /** Whether the guest debug state was active at the time of VM-exit. */
250 bool fWasGuestDebugStateActive;
251 /** Whether the hyper debug state was active at the time of VM-exit. */
252 bool fWasHyperDebugStateActive;
253 /** Whether TSC-offsetting and VMX-preemption timer was updated before VM-entry. */
254 bool fUpdatedTscOffsettingAndPreemptTimer;
255 /** Whether the VM-exit was caused by a page-fault during delivery of a
256 * contributory exception or a page-fault. */
257 bool fVectoringDoublePF;
258 /** Whether the VM-exit was caused by a page-fault during delivery of an
259 * external interrupt or NMI. */
260 bool fVectoringPF;
261 /** Whether the TSC_AUX MSR needs to be removed from the auto-load/store MSR
262 * area after VM-exit. */
263 bool fRemoveTscAuxMsr;
264 bool afAlignment0[2];
265
266 /** The VMCS info. object. */
267 PVMXVMCSINFO pVmcsInfo;
268} VMXTRANSIENT;
269AssertCompileMemberAlignment(VMXTRANSIENT, uExitReason, sizeof(uint64_t));
270AssertCompileMemberAlignment(VMXTRANSIENT, uExitIntInfo, sizeof(uint64_t));
271AssertCompileMemberAlignment(VMXTRANSIENT, uEntryIntInfo, sizeof(uint64_t));
272AssertCompileMemberAlignment(VMXTRANSIENT, fWasGuestDebugStateActive, sizeof(uint64_t));
273AssertCompileMemberAlignment(VMXTRANSIENT, pVmcsInfo, sizeof(uint64_t));
274AssertCompileMemberSize(VMXTRANSIENT, ExitInstrInfo, sizeof(uint32_t));
275/** Pointer to VMX transient state. */
276typedef VMXTRANSIENT *PVMXTRANSIENT;
277/** Pointer to a const VMX transient state. */
278typedef const VMXTRANSIENT *PCVMXTRANSIENT;
279
280/**
281 * Memory operand read or write access.
282 */
283typedef enum VMXMEMACCESS
284{
285 VMXMEMACCESS_READ = 0,
286 VMXMEMACCESS_WRITE = 1
287} VMXMEMACCESS;
288
289/**
290 * VMX VM-exit handler.
291 *
292 * @returns Strict VBox status code (i.e. informational status codes too).
293 * @param pVCpu The cross context virtual CPU structure.
294 * @param pVmxTransient The VMX-transient structure.
295 */
296#ifndef HMVMX_USE_FUNCTION_TABLE
297typedef VBOXSTRICTRC FNVMXEXITHANDLER(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
298#else
299typedef DECLCALLBACK(VBOXSTRICTRC) FNVMXEXITHANDLER(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
300/** Pointer to VM-exit handler. */
301typedef FNVMXEXITHANDLER *PFNVMXEXITHANDLER;
302#endif
303
304/**
305 * VMX VM-exit handler, non-strict status code.
306 *
307 * This is generally the same as FNVMXEXITHANDLER, the NSRC bit is just FYI.
308 *
309 * @returns VBox status code, no informational status code returned.
310 * @param pVCpu The cross context virtual CPU structure.
311 * @param pVmxTransient The VMX-transient structure.
312 *
313 * @remarks This is not used on anything returning VERR_EM_INTERPRETER as the
314 * use of that status code will be replaced with VINF_EM_SOMETHING
315 * later when switching over to IEM.
316 */
317#ifndef HMVMX_USE_FUNCTION_TABLE
318typedef int FNVMXEXITHANDLERNSRC(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
319#else
320typedef FNVMXEXITHANDLER FNVMXEXITHANDLERNSRC;
321#endif
322
323
324/*********************************************************************************************************************************
325* Internal Functions *
326*********************************************************************************************************************************/
327#ifndef HMVMX_USE_FUNCTION_TABLE
328DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
329# define HMVMX_EXIT_DECL DECLINLINE(VBOXSTRICTRC)
330# define HMVMX_EXIT_NSRC_DECL DECLINLINE(int)
331#else
332# define HMVMX_EXIT_DECL static DECLCALLBACK(VBOXSTRICTRC)
333# define HMVMX_EXIT_NSRC_DECL HMVMX_EXIT_DECL
334#endif
335#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
336DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
337#endif
338
339static int hmR0VmxImportGuestState(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat);
340#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
341static void hmR0VmxInitVmcsReadCache(PVMCPU pVCpu);
342#endif
343
344/** @name VM-exit handler prototypes.
345 * @{
346 */
347static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmi;
348static FNVMXEXITHANDLER hmR0VmxExitExtInt;
349static FNVMXEXITHANDLER hmR0VmxExitTripleFault;
350static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindow;
351static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindow;
352static FNVMXEXITHANDLER hmR0VmxExitTaskSwitch;
353static FNVMXEXITHANDLER hmR0VmxExitCpuid;
354static FNVMXEXITHANDLER hmR0VmxExitGetsec;
355static FNVMXEXITHANDLER hmR0VmxExitHlt;
356static FNVMXEXITHANDLERNSRC hmR0VmxExitInvd;
357static FNVMXEXITHANDLER hmR0VmxExitInvlpg;
358static FNVMXEXITHANDLER hmR0VmxExitRdpmc;
359static FNVMXEXITHANDLER hmR0VmxExitVmcall;
360#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
361static FNVMXEXITHANDLER hmR0VmxExitVmclear;
362static FNVMXEXITHANDLER hmR0VmxExitVmlaunch;
363static FNVMXEXITHANDLER hmR0VmxExitVmptrld;
364static FNVMXEXITHANDLER hmR0VmxExitVmptrst;
365static FNVMXEXITHANDLER hmR0VmxExitVmread;
366static FNVMXEXITHANDLER hmR0VmxExitVmresume;
367static FNVMXEXITHANDLER hmR0VmxExitVmwrite;
368static FNVMXEXITHANDLER hmR0VmxExitVmxoff;
369static FNVMXEXITHANDLER hmR0VmxExitVmxon;
370static FNVMXEXITHANDLER hmR0VmxExitInvvpid;
371#endif
372static FNVMXEXITHANDLER hmR0VmxExitRdtsc;
373static FNVMXEXITHANDLER hmR0VmxExitMovCRx;
374static FNVMXEXITHANDLER hmR0VmxExitMovDRx;
375static FNVMXEXITHANDLER hmR0VmxExitIoInstr;
376static FNVMXEXITHANDLER hmR0VmxExitRdmsr;
377static FNVMXEXITHANDLER hmR0VmxExitWrmsr;
378static FNVMXEXITHANDLER hmR0VmxExitMwait;
379static FNVMXEXITHANDLER hmR0VmxExitMtf;
380static FNVMXEXITHANDLER hmR0VmxExitMonitor;
381static FNVMXEXITHANDLER hmR0VmxExitPause;
382static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThreshold;
383static FNVMXEXITHANDLER hmR0VmxExitApicAccess;
384static FNVMXEXITHANDLER hmR0VmxExitEptViolation;
385static FNVMXEXITHANDLER hmR0VmxExitEptMisconfig;
386static FNVMXEXITHANDLER hmR0VmxExitRdtscp;
387static FNVMXEXITHANDLER hmR0VmxExitPreemptTimer;
388static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvd;
389static FNVMXEXITHANDLER hmR0VmxExitXsetbv;
390static FNVMXEXITHANDLER hmR0VmxExitInvpcid;
391static FNVMXEXITHANDLERNSRC hmR0VmxExitSetPendingXcptUD;
392static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestState;
393static FNVMXEXITHANDLERNSRC hmR0VmxExitErrUnexpected;
394/** @} */
395
396#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
397/** @name Nested-guest VM-exit handler prototypes.
398 * @{
399 */
400static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmiNested;
401static FNVMXEXITHANDLER hmR0VmxExitTripleFaultNested;
402static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindowNested;
403static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindowNested;
404static FNVMXEXITHANDLER hmR0VmxExitTaskSwitchNested;
405static FNVMXEXITHANDLER hmR0VmxExitHltNested;
406static FNVMXEXITHANDLER hmR0VmxExitInvlpgNested;
407static FNVMXEXITHANDLER hmR0VmxExitRdpmcNested;
408static FNVMXEXITHANDLER hmR0VmxExitVmreadVmwriteNested;
409static FNVMXEXITHANDLER hmR0VmxExitRdtscNested;
410static FNVMXEXITHANDLER hmR0VmxExitMovCRxNested;
411static FNVMXEXITHANDLER hmR0VmxExitMovDRxNested;
412static FNVMXEXITHANDLER hmR0VmxExitIoInstrNested;
413static FNVMXEXITHANDLER hmR0VmxExitRdmsrNested;
414static FNVMXEXITHANDLER hmR0VmxExitWrmsrNested;
415static FNVMXEXITHANDLER hmR0VmxExitMwaitNested;
416static FNVMXEXITHANDLER hmR0VmxExitMtfNested;
417static FNVMXEXITHANDLER hmR0VmxExitMonitorNested;
418static FNVMXEXITHANDLER hmR0VmxExitPauseNested;
419static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThresholdNested;
420static FNVMXEXITHANDLER hmR0VmxExitApicAccessNested;
421static FNVMXEXITHANDLER hmR0VmxExitApicWriteNested;
422static FNVMXEXITHANDLER hmR0VmxExitVirtEoiNested;
423static FNVMXEXITHANDLER hmR0VmxExitRdtscpNested;
424static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvdNested;
425static FNVMXEXITHANDLER hmR0VmxExitInvpcidNested;
426static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestStateNested;
427static FNVMXEXITHANDLER hmR0VmxExitInstrNested;
428static FNVMXEXITHANDLER hmR0VmxExitInstrWithInfoNested;
429/** @} */
430#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
431
432
433/*********************************************************************************************************************************
434* Global Variables *
435*********************************************************************************************************************************/
436#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
437/**
438 * Array of all VMCS fields.
439 * Any fields added to the VT-x spec. should be added here.
440 *
441 * Currently only used to derive shadow VMCS fields for hardware-assisted execution
442 * of nested-guests.
443 */
444static const uint32_t g_aVmcsFields[] =
445{
446 /* 16-bit control fields. */
447 VMX_VMCS16_VPID,
448 VMX_VMCS16_POSTED_INT_NOTIFY_VECTOR,
449 VMX_VMCS16_EPTP_INDEX,
450
451 /* 16-bit guest-state fields. */
452 VMX_VMCS16_GUEST_ES_SEL,
453 VMX_VMCS16_GUEST_CS_SEL,
454 VMX_VMCS16_GUEST_SS_SEL,
455 VMX_VMCS16_GUEST_DS_SEL,
456 VMX_VMCS16_GUEST_FS_SEL,
457 VMX_VMCS16_GUEST_GS_SEL,
458 VMX_VMCS16_GUEST_LDTR_SEL,
459 VMX_VMCS16_GUEST_TR_SEL,
460 VMX_VMCS16_GUEST_INTR_STATUS,
461 VMX_VMCS16_GUEST_PML_INDEX,
462
463 /* 16-bits host-state fields. */
464 VMX_VMCS16_HOST_ES_SEL,
465 VMX_VMCS16_HOST_CS_SEL,
466 VMX_VMCS16_HOST_SS_SEL,
467 VMX_VMCS16_HOST_DS_SEL,
468 VMX_VMCS16_HOST_FS_SEL,
469 VMX_VMCS16_HOST_GS_SEL,
470 VMX_VMCS16_HOST_TR_SEL,
471
472 /* 64-bit control fields. */
473 VMX_VMCS64_CTRL_IO_BITMAP_A_FULL,
474 VMX_VMCS64_CTRL_IO_BITMAP_A_HIGH,
475 VMX_VMCS64_CTRL_IO_BITMAP_B_FULL,
476 VMX_VMCS64_CTRL_IO_BITMAP_B_HIGH,
477 VMX_VMCS64_CTRL_MSR_BITMAP_FULL,
478 VMX_VMCS64_CTRL_MSR_BITMAP_HIGH,
479 VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL,
480 VMX_VMCS64_CTRL_EXIT_MSR_STORE_HIGH,
481 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL,
482 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_HIGH,
483 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL,
484 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_HIGH,
485 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL,
486 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_HIGH,
487 VMX_VMCS64_CTRL_EXEC_PML_ADDR_FULL,
488 VMX_VMCS64_CTRL_EXEC_PML_ADDR_HIGH,
489 VMX_VMCS64_CTRL_TSC_OFFSET_FULL,
490 VMX_VMCS64_CTRL_TSC_OFFSET_HIGH,
491 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL,
492 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_HIGH,
493 VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL,
494 VMX_VMCS64_CTRL_APIC_ACCESSADDR_HIGH,
495 VMX_VMCS64_CTRL_POSTED_INTR_DESC_FULL,
496 VMX_VMCS64_CTRL_POSTED_INTR_DESC_HIGH,
497 VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL,
498 VMX_VMCS64_CTRL_VMFUNC_CTRLS_HIGH,
499 VMX_VMCS64_CTRL_EPTP_FULL,
500 VMX_VMCS64_CTRL_EPTP_HIGH,
501 VMX_VMCS64_CTRL_EOI_BITMAP_0_FULL,
502 VMX_VMCS64_CTRL_EOI_BITMAP_0_HIGH,
503 VMX_VMCS64_CTRL_EOI_BITMAP_1_FULL,
504 VMX_VMCS64_CTRL_EOI_BITMAP_1_HIGH,
505 VMX_VMCS64_CTRL_EOI_BITMAP_2_FULL,
506 VMX_VMCS64_CTRL_EOI_BITMAP_2_HIGH,
507 VMX_VMCS64_CTRL_EOI_BITMAP_3_FULL,
508 VMX_VMCS64_CTRL_EOI_BITMAP_3_HIGH,
509 VMX_VMCS64_CTRL_EPTP_LIST_FULL,
510 VMX_VMCS64_CTRL_EPTP_LIST_HIGH,
511 VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL,
512 VMX_VMCS64_CTRL_VMREAD_BITMAP_HIGH,
513 VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL,
514 VMX_VMCS64_CTRL_VMWRITE_BITMAP_HIGH,
515 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_FULL,
516 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_HIGH,
517 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_FULL,
518 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_HIGH,
519 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_FULL,
520 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_HIGH,
521 VMX_VMCS64_CTRL_TSC_MULTIPLIER_FULL,
522 VMX_VMCS64_CTRL_TSC_MULTIPLIER_HIGH,
523
524 /* 64-bit read-only data fields. */
525 VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL,
526 VMX_VMCS64_RO_GUEST_PHYS_ADDR_HIGH,
527
528 /* 64-bit guest-state fields. */
529 VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL,
530 VMX_VMCS64_GUEST_VMCS_LINK_PTR_HIGH,
531 VMX_VMCS64_GUEST_DEBUGCTL_FULL,
532 VMX_VMCS64_GUEST_DEBUGCTL_HIGH,
533 VMX_VMCS64_GUEST_PAT_FULL,
534 VMX_VMCS64_GUEST_PAT_HIGH,
535 VMX_VMCS64_GUEST_EFER_FULL,
536 VMX_VMCS64_GUEST_EFER_HIGH,
537 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL,
538 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_HIGH,
539 VMX_VMCS64_GUEST_PDPTE0_FULL,
540 VMX_VMCS64_GUEST_PDPTE0_HIGH,
541 VMX_VMCS64_GUEST_PDPTE1_FULL,
542 VMX_VMCS64_GUEST_PDPTE1_HIGH,
543 VMX_VMCS64_GUEST_PDPTE2_FULL,
544 VMX_VMCS64_GUEST_PDPTE2_HIGH,
545 VMX_VMCS64_GUEST_PDPTE3_FULL,
546 VMX_VMCS64_GUEST_PDPTE3_HIGH,
547 VMX_VMCS64_GUEST_BNDCFGS_FULL,
548 VMX_VMCS64_GUEST_BNDCFGS_HIGH,
549
550 /* 64-bit host-state fields. */
551 VMX_VMCS64_HOST_PAT_FULL,
552 VMX_VMCS64_HOST_PAT_HIGH,
553 VMX_VMCS64_HOST_EFER_FULL,
554 VMX_VMCS64_HOST_EFER_HIGH,
555 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL,
556 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_HIGH,
557
558 /* 32-bit control fields. */
559 VMX_VMCS32_CTRL_PIN_EXEC,
560 VMX_VMCS32_CTRL_PROC_EXEC,
561 VMX_VMCS32_CTRL_EXCEPTION_BITMAP,
562 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK,
563 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH,
564 VMX_VMCS32_CTRL_CR3_TARGET_COUNT,
565 VMX_VMCS32_CTRL_EXIT,
566 VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT,
567 VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT,
568 VMX_VMCS32_CTRL_ENTRY,
569 VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT,
570 VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO,
571 VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE,
572 VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH,
573 VMX_VMCS32_CTRL_TPR_THRESHOLD,
574 VMX_VMCS32_CTRL_PROC_EXEC2,
575 VMX_VMCS32_CTRL_PLE_GAP,
576 VMX_VMCS32_CTRL_PLE_WINDOW,
577
578 /* 32-bits read-only fields. */
579 VMX_VMCS32_RO_VM_INSTR_ERROR,
580 VMX_VMCS32_RO_EXIT_REASON,
581 VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO,
582 VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE,
583 VMX_VMCS32_RO_IDT_VECTORING_INFO,
584 VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE,
585 VMX_VMCS32_RO_EXIT_INSTR_LENGTH,
586 VMX_VMCS32_RO_EXIT_INSTR_INFO,
587
588 /* 32-bit guest-state fields. */
589 VMX_VMCS32_GUEST_ES_LIMIT,
590 VMX_VMCS32_GUEST_CS_LIMIT,
591 VMX_VMCS32_GUEST_SS_LIMIT,
592 VMX_VMCS32_GUEST_DS_LIMIT,
593 VMX_VMCS32_GUEST_FS_LIMIT,
594 VMX_VMCS32_GUEST_GS_LIMIT,
595 VMX_VMCS32_GUEST_LDTR_LIMIT,
596 VMX_VMCS32_GUEST_TR_LIMIT,
597 VMX_VMCS32_GUEST_GDTR_LIMIT,
598 VMX_VMCS32_GUEST_IDTR_LIMIT,
599 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
600 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
601 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
602 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
603 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
604 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS,
605 VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS,
606 VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS,
607 VMX_VMCS32_GUEST_INT_STATE,
608 VMX_VMCS32_GUEST_ACTIVITY_STATE,
609 VMX_VMCS32_GUEST_SMBASE,
610 VMX_VMCS32_GUEST_SYSENTER_CS,
611 VMX_VMCS32_PREEMPT_TIMER_VALUE,
612
613 /* 32-bit host-state fields. */
614 VMX_VMCS32_HOST_SYSENTER_CS,
615
616 /* Natural-width control fields. */
617 VMX_VMCS_CTRL_CR0_MASK,
618 VMX_VMCS_CTRL_CR4_MASK,
619 VMX_VMCS_CTRL_CR0_READ_SHADOW,
620 VMX_VMCS_CTRL_CR4_READ_SHADOW,
621 VMX_VMCS_CTRL_CR3_TARGET_VAL0,
622 VMX_VMCS_CTRL_CR3_TARGET_VAL1,
623 VMX_VMCS_CTRL_CR3_TARGET_VAL2,
624 VMX_VMCS_CTRL_CR3_TARGET_VAL3,
625
626 /* Natural-width read-only data fields. */
627 VMX_VMCS_RO_EXIT_QUALIFICATION,
628 VMX_VMCS_RO_IO_RCX,
629 VMX_VMCS_RO_IO_RSI,
630 VMX_VMCS_RO_IO_RDI,
631 VMX_VMCS_RO_IO_RIP,
632 VMX_VMCS_RO_GUEST_LINEAR_ADDR,
633
634 /* Natural-width guest-state field */
635 VMX_VMCS_GUEST_CR0,
636 VMX_VMCS_GUEST_CR3,
637 VMX_VMCS_GUEST_CR4,
638 VMX_VMCS_GUEST_ES_BASE,
639 VMX_VMCS_GUEST_CS_BASE,
640 VMX_VMCS_GUEST_SS_BASE,
641 VMX_VMCS_GUEST_DS_BASE,
642 VMX_VMCS_GUEST_FS_BASE,
643 VMX_VMCS_GUEST_GS_BASE,
644 VMX_VMCS_GUEST_LDTR_BASE,
645 VMX_VMCS_GUEST_TR_BASE,
646 VMX_VMCS_GUEST_GDTR_BASE,
647 VMX_VMCS_GUEST_IDTR_BASE,
648 VMX_VMCS_GUEST_DR7,
649 VMX_VMCS_GUEST_RSP,
650 VMX_VMCS_GUEST_RIP,
651 VMX_VMCS_GUEST_RFLAGS,
652 VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS,
653 VMX_VMCS_GUEST_SYSENTER_ESP,
654 VMX_VMCS_GUEST_SYSENTER_EIP,
655
656 /* Natural-width host-state fields */
657 VMX_VMCS_HOST_CR0,
658 VMX_VMCS_HOST_CR3,
659 VMX_VMCS_HOST_CR4,
660 VMX_VMCS_HOST_FS_BASE,
661 VMX_VMCS_HOST_GS_BASE,
662 VMX_VMCS_HOST_TR_BASE,
663 VMX_VMCS_HOST_GDTR_BASE,
664 VMX_VMCS_HOST_IDTR_BASE,
665 VMX_VMCS_HOST_SYSENTER_ESP,
666 VMX_VMCS_HOST_SYSENTER_EIP,
667 VMX_VMCS_HOST_RSP,
668 VMX_VMCS_HOST_RIP
669};
670#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
671
672#ifdef VMX_USE_CACHED_VMCS_ACCESSES
673static const uint32_t g_aVmcsCacheSegBase[] =
674{
675 VMX_VMCS_GUEST_ES_BASE_CACHE_IDX,
676 VMX_VMCS_GUEST_CS_BASE_CACHE_IDX,
677 VMX_VMCS_GUEST_SS_BASE_CACHE_IDX,
678 VMX_VMCS_GUEST_DS_BASE_CACHE_IDX,
679 VMX_VMCS_GUEST_FS_BASE_CACHE_IDX,
680 VMX_VMCS_GUEST_GS_BASE_CACHE_IDX
681};
682AssertCompile(RT_ELEMENTS(g_aVmcsCacheSegBase) == X86_SREG_COUNT);
683#endif
684static const uint32_t g_aVmcsSegBase[] =
685{
686 VMX_VMCS_GUEST_ES_BASE,
687 VMX_VMCS_GUEST_CS_BASE,
688 VMX_VMCS_GUEST_SS_BASE,
689 VMX_VMCS_GUEST_DS_BASE,
690 VMX_VMCS_GUEST_FS_BASE,
691 VMX_VMCS_GUEST_GS_BASE
692};
693static const uint32_t g_aVmcsSegSel[] =
694{
695 VMX_VMCS16_GUEST_ES_SEL,
696 VMX_VMCS16_GUEST_CS_SEL,
697 VMX_VMCS16_GUEST_SS_SEL,
698 VMX_VMCS16_GUEST_DS_SEL,
699 VMX_VMCS16_GUEST_FS_SEL,
700 VMX_VMCS16_GUEST_GS_SEL
701};
702static const uint32_t g_aVmcsSegLimit[] =
703{
704 VMX_VMCS32_GUEST_ES_LIMIT,
705 VMX_VMCS32_GUEST_CS_LIMIT,
706 VMX_VMCS32_GUEST_SS_LIMIT,
707 VMX_VMCS32_GUEST_DS_LIMIT,
708 VMX_VMCS32_GUEST_FS_LIMIT,
709 VMX_VMCS32_GUEST_GS_LIMIT
710};
711static const uint32_t g_aVmcsSegAttr[] =
712{
713 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
714 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
715 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
716 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
717 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
718 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS
719};
720AssertCompile(RT_ELEMENTS(g_aVmcsSegSel) == X86_SREG_COUNT);
721AssertCompile(RT_ELEMENTS(g_aVmcsSegLimit) == X86_SREG_COUNT);
722AssertCompile(RT_ELEMENTS(g_aVmcsSegBase) == X86_SREG_COUNT);
723AssertCompile(RT_ELEMENTS(g_aVmcsSegAttr) == X86_SREG_COUNT);
724
725#ifdef HMVMX_USE_FUNCTION_TABLE
726/**
727 * VMX_EXIT dispatch table.
728 */
729static const PFNVMXEXITHANDLER g_apfnVMExitHandlers[VMX_EXIT_MAX + 1] =
730{
731 /* 0 VMX_EXIT_XCPT_OR_NMI */ hmR0VmxExitXcptOrNmi,
732 /* 1 VMX_EXIT_EXT_INT */ hmR0VmxExitExtInt,
733 /* 2 VMX_EXIT_TRIPLE_FAULT */ hmR0VmxExitTripleFault,
734 /* 3 VMX_EXIT_INIT_SIGNAL */ hmR0VmxExitErrUnexpected,
735 /* 4 VMX_EXIT_SIPI */ hmR0VmxExitErrUnexpected,
736 /* 5 VMX_EXIT_IO_SMI */ hmR0VmxExitErrUnexpected,
737 /* 6 VMX_EXIT_SMI */ hmR0VmxExitErrUnexpected,
738 /* 7 VMX_EXIT_INT_WINDOW */ hmR0VmxExitIntWindow,
739 /* 8 VMX_EXIT_NMI_WINDOW */ hmR0VmxExitNmiWindow,
740 /* 9 VMX_EXIT_TASK_SWITCH */ hmR0VmxExitTaskSwitch,
741 /* 10 VMX_EXIT_CPUID */ hmR0VmxExitCpuid,
742 /* 11 VMX_EXIT_GETSEC */ hmR0VmxExitGetsec,
743 /* 12 VMX_EXIT_HLT */ hmR0VmxExitHlt,
744 /* 13 VMX_EXIT_INVD */ hmR0VmxExitInvd,
745 /* 14 VMX_EXIT_INVLPG */ hmR0VmxExitInvlpg,
746 /* 15 VMX_EXIT_RDPMC */ hmR0VmxExitRdpmc,
747 /* 16 VMX_EXIT_RDTSC */ hmR0VmxExitRdtsc,
748 /* 17 VMX_EXIT_RSM */ hmR0VmxExitErrUnexpected,
749 /* 18 VMX_EXIT_VMCALL */ hmR0VmxExitVmcall,
750#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
751 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitVmclear,
752 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitVmlaunch,
753 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitVmptrld,
754 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitVmptrst,
755 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitVmread,
756 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitVmresume,
757 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitVmwrite,
758 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitVmxoff,
759 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitVmxon,
760#else
761 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitSetPendingXcptUD,
762 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitSetPendingXcptUD,
763 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitSetPendingXcptUD,
764 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitSetPendingXcptUD,
765 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitSetPendingXcptUD,
766 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitSetPendingXcptUD,
767 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitSetPendingXcptUD,
768 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitSetPendingXcptUD,
769 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitSetPendingXcptUD,
770#endif
771 /* 28 VMX_EXIT_MOV_CRX */ hmR0VmxExitMovCRx,
772 /* 29 VMX_EXIT_MOV_DRX */ hmR0VmxExitMovDRx,
773 /* 30 VMX_EXIT_IO_INSTR */ hmR0VmxExitIoInstr,
774 /* 31 VMX_EXIT_RDMSR */ hmR0VmxExitRdmsr,
775 /* 32 VMX_EXIT_WRMSR */ hmR0VmxExitWrmsr,
776 /* 33 VMX_EXIT_ERR_INVALID_GUEST_STATE */ hmR0VmxExitErrInvalidGuestState,
777 /* 34 VMX_EXIT_ERR_MSR_LOAD */ hmR0VmxExitErrUnexpected,
778 /* 35 UNDEFINED */ hmR0VmxExitErrUnexpected,
779 /* 36 VMX_EXIT_MWAIT */ hmR0VmxExitMwait,
780 /* 37 VMX_EXIT_MTF */ hmR0VmxExitMtf,
781 /* 38 UNDEFINED */ hmR0VmxExitErrUnexpected,
782 /* 39 VMX_EXIT_MONITOR */ hmR0VmxExitMonitor,
783 /* 40 VMX_EXIT_PAUSE */ hmR0VmxExitPause,
784 /* 41 VMX_EXIT_ERR_MACHINE_CHECK */ hmR0VmxExitErrUnexpected,
785 /* 42 UNDEFINED */ hmR0VmxExitErrUnexpected,
786 /* 43 VMX_EXIT_TPR_BELOW_THRESHOLD */ hmR0VmxExitTprBelowThreshold,
787 /* 44 VMX_EXIT_APIC_ACCESS */ hmR0VmxExitApicAccess,
788 /* 45 VMX_EXIT_VIRTUALIZED_EOI */ hmR0VmxExitErrUnexpected,
789 /* 46 VMX_EXIT_GDTR_IDTR_ACCESS */ hmR0VmxExitErrUnexpected,
790 /* 47 VMX_EXIT_LDTR_TR_ACCESS */ hmR0VmxExitErrUnexpected,
791 /* 48 VMX_EXIT_EPT_VIOLATION */ hmR0VmxExitEptViolation,
792 /* 49 VMX_EXIT_EPT_MISCONFIG */ hmR0VmxExitEptMisconfig,
793 /* 50 VMX_EXIT_INVEPT */ hmR0VmxExitSetPendingXcptUD,
794 /* 51 VMX_EXIT_RDTSCP */ hmR0VmxExitRdtscp,
795 /* 52 VMX_EXIT_PREEMPT_TIMER */ hmR0VmxExitPreemptTimer,
796#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
797 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitInvvpid,
798#else
799 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitSetPendingXcptUD,
800#endif
801 /* 54 VMX_EXIT_WBINVD */ hmR0VmxExitWbinvd,
802 /* 55 VMX_EXIT_XSETBV */ hmR0VmxExitXsetbv,
803 /* 56 VMX_EXIT_APIC_WRITE */ hmR0VmxExitErrUnexpected,
804 /* 57 VMX_EXIT_RDRAND */ hmR0VmxExitErrUnexpected,
805 /* 58 VMX_EXIT_INVPCID */ hmR0VmxExitInvpcid,
806 /* 59 VMX_EXIT_VMFUNC */ hmR0VmxExitErrUnexpected,
807 /* 60 VMX_EXIT_ENCLS */ hmR0VmxExitErrUnexpected,
808 /* 61 VMX_EXIT_RDSEED */ hmR0VmxExitErrUnexpected,
809 /* 62 VMX_EXIT_PML_FULL */ hmR0VmxExitErrUnexpected,
810 /* 63 VMX_EXIT_XSAVES */ hmR0VmxExitErrUnexpected,
811 /* 64 VMX_EXIT_XRSTORS */ hmR0VmxExitErrUnexpected,
812 /* 65 UNDEFINED */ hmR0VmxExitErrUnexpected,
813 /* 66 VMX_EXIT_SPP_EVENT */ hmR0VmxExitErrUnexpected,
814 /* 67 VMX_EXIT_UMWAIT */ hmR0VmxExitErrUnexpected,
815 /* 68 VMX_EXIT_TPAUSE */ hmR0VmxExitErrUnexpected,
816};
817#endif /* HMVMX_USE_FUNCTION_TABLE */
818
819#if defined(VBOX_STRICT) && defined(LOG_ENABLED)
820static const char * const g_apszVmxInstrErrors[HMVMX_INSTR_ERROR_MAX + 1] =
821{
822 /* 0 */ "(Not Used)",
823 /* 1 */ "VMCALL executed in VMX root operation.",
824 /* 2 */ "VMCLEAR with invalid physical address.",
825 /* 3 */ "VMCLEAR with VMXON pointer.",
826 /* 4 */ "VMLAUNCH with non-clear VMCS.",
827 /* 5 */ "VMRESUME with non-launched VMCS.",
828 /* 6 */ "VMRESUME after VMXOFF",
829 /* 7 */ "VM-entry with invalid control fields.",
830 /* 8 */ "VM-entry with invalid host state fields.",
831 /* 9 */ "VMPTRLD with invalid physical address.",
832 /* 10 */ "VMPTRLD with VMXON pointer.",
833 /* 11 */ "VMPTRLD with incorrect revision identifier.",
834 /* 12 */ "VMREAD/VMWRITE from/to unsupported VMCS component.",
835 /* 13 */ "VMWRITE to read-only VMCS component.",
836 /* 14 */ "(Not Used)",
837 /* 15 */ "VMXON executed in VMX root operation.",
838 /* 16 */ "VM-entry with invalid executive-VMCS pointer.",
839 /* 17 */ "VM-entry with non-launched executing VMCS.",
840 /* 18 */ "VM-entry with executive-VMCS pointer not VMXON pointer.",
841 /* 19 */ "VMCALL with non-clear VMCS.",
842 /* 20 */ "VMCALL with invalid VM-exit control fields.",
843 /* 21 */ "(Not Used)",
844 /* 22 */ "VMCALL with incorrect MSEG revision identifier.",
845 /* 23 */ "VMXOFF under dual monitor treatment of SMIs and SMM.",
846 /* 24 */ "VMCALL with invalid SMM-monitor features.",
847 /* 25 */ "VM-entry with invalid VM-execution control fields in executive VMCS.",
848 /* 26 */ "VM-entry with events blocked by MOV SS.",
849 /* 27 */ "(Not Used)",
850 /* 28 */ "Invalid operand to INVEPT/INVVPID."
851};
852#endif /* VBOX_STRICT && LOG_ENABLED */
853
854
855/**
856 * Get the CR0 guest/host mask that does not change through the lifetime of a VM.
857 *
858 * Any bit set in this mask is owned by the host/hypervisor and would cause a
859 * VM-exit when modified by the guest.
860 *
861 * @returns The static CR0 guest/host mask.
862 * @param pVCpu The cross context virtual CPU structure.
863 */
864DECL_FORCE_INLINE(uint64_t) hmR0VmxGetFixedCr0Mask(PCVMCPU pVCpu)
865{
866 /*
867 * Modifications to CR0 bits that VT-x ignores saving/restoring (CD, ET, NW) and
868 * to CR0 bits that we require for shadow paging (PG) by the guest must cause VM-exits.
869 */
870 /** @todo Avoid intercepting CR0.PE with unrestricted guest execution. Fix PGM
871 * enmGuestMode to be in-sync with the current mode. See @bugref{6398}
872 * and @bugref{6944}. */
873 PVM pVM = pVCpu->CTX_SUFF(pVM);
874 return ( X86_CR0_PE
875 | X86_CR0_NE
876 | (pVM->hm.s.fNestedPaging ? 0 : X86_CR0_WP)
877 | X86_CR0_PG
878 | X86_CR0_ET /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.ET */
879 | X86_CR0_CD /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.CD */
880 | X86_CR0_NW); /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.NW */
881}
882
883
884/**
885 * Gets the CR4 guest/host mask that does not change through the lifetime of a VM.
886 *
887 * Any bit set in this mask is owned by the host/hypervisor and would cause a
888 * VM-exit when modified by the guest.
889 *
890 * @returns The static CR4 guest/host mask.
891 * @param pVCpu The cross context virtual CPU structure.
892 */
893DECL_FORCE_INLINE(uint64_t) hmR0VmxGetFixedCr4Mask(PCVMCPU pVCpu)
894{
895 /*
896 * We need to look at the host features here (for e.g. OSXSAVE, PCID) because
897 * these bits are reserved on hardware that does not support them. Since the
898 * CPU cannot refer to our virtual CPUID, we need to intercept CR4 changes to
899 * these bits and handle it depending on whether we expose them to the guest.
900 */
901 PVM pVM = pVCpu->CTX_SUFF(pVM);
902 bool const fXSaveRstor = pVM->cpum.ro.HostFeatures.fXSaveRstor;
903 bool const fPcid = pVM->cpum.ro.HostFeatures.fPcid;
904 return ( X86_CR4_VMXE
905 | X86_CR4_VME
906 | X86_CR4_PAE
907 | X86_CR4_PGE
908 | X86_CR4_PSE
909 | (fXSaveRstor ? X86_CR4_OSXSAVE : 0)
910 | (fPcid ? X86_CR4_PCIDE : 0));
911}
912
913
914/**
915 * Returns whether the the VM-exit MSR-store area differs from the VM-exit MSR-load
916 * area.
917 *
918 * @returns @c true if it's different, @c false otherwise.
919 * @param pVmcsInfo The VMCS info. object.
920 */
921DECL_FORCE_INLINE(bool) hmR0VmxIsSeparateExitMsrStoreAreaVmcs(PCVMXVMCSINFO pVmcsInfo)
922{
923 return RT_BOOL( pVmcsInfo->pvGuestMsrStore != pVmcsInfo->pvGuestMsrLoad
924 && pVmcsInfo->pvGuestMsrStore);
925}
926
927
928/**
929 * Sets the given Processor-based VM-execution controls.
930 *
931 * @param pVmxTransient The VMX-transient structure.
932 * @param uProcCtls The Processor-based VM-execution controls to set.
933 */
934static void hmR0VmxSetProcCtlsVmcs(PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
935{
936 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
937 if ((pVmcsInfo->u32ProcCtls & uProcCtls) != uProcCtls)
938 {
939 pVmcsInfo->u32ProcCtls |= uProcCtls;
940 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
941 AssertRC(rc);
942 }
943}
944
945
946/**
947 * Removes the given Processor-based VM-execution controls.
948 *
949 * @param pVCpu The cross context virtual CPU structure.
950 * @param pVmxTransient The VMX-transient structure.
951 * @param uProcCtls The Processor-based VM-execution controls to remove.
952 *
953 * @remarks When executing a nested-guest, this will not remove any of the specified
954 * controls if the guest hypervisor has set any one of them.
955 */
956static void hmR0VmxRemoveProcCtlsVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
957{
958 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
959 if (pVmcsInfo->u32ProcCtls & uProcCtls)
960 {
961#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
962 bool const fRemoveCtls = !pVmxTransient->fIsNestedGuest
963 ? true
964 : !CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uProcCtls);
965#else
966 NOREF(pVCpu);
967 bool const fRemoveCtls = true;
968#endif
969 if (fRemoveCtls)
970 {
971 pVmcsInfo->u32ProcCtls &= ~uProcCtls;
972 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
973 AssertRC(rc);
974 }
975 }
976}
977
978
979/**
980 * Sets the TSC offset for the current VMCS.
981 *
982 * @param pVCpu The cross context virtual CPU structure.
983 * @param uTscOffset The TSC offset to set.
984 * @param pVmcsInfo The VMCS info. object.
985 */
986static void hmR0VmxSetTscOffsetVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t uTscOffset)
987{
988 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
989 if (pVmcsInfo->u64TscOffset != uTscOffset)
990 {
991 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, uTscOffset);
992 AssertRC(rc);
993 pVmcsInfo->u64TscOffset = uTscOffset;
994 }
995}
996
997
998/**
999 * Adds one or more exceptions to the exception bitmap and commits it to the current
1000 * VMCS.
1001 *
1002 * @returns VBox status code.
1003 * @param pVmxTransient The VMX-transient structure.
1004 * @param uXcptMask The exception(s) to add.
1005 */
1006static int hmR0VmxAddXcptInterceptMask(PVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1007{
1008 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1009 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
1010 if ((uXcptBitmap & uXcptMask) != uXcptMask)
1011 {
1012 uXcptBitmap |= uXcptMask;
1013 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
1014 AssertRCReturn(rc, rc);
1015 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
1016 }
1017 return VINF_SUCCESS;
1018}
1019
1020
1021/**
1022 * Adds an exception to the exception bitmap and commits it to the current VMCS.
1023 *
1024 * @returns VBox status code.
1025 * @param pVmxTransient The VMX-transient structure.
1026 * @param uXcpt The exception to add.
1027 */
1028static int hmR0VmxAddXcptIntercept(PVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1029{
1030 Assert(uXcpt <= X86_XCPT_LAST);
1031 return hmR0VmxAddXcptInterceptMask(pVmxTransient, RT_BIT_32(uXcpt));
1032}
1033
1034
1035/**
1036 * Remove one or more exceptions from the exception bitmap and commits it to the
1037 * current VMCS.
1038 *
1039 * This takes care of not removing the exception intercept if a nested-guest
1040 * requires the exception to be intercepted.
1041 *
1042 * @returns VBox status code.
1043 * @param pVCpu The cross context virtual CPU structure.
1044 * @param pVmxTransient The VMX-transient structure.
1045 * @param uXcptMask The exception(s) to remove.
1046 */
1047static int hmR0VmxRemoveXcptInterceptMask(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1048{
1049 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1050 uint32_t u32XcptBitmap = pVmcsInfo->u32XcptBitmap;
1051 if (u32XcptBitmap & uXcptMask)
1052 {
1053#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1054 if (!pVmxTransient->fIsNestedGuest)
1055 { /* likely */ }
1056 else
1057 {
1058 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
1059 uXcptMask &= ~pVmcsNstGst->u32XcptBitmap;
1060 }
1061#endif
1062#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
1063 uXcptMask &= ~( RT_BIT(X86_XCPT_BP)
1064 | RT_BIT(X86_XCPT_DE)
1065 | RT_BIT(X86_XCPT_NM)
1066 | RT_BIT(X86_XCPT_TS)
1067 | RT_BIT(X86_XCPT_UD)
1068 | RT_BIT(X86_XCPT_NP)
1069 | RT_BIT(X86_XCPT_SS)
1070 | RT_BIT(X86_XCPT_GP)
1071 | RT_BIT(X86_XCPT_PF)
1072 | RT_BIT(X86_XCPT_MF));
1073#elif defined(HMVMX_ALWAYS_TRAP_PF)
1074 uXcptMask &= ~RT_BIT(X86_XCPT_PF);
1075#endif
1076 if (uXcptMask)
1077 {
1078 /* Validate we are not removing any essential exception intercepts. */
1079 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || !(uXcptMask & RT_BIT(X86_XCPT_PF))); RT_NOREF(pVCpu);
1080 Assert(!(uXcptMask & RT_BIT(X86_XCPT_DB)));
1081 Assert(!(uXcptMask & RT_BIT(X86_XCPT_AC)));
1082
1083 /* Remove it from the exception bitmap. */
1084 u32XcptBitmap &= ~uXcptMask;
1085
1086 /* Commit and update the cache if necessary. */
1087 if (pVmcsInfo->u32XcptBitmap != u32XcptBitmap)
1088 {
1089 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
1090 AssertRCReturn(rc, rc);
1091 pVmcsInfo->u32XcptBitmap = u32XcptBitmap;
1092 }
1093 }
1094 }
1095 return VINF_SUCCESS;
1096}
1097
1098
1099/**
1100 * Remove an exceptions from the exception bitmap and commits it to the current
1101 * VMCS.
1102 *
1103 * @returns VBox status code.
1104 * @param pVCpu The cross context virtual CPU structure.
1105 * @param pVmxTransient The VMX-transient structure.
1106 * @param uXcpt The exception to remove.
1107 */
1108static int hmR0VmxRemoveXcptIntercept(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1109{
1110 return hmR0VmxRemoveXcptInterceptMask(pVCpu, pVmxTransient, RT_BIT(uXcpt));
1111}
1112
1113
1114/**
1115 * Loads the VMCS specified by the VMCS info. object.
1116 *
1117 * @returns VBox status code.
1118 * @param pVmcsInfo The VMCS info. object.
1119 *
1120 * @remarks Can be called with interrupts disabled.
1121 */
1122static int hmR0VmxLoadVmcs(PVMXVMCSINFO pVmcsInfo)
1123{
1124 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1125 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1126
1127 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysVmcs);
1128 if (RT_SUCCESS(rc))
1129 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1130 return rc;
1131}
1132
1133
1134/**
1135 * Clears the VMCS specified by the VMCS info. object.
1136 *
1137 * @returns VBox status code.
1138 * @param pVmcsInfo The VMCS info. object.
1139 *
1140 * @remarks Can be called with interrupts disabled.
1141 */
1142static int hmR0VmxClearVmcs(PVMXVMCSINFO pVmcsInfo)
1143{
1144 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1145 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1146
1147 int rc = VMXClearVmcs(pVmcsInfo->HCPhysVmcs);
1148 if (RT_SUCCESS(rc))
1149 pVmcsInfo->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1150 return rc;
1151}
1152
1153
1154#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1155/**
1156 * Loads the shadow VMCS specified by the VMCS info. object.
1157 *
1158 * @returns VBox status code.
1159 * @param pVmcsInfo The VMCS info. object.
1160 *
1161 * @remarks Can be called with interrupts disabled.
1162 */
1163static int hmR0VmxLoadShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1164{
1165 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1166 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1167
1168 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysShadowVmcs);
1169 if (RT_SUCCESS(rc))
1170 pVmcsInfo->fShadowVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1171 return rc;
1172}
1173
1174
1175/**
1176 * Clears the shadow VMCS specified by the VMCS info. object.
1177 *
1178 * @returns VBox status code.
1179 * @param pVmcsInfo The VMCS info. object.
1180 *
1181 * @remarks Can be called with interrupts disabled.
1182 */
1183static int hmR0VmxClearShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1184{
1185 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1186 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1187
1188 int rc = VMXClearVmcs(pVmcsInfo->HCPhysShadowVmcs);
1189 if (RT_SUCCESS(rc))
1190 pVmcsInfo->fShadowVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1191 return rc;
1192}
1193
1194
1195/**
1196 * Switches from and to the specified VMCSes.
1197 *
1198 * @returns VBox status code.
1199 * @param pVmcsInfoFrom The VMCS info. object we are switching from.
1200 * @param pVmcsInfoTo The VMCS info. object we are switching to.
1201 *
1202 * @remarks Called with interrupts disabled.
1203 */
1204static int hmR0VmxSwitchVmcs(PVMXVMCSINFO pVmcsInfoFrom, PVMXVMCSINFO pVmcsInfoTo)
1205{
1206 /*
1207 * Clear the VMCS we are switching out if it has not already been cleared.
1208 * This will sync any CPU internal data back to the VMCS.
1209 */
1210 if (pVmcsInfoFrom->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1211 {
1212 int rc = hmR0VmxClearVmcs(pVmcsInfoFrom);
1213 if (RT_SUCCESS(rc))
1214 {
1215 /*
1216 * The shadow VMCS, if any, would not be active at this point since we
1217 * would have cleared it while importing the virtual hardware-virtualization
1218 * state as part the VMLAUNCH/VMRESUME VM-exit. Hence, there's no need to
1219 * clear the shadow VMCS here, just assert for safety.
1220 */
1221 Assert(!pVmcsInfoFrom->pvShadowVmcs || pVmcsInfoFrom->fShadowVmcsState == VMX_V_VMCS_LAUNCH_STATE_CLEAR);
1222 }
1223 else
1224 return rc;
1225 }
1226
1227 /*
1228 * Clear the VMCS we are switching to if it has not already been cleared.
1229 * This will initialize the VMCS launch state to "clear" required for loading it.
1230 *
1231 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
1232 */
1233 if (pVmcsInfoTo->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1234 {
1235 int rc = hmR0VmxClearVmcs(pVmcsInfoTo);
1236 if (RT_SUCCESS(rc))
1237 { /* likely */ }
1238 else
1239 return rc;
1240 }
1241
1242 /*
1243 * Finally, load the VMCS we are switching to.
1244 */
1245 return hmR0VmxLoadVmcs(pVmcsInfoTo);
1246}
1247
1248
1249/**
1250 * Switches between the guest VMCS and the nested-guest VMCS as specified by the
1251 * caller.
1252 *
1253 * @returns VBox status code.
1254 * @param pVCpu The cross context virtual CPU structure.
1255 * @param fSwitchToNstGstVmcs Whether to switch to the nested-guest VMCS (pass
1256 * true) or guest VMCS (pass false).
1257 */
1258static int hmR0VmxSwitchToGstOrNstGstVmcs(PVMCPU pVCpu, bool fSwitchToNstGstVmcs)
1259{
1260 /* Ensure we have synced everything from the guest-CPU context to the VMCS before switching. */
1261 HMVMX_CPUMCTX_ASSERT(pVCpu, HMVMX_CPUMCTX_EXTRN_ALL);
1262
1263 PVMXVMCSINFO pVmcsInfoFrom;
1264 PVMXVMCSINFO pVmcsInfoTo;
1265 if (fSwitchToNstGstVmcs)
1266 {
1267 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfo;
1268 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1269 }
1270 else
1271 {
1272 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1273 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfo;
1274 }
1275
1276 /*
1277 * Disable interrupts to prevent being preempted while we switch the current VMCS as the
1278 * preemption hook code path acquires the current VMCS.
1279 */
1280 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1281
1282 int rc = hmR0VmxSwitchVmcs(pVmcsInfoFrom, pVmcsInfoTo);
1283 if (RT_SUCCESS(rc))
1284 {
1285 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fSwitchToNstGstVmcs;
1286
1287 /*
1288 * If we are switching to a VMCS that was executed on a different host CPU or was
1289 * never executed before, flag that we need to export the host state before executing
1290 * guest/nested-guest code using hardware-assisted VMX.
1291 *
1292 * This could probably be done in a preemptible context since the preemption hook
1293 * will flag the necessary change in host context. However, since preemption is
1294 * already disabled and to avoid making assumptions about host specific code in
1295 * RTMpCpuId when called with preemption enabled, we'll do this while preemption is
1296 * disabled.
1297 */
1298 if (pVmcsInfoTo->idHostCpu == RTMpCpuId())
1299 { /* likely */ }
1300 else
1301 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE);
1302
1303 ASMSetFlags(fEFlags);
1304
1305 /*
1306 * We use a different VM-exit MSR-store areas for the guest and nested-guest. Hence,
1307 * flag that we need to update the host MSR values there. Even if we decide in the
1308 * future to share the VM-exit MSR-store area page between the guest and nested-guest,
1309 * if its content differs, we would have to update the host MSRs anyway.
1310 */
1311 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
1312 }
1313 else
1314 ASMSetFlags(fEFlags);
1315 return rc;
1316}
1317#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
1318
1319
1320/**
1321 * Updates the VM's last error record.
1322 *
1323 * If there was a VMX instruction error, reads the error data from the VMCS and
1324 * updates VCPU's last error record as well.
1325 *
1326 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
1327 * Can be NULL if @a rc is not VERR_VMX_UNABLE_TO_START_VM or
1328 * VERR_VMX_INVALID_VMCS_FIELD.
1329 * @param rc The error code.
1330 */
1331static void hmR0VmxUpdateErrorRecord(PVMCPU pVCpu, int rc)
1332{
1333 if ( rc == VERR_VMX_INVALID_VMCS_FIELD
1334 || rc == VERR_VMX_UNABLE_TO_START_VM)
1335 {
1336 AssertPtrReturnVoid(pVCpu);
1337 VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
1338 }
1339 pVCpu->CTX_SUFF(pVM)->hm.s.rcInit = rc;
1340}
1341
1342
1343#ifdef VBOX_STRICT
1344/**
1345 * Reads the VM-entry interruption-information field from the VMCS into the VMX
1346 * transient structure.
1347 *
1348 * @returns VBox status code.
1349 * @param pVmxTransient The VMX-transient structure.
1350 *
1351 * @remarks No-long-jump zone!!!
1352 */
1353DECLINLINE(int) hmR0VmxReadEntryIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1354{
1355 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &pVmxTransient->uEntryIntInfo);
1356 AssertRCReturn(rc, rc);
1357 return VINF_SUCCESS;
1358}
1359
1360
1361/**
1362 * Reads the VM-entry exception error code field from the VMCS into
1363 * the VMX transient structure.
1364 *
1365 * @returns VBox status code.
1366 * @param pVmxTransient The VMX-transient structure.
1367 *
1368 * @remarks No-long-jump zone!!!
1369 */
1370DECLINLINE(int) hmR0VmxReadEntryXcptErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1371{
1372 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &pVmxTransient->uEntryXcptErrorCode);
1373 AssertRCReturn(rc, rc);
1374 return VINF_SUCCESS;
1375}
1376
1377
1378/**
1379 * Reads the VM-entry exception error code field from the VMCS into
1380 * the VMX transient structure.
1381 *
1382 * @returns VBox status code.
1383 * @param pVmxTransient The VMX-transient structure.
1384 *
1385 * @remarks No-long-jump zone!!!
1386 */
1387DECLINLINE(int) hmR0VmxReadEntryInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1388{
1389 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &pVmxTransient->cbEntryInstr);
1390 AssertRCReturn(rc, rc);
1391 return VINF_SUCCESS;
1392}
1393#endif /* VBOX_STRICT */
1394
1395
1396/**
1397 * Reads the VM-exit interruption-information field from the VMCS into the VMX
1398 * transient structure.
1399 *
1400 * @returns VBox status code.
1401 * @param pVmxTransient The VMX-transient structure.
1402 */
1403DECLINLINE(int) hmR0VmxReadExitIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1404{
1405 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_INFO))
1406 {
1407 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1408 AssertRCReturn(rc,rc);
1409 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_INFO;
1410 }
1411 return VINF_SUCCESS;
1412}
1413
1414
1415/**
1416 * Reads the VM-exit interruption error code from the VMCS into the VMX
1417 * transient structure.
1418 *
1419 * @returns VBox status code.
1420 * @param pVmxTransient The VMX-transient structure.
1421 */
1422DECLINLINE(int) hmR0VmxReadExitIntErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1423{
1424 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE))
1425 {
1426 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1427 AssertRCReturn(rc, rc);
1428 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE;
1429 }
1430 return VINF_SUCCESS;
1431}
1432
1433
1434/**
1435 * Reads the VM-exit instruction length field from the VMCS into the VMX
1436 * transient structure.
1437 *
1438 * @returns VBox status code.
1439 * @param pVmxTransient The VMX-transient structure.
1440 */
1441DECLINLINE(int) hmR0VmxReadExitInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1442{
1443 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_LEN))
1444 {
1445 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbInstr);
1446 AssertRCReturn(rc, rc);
1447 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_LEN;
1448 }
1449 return VINF_SUCCESS;
1450}
1451
1452
1453/**
1454 * Reads the VM-exit instruction-information field from the VMCS into
1455 * the VMX transient structure.
1456 *
1457 * @returns VBox status code.
1458 * @param pVmxTransient The VMX-transient structure.
1459 */
1460DECLINLINE(int) hmR0VmxReadExitInstrInfoVmcs(PVMXTRANSIENT pVmxTransient)
1461{
1462 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_INFO))
1463 {
1464 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1465 AssertRCReturn(rc, rc);
1466 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_INFO;
1467 }
1468 return VINF_SUCCESS;
1469}
1470
1471
1472/**
1473 * Reads the Exit Qualification from the VMCS into the VMX transient structure.
1474 *
1475 * @returns VBox status code.
1476 * @param pVCpu The cross context virtual CPU structure of the
1477 * calling EMT. (Required for the VMCS cache case.)
1478 * @param pVmxTransient The VMX-transient structure.
1479 */
1480DECLINLINE(int) hmR0VmxReadExitQualVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
1481{
1482 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_QUALIFICATION))
1483 {
1484 int rc = VMXReadVmcsGstN(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual); NOREF(pVCpu);
1485 AssertRCReturn(rc, rc);
1486 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION;
1487 }
1488 return VINF_SUCCESS;
1489}
1490
1491
1492/**
1493 * Reads the Guest-linear address from the VMCS into the VMX transient structure.
1494 *
1495 * @returns VBox status code.
1496 * @param pVCpu The cross context virtual CPU structure of the
1497 * calling EMT. (Required for the VMCS cache case.)
1498 * @param pVmxTransient The VMX-transient structure.
1499 */
1500DECLINLINE(int) hmR0VmxReadGuestLinearAddrVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
1501{
1502 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_LINEAR_ADDR))
1503 {
1504 int rc = VMXReadVmcsGstN(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr); NOREF(pVCpu);
1505 AssertRCReturn(rc, rc);
1506 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_LINEAR_ADDR;
1507 }
1508 return VINF_SUCCESS;
1509}
1510
1511
1512/**
1513 * Reads the Guest-physical address from the VMCS into the VMX transient structure.
1514 *
1515 * @returns VBox status code.
1516 * @param pVCpu The cross context virtual CPU structure of the
1517 * calling EMT. (Required for the VMCS cache case.)
1518 * @param pVmxTransient The VMX-transient structure.
1519 */
1520DECLINLINE(int) hmR0VmxReadGuestPhysicalAddrVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
1521{
1522 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PHYSICAL_ADDR))
1523 {
1524 int rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr); NOREF(pVCpu);
1525 AssertRCReturn(rc, rc);
1526 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PHYSICAL_ADDR;
1527 }
1528 return VINF_SUCCESS;
1529}
1530
1531
1532/**
1533 * Reads the IDT-vectoring information field from the VMCS into the VMX
1534 * transient structure.
1535 *
1536 * @returns VBox status code.
1537 * @param pVmxTransient The VMX-transient structure.
1538 *
1539 * @remarks No-long-jump zone!!!
1540 */
1541DECLINLINE(int) hmR0VmxReadIdtVectoringInfoVmcs(PVMXTRANSIENT pVmxTransient)
1542{
1543 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_INFO))
1544 {
1545 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1546 AssertRCReturn(rc, rc);
1547 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_INFO;
1548 }
1549 return VINF_SUCCESS;
1550}
1551
1552
1553/**
1554 * Reads the IDT-vectoring error code from the VMCS into the VMX
1555 * transient structure.
1556 *
1557 * @returns VBox status code.
1558 * @param pVmxTransient The VMX-transient structure.
1559 */
1560DECLINLINE(int) hmR0VmxReadIdtVectoringErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1561{
1562 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_ERROR_CODE))
1563 {
1564 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1565 AssertRCReturn(rc, rc);
1566 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_ERROR_CODE;
1567 }
1568 return VINF_SUCCESS;
1569}
1570
1571#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
1572/**
1573 * Reads all relevant read-only VMCS fields into the VMX transient structure.
1574 *
1575 * @returns VBox status code.
1576 * @param pVCpu The cross context virtual CPU structure of the
1577 * calling EMT. (Required for the VMCS cache case.)
1578 * @param pVmxTransient The VMX-transient structure.
1579 */
1580static int hmR0VmxReadAllRoFieldsVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
1581{
1582 NOREF(pVCpu); /* Used implicitly by VMXReadVmcsGstN on 32-bit hosts. */
1583 int rc = VMXReadVmcsGstN(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1584 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbInstr);
1585 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1586 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1587 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1588 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1589 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1590 rc |= VMXReadVmcsGstN(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1591 rc |= VMXReadVmcsGstN(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1592 AssertRCReturn(rc, rc);
1593 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION
1594 | HMVMX_READ_EXIT_INSTR_LEN
1595 | HMVMX_READ_EXIT_INSTR_INFO
1596 | HMVMX_READ_IDT_VECTORING_INFO
1597 | HMVMX_READ_IDT_VECTORING_ERROR_CODE
1598 | HMVMX_READ_EXIT_INTERRUPTION_INFO
1599 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
1600 | HMVMX_READ_GUEST_LINEAR_ADDR
1601 | HMVMX_READ_GUEST_PHYSICAL_ADDR;
1602 return VINF_SUCCESS;
1603}
1604#endif
1605
1606/**
1607 * Enters VMX root mode operation on the current CPU.
1608 *
1609 * @returns VBox status code.
1610 * @param pVM The cross context VM structure. Can be
1611 * NULL, after a resume.
1612 * @param HCPhysCpuPage Physical address of the VMXON region.
1613 * @param pvCpuPage Pointer to the VMXON region.
1614 */
1615static int hmR0VmxEnterRootMode(PVM pVM, RTHCPHYS HCPhysCpuPage, void *pvCpuPage)
1616{
1617 Assert(HCPhysCpuPage && HCPhysCpuPage != NIL_RTHCPHYS);
1618 Assert(RT_ALIGN_T(HCPhysCpuPage, _4K, RTHCPHYS) == HCPhysCpuPage);
1619 Assert(pvCpuPage);
1620 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1621
1622 if (pVM)
1623 {
1624 /* Write the VMCS revision identifier to the VMXON region. */
1625 *(uint32_t *)pvCpuPage = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
1626 }
1627
1628 /* Paranoid: Disable interrupts as, in theory, interrupt handlers might mess with CR4. */
1629 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1630
1631 /* Enable the VMX bit in CR4 if necessary. */
1632 RTCCUINTREG const uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
1633
1634 /* Enter VMX root mode. */
1635 int rc = VMXEnable(HCPhysCpuPage);
1636 if (RT_FAILURE(rc))
1637 {
1638 if (!(uOldCr4 & X86_CR4_VMXE))
1639 SUPR0ChangeCR4(0 /* fOrMask */, ~X86_CR4_VMXE);
1640
1641 if (pVM)
1642 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
1643 }
1644
1645 /* Restore interrupts. */
1646 ASMSetFlags(fEFlags);
1647 return rc;
1648}
1649
1650
1651/**
1652 * Exits VMX root mode operation on the current CPU.
1653 *
1654 * @returns VBox status code.
1655 */
1656static int hmR0VmxLeaveRootMode(void)
1657{
1658 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1659
1660 /* Paranoid: Disable interrupts as, in theory, interrupts handlers might mess with CR4. */
1661 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1662
1663 /* If we're for some reason not in VMX root mode, then don't leave it. */
1664 RTCCUINTREG const uHostCr4 = ASMGetCR4();
1665
1666 int rc;
1667 if (uHostCr4 & X86_CR4_VMXE)
1668 {
1669 /* Exit VMX root mode and clear the VMX bit in CR4. */
1670 VMXDisable();
1671 SUPR0ChangeCR4(0 /* fOrMask */, ~X86_CR4_VMXE);
1672 rc = VINF_SUCCESS;
1673 }
1674 else
1675 rc = VERR_VMX_NOT_IN_VMX_ROOT_MODE;
1676
1677 /* Restore interrupts. */
1678 ASMSetFlags(fEFlags);
1679 return rc;
1680}
1681
1682
1683/**
1684 * Allocates and maps a physically contiguous page. The allocated page is
1685 * zero'd out (used by various VT-x structures).
1686 *
1687 * @returns IPRT status code.
1688 * @param pMemObj Pointer to the ring-0 memory object.
1689 * @param ppVirt Where to store the virtual address of the allocation.
1690 * @param pHCPhys Where to store the physical address of the allocation.
1691 */
1692static int hmR0VmxPageAllocZ(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1693{
1694 AssertPtr(pMemObj);
1695 AssertPtr(ppVirt);
1696 AssertPtr(pHCPhys);
1697 int rc = RTR0MemObjAllocCont(pMemObj, X86_PAGE_4K_SIZE, false /* fExecutable */);
1698 if (RT_FAILURE(rc))
1699 return rc;
1700 *ppVirt = RTR0MemObjAddress(*pMemObj);
1701 *pHCPhys = RTR0MemObjGetPagePhysAddr(*pMemObj, 0 /* iPage */);
1702 ASMMemZero32(*ppVirt, X86_PAGE_4K_SIZE);
1703 return VINF_SUCCESS;
1704}
1705
1706
1707/**
1708 * Frees and unmaps an allocated, physical page.
1709 *
1710 * @param pMemObj Pointer to the ring-0 memory object.
1711 * @param ppVirt Where to re-initialize the virtual address of allocation as
1712 * 0.
1713 * @param pHCPhys Where to re-initialize the physical address of the
1714 * allocation as 0.
1715 */
1716static void hmR0VmxPageFree(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1717{
1718 AssertPtr(pMemObj);
1719 AssertPtr(ppVirt);
1720 AssertPtr(pHCPhys);
1721 /* NULL is valid, accepted and ignored by the free function below. */
1722 RTR0MemObjFree(*pMemObj, true /* fFreeMappings */);
1723 *pMemObj = NIL_RTR0MEMOBJ;
1724 *ppVirt = NULL;
1725 *pHCPhys = NIL_RTHCPHYS;
1726}
1727
1728
1729/**
1730 * Initializes a VMCS info. object.
1731 *
1732 * @param pVmcsInfo The VMCS info. object.
1733 */
1734static void hmR0VmxInitVmcsInfo(PVMXVMCSINFO pVmcsInfo)
1735{
1736 memset(pVmcsInfo, 0, sizeof(*pVmcsInfo));
1737
1738 Assert(pVmcsInfo->hMemObjVmcs == NIL_RTR0MEMOBJ);
1739 Assert(pVmcsInfo->hMemObjShadowVmcs == NIL_RTR0MEMOBJ);
1740 Assert(pVmcsInfo->hMemObjMsrBitmap == NIL_RTR0MEMOBJ);
1741 Assert(pVmcsInfo->hMemObjGuestMsrLoad == NIL_RTR0MEMOBJ);
1742 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1743 Assert(pVmcsInfo->hMemObjHostMsrLoad == NIL_RTR0MEMOBJ);
1744 pVmcsInfo->HCPhysVmcs = NIL_RTHCPHYS;
1745 pVmcsInfo->HCPhysShadowVmcs = NIL_RTHCPHYS;
1746 pVmcsInfo->HCPhysMsrBitmap = NIL_RTHCPHYS;
1747 pVmcsInfo->HCPhysGuestMsrLoad = NIL_RTHCPHYS;
1748 pVmcsInfo->HCPhysGuestMsrStore = NIL_RTHCPHYS;
1749 pVmcsInfo->HCPhysHostMsrLoad = NIL_RTHCPHYS;
1750 pVmcsInfo->HCPhysVirtApic = NIL_RTHCPHYS;
1751 pVmcsInfo->HCPhysEPTP = NIL_RTHCPHYS;
1752 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
1753 pVmcsInfo->idHostCpu = NIL_RTCPUID;
1754}
1755
1756
1757/**
1758 * Frees the VT-x structures for a VMCS info. object.
1759 *
1760 * @param pVM The cross context VM structure.
1761 * @param pVmcsInfo The VMCS info. object.
1762 */
1763static void hmR0VmxFreeVmcsInfo(PVM pVM, PVMXVMCSINFO pVmcsInfo)
1764{
1765 hmR0VmxPageFree(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1766
1767#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1768 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1769 hmR0VmxPageFree(&pVmcsInfo->hMemObjShadowVmcs, &pVmcsInfo->pvShadowVmcs, &pVmcsInfo->HCPhysShadowVmcs);
1770#endif
1771
1772 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1773 hmR0VmxPageFree(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1774
1775 hmR0VmxPageFree(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad, &pVmcsInfo->HCPhysHostMsrLoad);
1776 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad, &pVmcsInfo->HCPhysGuestMsrLoad);
1777 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrStore, &pVmcsInfo->pvGuestMsrStore, &pVmcsInfo->HCPhysGuestMsrStore);
1778
1779 hmR0VmxInitVmcsInfo(pVmcsInfo);
1780}
1781
1782
1783/**
1784 * Allocates the VT-x structures for a VMCS info. object.
1785 *
1786 * @returns VBox status code.
1787 * @param pVCpu The cross context virtual CPU structure.
1788 * @param pVmcsInfo The VMCS info. object.
1789 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
1790 */
1791static int hmR0VmxAllocVmcsInfo(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
1792{
1793 PVM pVM = pVCpu->CTX_SUFF(pVM);
1794
1795 /* Allocate the guest VM control structure (VMCS). */
1796 int rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1797 if (RT_SUCCESS(rc))
1798 {
1799 if (!fIsNstGstVmcs)
1800 {
1801#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1802 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1803 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjShadowVmcs, &pVmcsInfo->pvShadowVmcs, &pVmcsInfo->HCPhysShadowVmcs);
1804#endif
1805 if (RT_SUCCESS(rc))
1806 {
1807 /* Get the allocated virtual-APIC page from the virtual APIC device. */
1808 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
1809 && (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW))
1810 {
1811 rc = APICGetApicPageForCpu(pVCpu, &pVmcsInfo->HCPhysVirtApic, (PRTR0PTR)&pVmcsInfo->pbVirtApic,
1812 NULL /* pR3Ptr */, NULL /* pRCPtr */);
1813 }
1814 }
1815 }
1816 else
1817 {
1818 /* We don't yet support exposing VMCS shadowing to the guest. */
1819 Assert(pVmcsInfo->HCPhysShadowVmcs == NIL_RTHCPHYS);
1820 Assert(!pVmcsInfo->pvShadowVmcs);
1821
1822 /* Get the allocated virtual-APIC page from CPUM. */
1823 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
1824 {
1825 pVmcsInfo->pbVirtApic = (uint8_t *)CPUMGetGuestVmxVirtApicPage(pVCpu, &pVCpu->cpum.GstCtx,
1826 &pVmcsInfo->HCPhysVirtApic);
1827 Assert(pVmcsInfo->pbVirtApic);
1828 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1829 }
1830 }
1831
1832 if (RT_SUCCESS(rc))
1833 {
1834 /*
1835 * Allocate the MSR-bitmap if supported by the CPU. The MSR-bitmap is for
1836 * transparent accesses of specific MSRs.
1837 *
1838 * If the condition for enabling MSR bitmaps changes here, don't forget to
1839 * update HMIsMsrBitmapActive().
1840 *
1841 * We don't share MSR bitmaps between the guest and nested-guest as we then
1842 * don't need to care about carefully restoring the guest MSR bitmap.
1843 * The guest visible nested-guest MSR bitmap needs to remain unchanged.
1844 * Hence, allocate a separate MSR bitmap for the guest and nested-guest.
1845 * We also don't need to re-initialize the nested-guest MSR bitmap here as
1846 * we do that later while merging VMCS.
1847 */
1848 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1849 {
1850 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1851 if ( RT_SUCCESS(rc)
1852 && !fIsNstGstVmcs)
1853 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
1854 }
1855
1856 if (RT_SUCCESS(rc))
1857 {
1858 /*
1859 * Allocate the VM-entry MSR-load area for the guest MSRs.
1860 *
1861 * Similar to MSR-bitmaps, we do not share the auto MSR-load/store are between
1862 * the guest and nested-guest.
1863 */
1864 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad,
1865 &pVmcsInfo->HCPhysGuestMsrLoad);
1866 if (RT_SUCCESS(rc))
1867 {
1868 /*
1869 * We use the same page for VM-entry MSR-load and VM-exit MSR store areas.
1870 * These contain the guest MSRs to load on VM-entry and store on VM-exit.
1871 */
1872 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1873 pVmcsInfo->pvGuestMsrStore = pVmcsInfo->pvGuestMsrLoad;
1874 pVmcsInfo->HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrLoad;
1875
1876 /* Allocate the VM-exit MSR-load page for the host MSRs. */
1877 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad,
1878 &pVmcsInfo->HCPhysHostMsrLoad);
1879 }
1880 }
1881 }
1882 }
1883
1884 return rc;
1885}
1886
1887
1888/**
1889 * Free all VT-x structures for the VM.
1890 *
1891 * @returns IPRT status code.
1892 * @param pVM The cross context VM structure.
1893 */
1894static void hmR0VmxStructsFree(PVM pVM)
1895{
1896#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1897 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1898#endif
1899 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess, &pVM->hm.s.vmx.HCPhysApicAccess);
1900
1901#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1902 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1903 {
1904 RTMemFree(pVM->hm.s.vmx.paShadowVmcsFields);
1905 RTMemFree(pVM->hm.s.vmx.paShadowVmcsRoFields);
1906 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap, &pVM->hm.s.vmx.HCPhysVmreadBitmap);
1907 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap, &pVM->hm.s.vmx.HCPhysVmwriteBitmap);
1908 }
1909#endif
1910
1911 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1912 {
1913 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1914 PVMXVMCSINFO pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
1915 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1916#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1917 if (pVM->cpum.ro.GuestFeatures.fVmx)
1918 {
1919 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1920 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1921 }
1922#endif
1923 }
1924}
1925
1926
1927/**
1928 * Allocate all VT-x structures for the VM.
1929 *
1930 * @returns IPRT status code.
1931 * @param pVM The cross context VM structure.
1932 */
1933static int hmR0VmxStructsAlloc(PVM pVM)
1934{
1935 /*
1936 * Sanity check the VMCS size reported by the CPU as we assume 4KB allocations.
1937 * The VMCS size cannot be more than 4096 bytes.
1938 *
1939 * See Intel spec. Appendix A.1 "Basic VMX Information".
1940 */
1941 uint32_t const cbVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_SIZE);
1942 if (cbVmcs <= X86_PAGE_4K_SIZE)
1943 { /* likely */ }
1944 else
1945 {
1946 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_INVALID_VMCS_SIZE;
1947 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
1948 }
1949
1950 /*
1951 * Initialize/check members up-front so we can cleanup en masse on allocation failures.
1952 */
1953#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1954 Assert(pVM->hm.s.vmx.hMemObjScratch == NIL_RTR0MEMOBJ);
1955 Assert(pVM->hm.s.vmx.pbScratch == NULL);
1956 pVM->hm.s.vmx.HCPhysScratch = NIL_RTHCPHYS;
1957#endif
1958
1959 Assert(pVM->hm.s.vmx.hMemObjApicAccess == NIL_RTR0MEMOBJ);
1960 Assert(pVM->hm.s.vmx.pbApicAccess == NULL);
1961 pVM->hm.s.vmx.HCPhysApicAccess = NIL_RTHCPHYS;
1962
1963 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1964 {
1965 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1966 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfo);
1967 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
1968 }
1969
1970 /*
1971 * Allocate per-VM VT-x structures.
1972 */
1973 int rc = VINF_SUCCESS;
1974#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1975 /* Allocate crash-dump magic scratch page. */
1976 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1977 if (RT_FAILURE(rc))
1978 {
1979 hmR0VmxStructsFree(pVM);
1980 return rc;
1981 }
1982 strcpy((char *)pVM->hm.s.vmx.pbScratch, "SCRATCH Magic");
1983 *(uint64_t *)(pVM->hm.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
1984#endif
1985
1986 /* Allocate the APIC-access page for trapping APIC accesses from the guest. */
1987 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
1988 {
1989 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess,
1990 &pVM->hm.s.vmx.HCPhysApicAccess);
1991 if (RT_FAILURE(rc))
1992 {
1993 hmR0VmxStructsFree(pVM);
1994 return rc;
1995 }
1996 }
1997
1998#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1999 /* Allocate the shadow VMCS fields array, VMREAD, VMWRITE bitmaps.. */
2000 if (pVM->hm.s.vmx.fUseVmcsShadowing)
2001 {
2002 Assert(!pVM->hm.s.vmx.cShadowVmcsFields);
2003 Assert(!pVM->hm.s.vmx.cShadowVmcsRoFields);
2004 pVM->hm.s.vmx.paShadowVmcsFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
2005 pVM->hm.s.vmx.paShadowVmcsRoFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
2006 if (RT_LIKELY( pVM->hm.s.vmx.paShadowVmcsFields
2007 && pVM->hm.s.vmx.paShadowVmcsRoFields))
2008 {
2009 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap,
2010 &pVM->hm.s.vmx.HCPhysVmreadBitmap);
2011 if (RT_SUCCESS(rc))
2012 {
2013 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap,
2014 &pVM->hm.s.vmx.HCPhysVmwriteBitmap);
2015 }
2016 }
2017 else
2018 rc = VERR_NO_MEMORY;
2019
2020 if (RT_FAILURE(rc))
2021 {
2022 hmR0VmxStructsFree(pVM);
2023 return rc;
2024 }
2025 }
2026#endif
2027
2028 /*
2029 * Initialize per-VCPU VT-x structures.
2030 */
2031 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
2032 {
2033 /* Allocate the guest VMCS structures. */
2034 PVMCPU pVCpu = &pVM->aCpus[idCpu];
2035 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
2036 if (RT_SUCCESS(rc))
2037 {
2038#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2039 /* Allocate the nested-guest VMCS structures, when the VMX feature is exposed to the guest. */
2040 if (pVM->cpum.ro.GuestFeatures.fVmx)
2041 {
2042 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
2043 if (RT_SUCCESS(rc))
2044 { /* likely */ }
2045 else
2046 break;
2047 }
2048#endif
2049 }
2050 else
2051 break;
2052 }
2053
2054 if (RT_FAILURE(rc))
2055 {
2056 hmR0VmxStructsFree(pVM);
2057 return rc;
2058 }
2059
2060 return VINF_SUCCESS;
2061}
2062
2063#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2064/**
2065 * Returns whether an MSR at the given MSR-bitmap offset is intercepted or not.
2066 *
2067 * @returns @c true if the MSR is intercepted, @c false otherwise.
2068 * @param pvMsrBitmap The MSR bitmap.
2069 * @param offMsr The MSR byte offset.
2070 * @param iBit The bit offset from the byte offset.
2071 */
2072DECLINLINE(bool) hmR0VmxIsMsrBitSet(const void *pvMsrBitmap, uint16_t offMsr, int32_t iBit)
2073{
2074 uint8_t const * const pbMsrBitmap = (uint8_t const * const)pvMsrBitmap;
2075 Assert(pbMsrBitmap);
2076 Assert(offMsr + (iBit >> 3) <= X86_PAGE_4K_SIZE);
2077 return ASMBitTest(pbMsrBitmap + offMsr, iBit);
2078}
2079#endif
2080
2081/**
2082 * Sets the permission bits for the specified MSR in the given MSR bitmap.
2083 *
2084 * If the passed VMCS is a nested-guest VMCS, this function ensures that the
2085 * read/write intercept is cleared from the MSR bitmap used for hardware-assisted
2086 * VMX execution of the nested-guest, only if nested-guest is also not intercepting
2087 * the read/write access of this MSR.
2088 *
2089 * @param pVCpu The cross context virtual CPU structure.
2090 * @param pVmcsInfo The VMCS info. object.
2091 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2092 * @param idMsr The MSR value.
2093 * @param fMsrpm The MSR permissions (see VMXMSRPM_XXX). This must
2094 * include both a read -and- a write permission!
2095 *
2096 * @sa CPUMGetVmxMsrPermission.
2097 * @remarks Can be called with interrupts disabled.
2098 */
2099static void hmR0VmxSetMsrPermission(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs, uint32_t idMsr, uint32_t fMsrpm)
2100{
2101 uint8_t *pbMsrBitmap = (uint8_t *)pVmcsInfo->pvMsrBitmap;
2102 Assert(pbMsrBitmap);
2103 Assert(VMXMSRPM_IS_FLAG_VALID(fMsrpm));
2104
2105 /*
2106 * MSR-bitmap Layout:
2107 * Byte index MSR range Interpreted as
2108 * 0x000 - 0x3ff 0x00000000 - 0x00001fff Low MSR read bits.
2109 * 0x400 - 0x7ff 0xc0000000 - 0xc0001fff High MSR read bits.
2110 * 0x800 - 0xbff 0x00000000 - 0x00001fff Low MSR write bits.
2111 * 0xc00 - 0xfff 0xc0000000 - 0xc0001fff High MSR write bits.
2112 *
2113 * A bit corresponding to an MSR within the above range causes a VM-exit
2114 * if the bit is 1 on executions of RDMSR/WRMSR. If an MSR falls out of
2115 * the MSR range, it always cause a VM-exit.
2116 *
2117 * See Intel spec. 24.6.9 "MSR-Bitmap Address".
2118 */
2119 uint16_t const offBitmapRead = 0;
2120 uint16_t const offBitmapWrite = 0x800;
2121 uint16_t offMsr;
2122 int32_t iBit;
2123 if (idMsr <= UINT32_C(0x00001fff))
2124 {
2125 offMsr = 0;
2126 iBit = idMsr;
2127 }
2128 else if (idMsr - UINT32_C(0xc0000000) <= UINT32_C(0x00001fff))
2129 {
2130 offMsr = 0x400;
2131 iBit = idMsr - UINT32_C(0xc0000000);
2132 }
2133 else
2134 AssertMsgFailedReturnVoid(("Invalid MSR %#RX32\n", idMsr));
2135
2136 /*
2137 * Set the MSR read permission.
2138 */
2139 uint16_t const offMsrRead = offBitmapRead + offMsr;
2140 Assert(offMsrRead + (iBit >> 3) < offBitmapWrite);
2141 if (fMsrpm & VMXMSRPM_ALLOW_RD)
2142 {
2143#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2144 bool const fClear = !fIsNstGstVmcs ? true
2145 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrRead, iBit);
2146#else
2147 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2148 bool const fClear = true;
2149#endif
2150 if (fClear)
2151 ASMBitClear(pbMsrBitmap + offMsrRead, iBit);
2152 }
2153 else
2154 ASMBitSet(pbMsrBitmap + offMsrRead, iBit);
2155
2156 /*
2157 * Set the MSR write permission.
2158 */
2159 uint16_t const offMsrWrite = offBitmapWrite + offMsr;
2160 Assert(offMsrWrite + (iBit >> 3) < X86_PAGE_4K_SIZE);
2161 if (fMsrpm & VMXMSRPM_ALLOW_WR)
2162 {
2163#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2164 bool const fClear = !fIsNstGstVmcs ? true
2165 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrWrite, iBit);
2166#else
2167 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2168 bool const fClear = true;
2169#endif
2170 if (fClear)
2171 ASMBitClear(pbMsrBitmap + offMsrWrite, iBit);
2172 }
2173 else
2174 ASMBitSet(pbMsrBitmap + offMsrWrite, iBit);
2175}
2176
2177
2178/**
2179 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR
2180 * area.
2181 *
2182 * @returns VBox status code.
2183 * @param pVCpu The cross context virtual CPU structure.
2184 * @param pVmcsInfo The VMCS info. object.
2185 * @param cMsrs The number of MSRs.
2186 */
2187static int hmR0VmxSetAutoLoadStoreMsrCount(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t cMsrs)
2188{
2189 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */
2190 uint32_t const cMaxSupportedMsrs = VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc);
2191 if (RT_LIKELY(cMsrs < cMaxSupportedMsrs))
2192 {
2193 /* Commit the MSR counts to the VMCS and update the cache. */
2194 if (pVmcsInfo->cEntryMsrLoad != cMsrs)
2195 {
2196 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs);
2197 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs);
2198 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs);
2199 AssertRCReturn(rc, rc);
2200
2201 pVmcsInfo->cEntryMsrLoad = cMsrs;
2202 pVmcsInfo->cExitMsrStore = cMsrs;
2203 pVmcsInfo->cExitMsrLoad = cMsrs;
2204 }
2205 return VINF_SUCCESS;
2206 }
2207
2208 LogRel(("Auto-load/store MSR count exceeded! cMsrs=%u MaxSupported=%u\n", cMsrs, cMaxSupportedMsrs));
2209 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE;
2210 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2211}
2212
2213
2214/**
2215 * Adds a new (or updates the value of an existing) guest/host MSR
2216 * pair to be swapped during the world-switch as part of the
2217 * auto-load/store MSR area in the VMCS.
2218 *
2219 * @returns VBox status code.
2220 * @param pVCpu The cross context virtual CPU structure.
2221 * @param pVmxTransient The VMX-transient structure.
2222 * @param idMsr The MSR.
2223 * @param uGuestMsrValue Value of the guest MSR.
2224 * @param fSetReadWrite Whether to set the guest read/write access of this
2225 * MSR (thus not causing a VM-exit).
2226 * @param fUpdateHostMsr Whether to update the value of the host MSR if
2227 * necessary.
2228 */
2229static int hmR0VmxAddAutoLoadStoreMsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t idMsr, uint64_t uGuestMsrValue,
2230 bool fSetReadWrite, bool fUpdateHostMsr)
2231{
2232 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2233 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2234 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2235 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2236 uint32_t i;
2237
2238 /* Paranoia. */
2239 Assert(pGuestMsrLoad);
2240
2241 LogFlowFunc(("pVCpu=%p idMsr=%#RX32 uGestMsrValue=%#RX64\n", pVCpu, idMsr, uGuestMsrValue));
2242
2243 /* Check if the MSR already exists in the VM-entry MSR-load area. */
2244 for (i = 0; i < cMsrs; i++)
2245 {
2246 if (pGuestMsrLoad[i].u32Msr == idMsr)
2247 break;
2248 }
2249
2250 bool fAdded = false;
2251 if (i == cMsrs)
2252 {
2253 /* The MSR does not exist, bump the MSR count to make room for the new MSR. */
2254 ++cMsrs;
2255 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2256 AssertMsgRCReturn(rc, ("Insufficient space to add MSR to VM-entry MSR-load/store area %u\n", idMsr), rc);
2257
2258 /* Set the guest to read/write this MSR without causing VM-exits. */
2259 if ( fSetReadWrite
2260 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
2261 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_ALLOW_RD_WR);
2262
2263 Log4Func(("Added MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2264 fAdded = true;
2265 }
2266
2267 /* Update the MSR value for the newly added or already existing MSR. */
2268 pGuestMsrLoad[i].u32Msr = idMsr;
2269 pGuestMsrLoad[i].u64Value = uGuestMsrValue;
2270
2271 /* Create the corresponding slot in the VM-exit MSR-store area if we use a different page. */
2272 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2273 {
2274 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2275 pGuestMsrStore[i].u32Msr = idMsr;
2276 pGuestMsrStore[i].u64Value = uGuestMsrValue;
2277 }
2278
2279 /* Update the corresponding slot in the host MSR area. */
2280 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2281 Assert(pHostMsr != pVmcsInfo->pvGuestMsrLoad);
2282 Assert(pHostMsr != pVmcsInfo->pvGuestMsrStore);
2283 pHostMsr[i].u32Msr = idMsr;
2284
2285 /*
2286 * Only if the caller requests to update the host MSR value AND we've newly added the
2287 * MSR to the host MSR area do we actually update the value. Otherwise, it will be
2288 * updated by hmR0VmxUpdateAutoLoadHostMsrs().
2289 *
2290 * We do this for performance reasons since reading MSRs may be quite expensive.
2291 */
2292 if (fAdded)
2293 {
2294 if (fUpdateHostMsr)
2295 {
2296 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2297 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2298 pHostMsr[i].u64Value = ASMRdMsr(idMsr);
2299 }
2300 else
2301 {
2302 /* Someone else can do the work. */
2303 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
2304 }
2305 }
2306 return VINF_SUCCESS;
2307}
2308
2309
2310/**
2311 * Removes a guest/host MSR pair to be swapped during the world-switch from the
2312 * auto-load/store MSR area in the VMCS.
2313 *
2314 * @returns VBox status code.
2315 * @param pVCpu The cross context virtual CPU structure.
2316 * @param pVmxTransient The VMX-transient structure.
2317 * @param idMsr The MSR.
2318 */
2319static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t idMsr)
2320{
2321 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2322 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2323 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2324 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2325
2326 LogFlowFunc(("pVCpu=%p idMsr=%#RX32\n", pVCpu, idMsr));
2327
2328 for (uint32_t i = 0; i < cMsrs; i++)
2329 {
2330 /* Find the MSR. */
2331 if (pGuestMsrLoad[i].u32Msr == idMsr)
2332 {
2333 /*
2334 * If it's the last MSR, we only need to reduce the MSR count.
2335 * If it's -not- the last MSR, copy the last MSR in place of it and reduce the MSR count.
2336 */
2337 if (i < cMsrs - 1)
2338 {
2339 /* Remove it from the VM-entry MSR-load area. */
2340 pGuestMsrLoad[i].u32Msr = pGuestMsrLoad[cMsrs - 1].u32Msr;
2341 pGuestMsrLoad[i].u64Value = pGuestMsrLoad[cMsrs - 1].u64Value;
2342
2343 /* Remove it from the VM-exit MSR-store area if it's in a different page. */
2344 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2345 {
2346 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2347 Assert(pGuestMsrStore[i].u32Msr == idMsr);
2348 pGuestMsrStore[i].u32Msr = pGuestMsrStore[cMsrs - 1].u32Msr;
2349 pGuestMsrStore[i].u64Value = pGuestMsrStore[cMsrs - 1].u64Value;
2350 }
2351
2352 /* Remove it from the VM-exit MSR-load area. */
2353 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2354 Assert(pHostMsr[i].u32Msr == idMsr);
2355 pHostMsr[i].u32Msr = pHostMsr[cMsrs - 1].u32Msr;
2356 pHostMsr[i].u64Value = pHostMsr[cMsrs - 1].u64Value;
2357 }
2358
2359 /* Reduce the count to reflect the removed MSR and bail. */
2360 --cMsrs;
2361 break;
2362 }
2363 }
2364
2365 /* Update the VMCS if the count changed (meaning the MSR was found and removed). */
2366 if (cMsrs != pVmcsInfo->cEntryMsrLoad)
2367 {
2368 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2369 AssertRCReturn(rc, rc);
2370
2371 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */
2372 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2373 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR);
2374
2375 Log4Func(("Removed MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2376 return VINF_SUCCESS;
2377 }
2378
2379 return VERR_NOT_FOUND;
2380}
2381
2382
2383/**
2384 * Checks if the specified guest MSR is part of the VM-entry MSR-load area.
2385 *
2386 * @returns @c true if found, @c false otherwise.
2387 * @param pVmcsInfo The VMCS info. object.
2388 * @param idMsr The MSR to find.
2389 */
2390static bool hmR0VmxIsAutoLoadGuestMsr(PCVMXVMCSINFO pVmcsInfo, uint32_t idMsr)
2391{
2392 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2393 uint32_t const cMsrs = pVmcsInfo->cEntryMsrLoad;
2394 Assert(pMsrs);
2395 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
2396 for (uint32_t i = 0; i < cMsrs; i++)
2397 {
2398 if (pMsrs[i].u32Msr == idMsr)
2399 return true;
2400 }
2401 return false;
2402}
2403
2404
2405/**
2406 * Updates the value of all host MSRs in the VM-exit MSR-load area.
2407 *
2408 * @param pVCpu The cross context virtual CPU structure.
2409 * @param pVmcsInfo The VMCS info. object.
2410 *
2411 * @remarks No-long-jump zone!!!
2412 */
2413static void hmR0VmxUpdateAutoLoadHostMsrs(PCVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2414{
2415 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2416
2417 PVMXAUTOMSR pHostMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2418 uint32_t const cMsrs = pVmcsInfo->cExitMsrLoad;
2419 Assert(pHostMsrLoad);
2420 Assert(sizeof(*pHostMsrLoad) * cMsrs <= X86_PAGE_4K_SIZE);
2421 LogFlowFunc(("pVCpu=%p cMsrs=%u\n", pVCpu, cMsrs));
2422 for (uint32_t i = 0; i < cMsrs; i++)
2423 {
2424 /*
2425 * Performance hack for the host EFER MSR. We use the cached value rather than re-read it.
2426 * Strict builds will catch mismatches in hmR0VmxCheckAutoLoadStoreMsrs(). See @bugref{7368}.
2427 */
2428 if (pHostMsrLoad[i].u32Msr == MSR_K6_EFER)
2429 pHostMsrLoad[i].u64Value = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2430 else
2431 pHostMsrLoad[i].u64Value = ASMRdMsr(pHostMsrLoad[i].u32Msr);
2432 }
2433}
2434
2435
2436/**
2437 * Saves a set of host MSRs to allow read/write passthru access to the guest and
2438 * perform lazy restoration of the host MSRs while leaving VT-x.
2439 *
2440 * @param pVCpu The cross context virtual CPU structure.
2441 *
2442 * @remarks No-long-jump zone!!!
2443 */
2444static void hmR0VmxLazySaveHostMsrs(PVMCPU pVCpu)
2445{
2446 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2447
2448 /*
2449 * Note: If you're adding MSRs here, make sure to update the MSR-bitmap accesses in hmR0VmxSetupVmcsProcCtls().
2450 */
2451 if (!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST))
2452 {
2453 Assert(!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)); /* Guest MSRs better not be loaded now. */
2454#if HC_ARCH_BITS == 64
2455 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2456 {
2457 pVCpu->hm.s.vmx.u64HostMsrLStar = ASMRdMsr(MSR_K8_LSTAR);
2458 pVCpu->hm.s.vmx.u64HostMsrStar = ASMRdMsr(MSR_K6_STAR);
2459 pVCpu->hm.s.vmx.u64HostMsrSfMask = ASMRdMsr(MSR_K8_SF_MASK);
2460 pVCpu->hm.s.vmx.u64HostMsrKernelGsBase = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
2461 }
2462#endif
2463 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_SAVED_HOST;
2464 }
2465}
2466
2467
2468/**
2469 * Checks whether the MSR belongs to the set of guest MSRs that we restore
2470 * lazily while leaving VT-x.
2471 *
2472 * @returns true if it does, false otherwise.
2473 * @param pVCpu The cross context virtual CPU structure.
2474 * @param idMsr The MSR to check.
2475 */
2476static bool hmR0VmxIsLazyGuestMsr(PCVMCPU pVCpu, uint32_t idMsr)
2477{
2478 NOREF(pVCpu);
2479#if HC_ARCH_BITS == 64
2480 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2481 {
2482 switch (idMsr)
2483 {
2484 case MSR_K8_LSTAR:
2485 case MSR_K6_STAR:
2486 case MSR_K8_SF_MASK:
2487 case MSR_K8_KERNEL_GS_BASE:
2488 return true;
2489 }
2490 }
2491#else
2492 RT_NOREF(pVCpu, idMsr);
2493#endif
2494 return false;
2495}
2496
2497
2498/**
2499 * Loads a set of guests MSRs to allow read/passthru to the guest.
2500 *
2501 * The name of this function is slightly confusing. This function does NOT
2502 * postpone loading, but loads the MSR right now. "hmR0VmxLazy" is simply a
2503 * common prefix for functions dealing with "lazy restoration" of the shared
2504 * MSRs.
2505 *
2506 * @param pVCpu The cross context virtual CPU structure.
2507 *
2508 * @remarks No-long-jump zone!!!
2509 */
2510static void hmR0VmxLazyLoadGuestMsrs(PVMCPU pVCpu)
2511{
2512 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2513 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2514
2515 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2516#if HC_ARCH_BITS == 64
2517 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2518 {
2519 /*
2520 * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
2521 * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
2522 * we can skip a few MSR writes.
2523 *
2524 * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
2525 * guest MSR values in the guest-CPU context might be different to what's currently
2526 * loaded in the CPU. In either case, we need to write the new guest MSR values to the
2527 * CPU, see @bugref{8728}.
2528 */
2529 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2530 if ( !(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2531 && pCtx->msrKERNELGSBASE == pVCpu->hm.s.vmx.u64HostMsrKernelGsBase
2532 && pCtx->msrLSTAR == pVCpu->hm.s.vmx.u64HostMsrLStar
2533 && pCtx->msrSTAR == pVCpu->hm.s.vmx.u64HostMsrStar
2534 && pCtx->msrSFMASK == pVCpu->hm.s.vmx.u64HostMsrSfMask)
2535 {
2536#ifdef VBOX_STRICT
2537 Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pCtx->msrKERNELGSBASE);
2538 Assert(ASMRdMsr(MSR_K8_LSTAR) == pCtx->msrLSTAR);
2539 Assert(ASMRdMsr(MSR_K6_STAR) == pCtx->msrSTAR);
2540 Assert(ASMRdMsr(MSR_K8_SF_MASK) == pCtx->msrSFMASK);
2541#endif
2542 }
2543 else
2544 {
2545 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE);
2546 ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR);
2547 ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR);
2548 ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK);
2549 }
2550 }
2551#endif
2552 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
2553}
2554
2555
2556/**
2557 * Performs lazy restoration of the set of host MSRs if they were previously
2558 * loaded with guest MSR values.
2559 *
2560 * @param pVCpu The cross context virtual CPU structure.
2561 *
2562 * @remarks No-long-jump zone!!!
2563 * @remarks The guest MSRs should have been saved back into the guest-CPU
2564 * context by hmR0VmxImportGuestState()!!!
2565 */
2566static void hmR0VmxLazyRestoreHostMsrs(PVMCPU pVCpu)
2567{
2568 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2569 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2570
2571 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2572 {
2573 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2574#if HC_ARCH_BITS == 64
2575 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2576 {
2577 ASMWrMsr(MSR_K8_LSTAR, pVCpu->hm.s.vmx.u64HostMsrLStar);
2578 ASMWrMsr(MSR_K6_STAR, pVCpu->hm.s.vmx.u64HostMsrStar);
2579 ASMWrMsr(MSR_K8_SF_MASK, pVCpu->hm.s.vmx.u64HostMsrSfMask);
2580 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pVCpu->hm.s.vmx.u64HostMsrKernelGsBase);
2581 }
2582#endif
2583 }
2584 pVCpu->hm.s.vmx.fLazyMsrs &= ~(VMX_LAZY_MSRS_LOADED_GUEST | VMX_LAZY_MSRS_SAVED_HOST);
2585}
2586
2587
2588/**
2589 * Verifies that our cached values of the VMCS fields are all consistent with
2590 * what's actually present in the VMCS.
2591 *
2592 * @returns VBox status code.
2593 * @retval VINF_SUCCESS if all our caches match their respective VMCS fields.
2594 * @retval VERR_VMX_VMCS_FIELD_CACHE_INVALID if a cache field doesn't match the
2595 * VMCS content. HMCPU error-field is
2596 * updated, see VMX_VCI_XXX.
2597 * @param pVCpu The cross context virtual CPU structure.
2598 * @param pVmcsInfo The VMCS info. object.
2599 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2600 */
2601static int hmR0VmxCheckVmcsCtls(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2602{
2603 const char * const pcszVmcs = fIsNstGstVmcs ? "Nested-guest VMCS" : "VMCS";
2604
2605 uint32_t u32Val;
2606 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
2607 AssertRCReturn(rc, rc);
2608 AssertMsgReturnStmt(pVmcsInfo->u32EntryCtls == u32Val,
2609 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32EntryCtls, u32Val),
2610 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_ENTRY,
2611 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2612
2613 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val);
2614 AssertRCReturn(rc, rc);
2615 AssertMsgReturnStmt(pVmcsInfo->u32ExitCtls == u32Val,
2616 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ExitCtls, u32Val),
2617 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_EXIT,
2618 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2619
2620 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val);
2621 AssertRCReturn(rc, rc);
2622 AssertMsgReturnStmt(pVmcsInfo->u32PinCtls == u32Val,
2623 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32PinCtls, u32Val),
2624 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PIN_EXEC,
2625 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2626
2627 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val);
2628 AssertRCReturn(rc, rc);
2629 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls == u32Val,
2630 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls, u32Val),
2631 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC,
2632 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2633
2634 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
2635 {
2636 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val);
2637 AssertRCReturn(rc, rc);
2638 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls2 == u32Val,
2639 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls2, u32Val),
2640 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC2,
2641 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2642 }
2643
2644 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val);
2645 AssertRCReturn(rc, rc);
2646 AssertMsgReturnStmt(pVmcsInfo->u32XcptBitmap == u32Val,
2647 ("%s exception bitmap mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32XcptBitmap, u32Val),
2648 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_XCPT_BITMAP,
2649 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2650
2651 uint64_t u64Val;
2652 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, &u64Val);
2653 AssertRCReturn(rc, rc);
2654 AssertMsgReturnStmt(pVmcsInfo->u64TscOffset == u64Val,
2655 ("%s TSC offset mismatch: Cache=%#RX64 VMCS=%#RX64\n", pcszVmcs, pVmcsInfo->u64TscOffset, u64Val),
2656 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_TSC_OFFSET,
2657 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2658
2659 NOREF(pcszVmcs);
2660 return VINF_SUCCESS;
2661}
2662
2663
2664#ifdef VBOX_STRICT
2665/**
2666 * Verifies that our cached host EFER MSR value has not changed since we cached it.
2667 *
2668 * @param pVCpu The cross context virtual CPU structure.
2669 * @param pVmcsInfo The VMCS info. object.
2670 */
2671static void hmR0VmxCheckHostEferMsr(PCVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2672{
2673 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2674
2675 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2676 {
2677 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2678 uint64_t const uHostEferMsrCache = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2679 uint64_t uVmcsEferMsrVmcs;
2680 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2681 AssertRC(rc);
2682
2683 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2684 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2685 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2686 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2687 }
2688}
2689
2690
2691/**
2692 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2693 * VMCS are correct.
2694 *
2695 * @param pVCpu The cross context virtual CPU structure.
2696 * @param pVmcsInfo The VMCS info. object.
2697 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2698 */
2699static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2700{
2701 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2702
2703 /* Read the various MSR-area counts from the VMCS. */
2704 uint32_t cEntryLoadMsrs;
2705 uint32_t cExitStoreMsrs;
2706 uint32_t cExitLoadMsrs;
2707 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2708 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2709 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2710
2711 /* Verify all the MSR counts are the same. */
2712 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2713 Assert(cExitStoreMsrs == cExitLoadMsrs);
2714 uint32_t const cMsrs = cExitLoadMsrs;
2715
2716 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2717 Assert(cMsrs < VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc));
2718
2719 /* Verify the MSR counts are within the allocated page size. */
2720 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2721
2722 /* Verify the relevant contents of the MSR areas match. */
2723 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2724 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2725 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2726 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2727 for (uint32_t i = 0; i < cMsrs; i++)
2728 {
2729 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2730 if (fSeparateExitMsrStorePage)
2731 {
2732 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2733 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2734 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2735 }
2736
2737 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2738 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2739 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2740
2741 uint64_t const u64Msr = ASMRdMsr(pHostMsrLoad->u32Msr);
2742 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64Msr,
2743 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2744 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64Msr, cMsrs));
2745
2746 /* Verify that cached host EFER MSR matches what's loaded the CPU. */
2747 bool const fIsEferMsr = RT_BOOL(pHostMsrLoad->u32Msr == MSR_K6_EFER);
2748 if (fIsEferMsr)
2749 {
2750 AssertMsgReturnVoid(u64Msr == pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer,
2751 ("Cached=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2752 pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer, u64Msr, cMsrs));
2753 }
2754
2755 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2756 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2757 {
2758 uint32_t const fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2759 if (fIsEferMsr)
2760 {
2761 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2762 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2763 }
2764 else
2765 {
2766 if (!fIsNstGstVmcs)
2767 {
2768 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_ALLOW_RD_WR) == VMXMSRPM_ALLOW_RD_WR,
2769 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2770 }
2771 else
2772 {
2773 /*
2774 * A nested-guest VMCS must -also- allow read/write passthrough for the MSR for us to
2775 * execute a nested-guest with MSR passthrough.
2776 *
2777 * Check if the nested-guest MSR bitmap allows passthrough, and if so, assert that we
2778 * allow passthrough too.
2779 */
2780 void const *pvMsrBitmapNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
2781 Assert(pvMsrBitmapNstGst);
2782 uint32_t const fMsrpmNstGst = CPUMGetVmxMsrPermission(pvMsrBitmapNstGst, pGuestMsrLoad->u32Msr);
2783 AssertMsgReturnVoid(fMsrpm == fMsrpmNstGst,
2784 ("u32Msr=%#RX32 cMsrs=%u Permission mismatch fMsrpm=%#x fMsrpmNstGst=%#x!\n",
2785 pGuestMsrLoad->u32Msr, cMsrs, fMsrpm, fMsrpmNstGst));
2786 }
2787 }
2788 }
2789
2790 /* Move to the next MSR. */
2791 pHostMsrLoad++;
2792 pGuestMsrLoad++;
2793 pGuestMsrStore++;
2794 }
2795}
2796#endif /* VBOX_STRICT */
2797
2798
2799/**
2800 * Flushes the TLB using EPT.
2801 *
2802 * @returns VBox status code.
2803 * @param pVCpu The cross context virtual CPU structure of the calling
2804 * EMT. Can be NULL depending on @a enmTlbFlush.
2805 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2806 * enmTlbFlush.
2807 * @param enmTlbFlush Type of flush.
2808 *
2809 * @remarks Caller is responsible for making sure this function is called only
2810 * when NestedPaging is supported and providing @a enmTlbFlush that is
2811 * supported by the CPU.
2812 * @remarks Can be called with interrupts disabled.
2813 */
2814static void hmR0VmxFlushEpt(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2815{
2816 uint64_t au64Descriptor[2];
2817 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2818 au64Descriptor[0] = 0;
2819 else
2820 {
2821 Assert(pVCpu);
2822 Assert(pVmcsInfo);
2823 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2824 }
2825 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2826
2827 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2828 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2829
2830 if ( RT_SUCCESS(rc)
2831 && pVCpu)
2832 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2833}
2834
2835
2836/**
2837 * Flushes the TLB using VPID.
2838 *
2839 * @returns VBox status code.
2840 * @param pVCpu The cross context virtual CPU structure of the calling
2841 * EMT. Can be NULL depending on @a enmTlbFlush.
2842 * @param enmTlbFlush Type of flush.
2843 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2844 * on @a enmTlbFlush).
2845 *
2846 * @remarks Can be called with interrupts disabled.
2847 */
2848static void hmR0VmxFlushVpid(PVMCPU pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2849{
2850 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid);
2851
2852 uint64_t au64Descriptor[2];
2853 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2854 {
2855 au64Descriptor[0] = 0;
2856 au64Descriptor[1] = 0;
2857 }
2858 else
2859 {
2860 AssertPtr(pVCpu);
2861 AssertMsg(pVCpu->hm.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2862 AssertMsg(pVCpu->hm.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2863 au64Descriptor[0] = pVCpu->hm.s.uCurrentAsid;
2864 au64Descriptor[1] = GCPtr;
2865 }
2866
2867 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2868 AssertMsg(rc == VINF_SUCCESS,
2869 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hm.s.uCurrentAsid : 0, GCPtr, rc));
2870
2871 if ( RT_SUCCESS(rc)
2872 && pVCpu)
2873 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2874 NOREF(rc);
2875}
2876
2877
2878/**
2879 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2880 * otherwise there is nothing really to invalidate.
2881 *
2882 * @returns VBox status code.
2883 * @param pVCpu The cross context virtual CPU structure.
2884 * @param GCVirt Guest virtual address of the page to invalidate.
2885 */
2886VMMR0DECL(int) VMXR0InvalidatePage(PVMCPU pVCpu, RTGCPTR GCVirt)
2887{
2888 AssertPtr(pVCpu);
2889 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2890
2891 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2892 {
2893 /*
2894 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2895 * the EPT case. See @bugref{6043} and @bugref{6177}.
2896 *
2897 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2898 * as this function maybe called in a loop with individual addresses.
2899 */
2900 PVM pVM = pVCpu->CTX_SUFF(pVM);
2901 if (pVM->hm.s.vmx.fVpid)
2902 {
2903 bool fVpidFlush = RT_BOOL(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
2904
2905#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
2906 /*
2907 * Workaround Erratum BV75, AAJ159 and others that affect several Intel CPUs
2908 * where executing INVVPID outside 64-bit mode does not flush translations of
2909 * 64-bit linear addresses, see @bugref{6208#c72}.
2910 */
2911 if (RT_HI_U32(GCVirt))
2912 fVpidFlush = false;
2913#endif
2914
2915 if (fVpidFlush)
2916 {
2917 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2918 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2919 }
2920 else
2921 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2922 }
2923 else if (pVM->hm.s.fNestedPaging)
2924 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2925 }
2926
2927 return VINF_SUCCESS;
2928}
2929
2930
2931/**
2932 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2933 * case where neither EPT nor VPID is supported by the CPU.
2934 *
2935 * @param pHostCpu The HM physical-CPU structure.
2936 * @param pVCpu The cross context virtual CPU structure.
2937 *
2938 * @remarks Called with interrupts disabled.
2939 */
2940static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPU pVCpu)
2941{
2942 AssertPtr(pVCpu);
2943 AssertPtr(pHostCpu);
2944
2945 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2946
2947 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2948 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2949 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2950 pVCpu->hm.s.fForceTLBFlush = false;
2951 return;
2952}
2953
2954
2955/**
2956 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
2957 *
2958 * @param pHostCpu The HM physical-CPU structure.
2959 * @param pVCpu The cross context virtual CPU structure.
2960 * @param pVmcsInfo The VMCS info. object.
2961 *
2962 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
2963 * nomenclature. The reason is, to avoid confusion in compare statements
2964 * since the host-CPU copies are named "ASID".
2965 *
2966 * @remarks Called with interrupts disabled.
2967 */
2968static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2969{
2970#ifdef VBOX_WITH_STATISTICS
2971 bool fTlbFlushed = false;
2972# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
2973# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
2974 if (!fTlbFlushed) \
2975 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
2976 } while (0)
2977#else
2978# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
2979# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
2980#endif
2981
2982 AssertPtr(pVCpu);
2983 AssertPtr(pHostCpu);
2984 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2985
2986 PVM pVM = pVCpu->CTX_SUFF(pVM);
2987 AssertMsg(pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid,
2988 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
2989 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hm.s.fNestedPaging, pVM->hm.s.vmx.fVpid));
2990
2991 /*
2992 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
2993 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
2994 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
2995 * cannot reuse the current ASID anymore.
2996 */
2997 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
2998 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
2999 {
3000 ++pHostCpu->uCurrentAsid;
3001 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3002 {
3003 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
3004 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3005 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3006 }
3007
3008 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3009 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3010 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3011
3012 /*
3013 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
3014 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
3015 */
3016 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
3017 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3018 HMVMX_SET_TAGGED_TLB_FLUSHED();
3019 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
3020 }
3021 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
3022 {
3023 /*
3024 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
3025 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
3026 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
3027 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
3028 * mappings, see @bugref{6568}.
3029 *
3030 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
3031 */
3032 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
3033 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3034 HMVMX_SET_TAGGED_TLB_FLUSHED();
3035 }
3036
3037 pVCpu->hm.s.fForceTLBFlush = false;
3038 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
3039
3040 Assert(pVCpu->hm.s.idLastCpu == pHostCpu->idCpu);
3041 Assert(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes);
3042 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3043 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3044 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3045 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3046 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3047 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3048 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3049
3050 /* Update VMCS with the VPID. */
3051 int rc = VMXWriteVmcs32(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3052 AssertRC(rc);
3053
3054#undef HMVMX_SET_TAGGED_TLB_FLUSHED
3055}
3056
3057
3058/**
3059 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
3060 *
3061 * @param pHostCpu The HM physical-CPU structure.
3062 * @param pVCpu The cross context virtual CPU structure.
3063 * @param pVmcsInfo The VMCS info. object.
3064 *
3065 * @remarks Called with interrupts disabled.
3066 */
3067static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
3068{
3069 AssertPtr(pVCpu);
3070 AssertPtr(pHostCpu);
3071 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3072 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
3073 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
3074
3075 /*
3076 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
3077 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
3078 */
3079 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3080 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3081 {
3082 pVCpu->hm.s.fForceTLBFlush = true;
3083 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3084 }
3085
3086 /* Check for explicit TLB flushes. */
3087 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3088 {
3089 pVCpu->hm.s.fForceTLBFlush = true;
3090 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3091 }
3092
3093 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3094 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3095
3096 if (pVCpu->hm.s.fForceTLBFlush)
3097 {
3098 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hm.s.vmx.enmTlbFlushEpt);
3099 pVCpu->hm.s.fForceTLBFlush = false;
3100 }
3101}
3102
3103
3104/**
3105 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
3106 *
3107 * @param pHostCpu The HM physical-CPU structure.
3108 * @param pVCpu The cross context virtual CPU structure.
3109 *
3110 * @remarks Called with interrupts disabled.
3111 */
3112static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPU pVCpu)
3113{
3114 AssertPtr(pVCpu);
3115 AssertPtr(pHostCpu);
3116 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3117 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
3118 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
3119
3120 /*
3121 * Force a TLB flush for the first world switch if the current CPU differs from the one we
3122 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3123 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3124 * cannot reuse the current ASID anymore.
3125 */
3126 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3127 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3128 {
3129 pVCpu->hm.s.fForceTLBFlush = true;
3130 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3131 }
3132
3133 /* Check for explicit TLB flushes. */
3134 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3135 {
3136 /*
3137 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
3138 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
3139 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
3140 * include fExplicitFlush's too) - an obscure corner case.
3141 */
3142 pVCpu->hm.s.fForceTLBFlush = true;
3143 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3144 }
3145
3146 PVM pVM = pVCpu->CTX_SUFF(pVM);
3147 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3148 if (pVCpu->hm.s.fForceTLBFlush)
3149 {
3150 ++pHostCpu->uCurrentAsid;
3151 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3152 {
3153 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
3154 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3155 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3156 }
3157
3158 pVCpu->hm.s.fForceTLBFlush = false;
3159 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3160 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3161 if (pHostCpu->fFlushAsidBeforeUse)
3162 {
3163 if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
3164 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
3165 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
3166 {
3167 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
3168 pHostCpu->fFlushAsidBeforeUse = false;
3169 }
3170 else
3171 {
3172 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
3173 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
3174 }
3175 }
3176 }
3177
3178 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3179 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3180 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3181 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3182 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3183 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3184 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3185
3186 int rc = VMXWriteVmcs32(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3187 AssertRC(rc);
3188}
3189
3190
3191/**
3192 * Flushes the guest TLB entry based on CPU capabilities.
3193 *
3194 * @param pHostCpu The HM physical-CPU structure.
3195 * @param pVCpu The cross context virtual CPU structure.
3196 * @param pVmcsInfo The VMCS info. object.
3197 *
3198 * @remarks Called with interrupts disabled.
3199 */
3200static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3201{
3202#ifdef HMVMX_ALWAYS_FLUSH_TLB
3203 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
3204#endif
3205 PVM pVM = pVCpu->CTX_SUFF(pVM);
3206 switch (pVM->hm.s.vmx.enmTlbFlushType)
3207 {
3208 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
3209 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
3210 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
3211 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
3212 default:
3213 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
3214 break;
3215 }
3216 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
3217}
3218
3219
3220/**
3221 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
3222 * TLB entries from the host TLB before VM-entry.
3223 *
3224 * @returns VBox status code.
3225 * @param pVM The cross context VM structure.
3226 */
3227static int hmR0VmxSetupTaggedTlb(PVM pVM)
3228{
3229 /*
3230 * Determine optimal flush type for nested paging.
3231 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
3232 * unrestricted guest execution (see hmR3InitFinalizeR0()).
3233 */
3234 if (pVM->hm.s.fNestedPaging)
3235 {
3236 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
3237 {
3238 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
3239 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
3240 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3241 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
3242 else
3243 {
3244 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
3245 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3246 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
3247 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3248 }
3249
3250 /* Make sure the write-back cacheable memory type for EPT is supported. */
3251 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
3252 {
3253 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3254 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
3255 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3256 }
3257
3258 /* EPT requires a page-walk length of 4. */
3259 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
3260 {
3261 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3262 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
3263 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3264 }
3265 }
3266 else
3267 {
3268 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
3269 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3270 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
3271 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3272 }
3273 }
3274
3275 /*
3276 * Determine optimal flush type for VPID.
3277 */
3278 if (pVM->hm.s.vmx.fVpid)
3279 {
3280 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
3281 {
3282 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
3283 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
3284 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
3285 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
3286 else
3287 {
3288 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
3289 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
3290 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
3291 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
3292 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
3293 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3294 pVM->hm.s.vmx.fVpid = false;
3295 }
3296 }
3297 else
3298 {
3299 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
3300 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
3301 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3302 pVM->hm.s.vmx.fVpid = false;
3303 }
3304 }
3305
3306 /*
3307 * Setup the handler for flushing tagged-TLBs.
3308 */
3309 if (pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid)
3310 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
3311 else if (pVM->hm.s.fNestedPaging)
3312 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
3313 else if (pVM->hm.s.vmx.fVpid)
3314 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
3315 else
3316 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
3317 return VINF_SUCCESS;
3318}
3319
3320
3321#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3322/**
3323 * Sets up the shadow VMCS fields arrays.
3324 *
3325 * This function builds arrays of VMCS fields to sync the shadow VMCS later while
3326 * executing the guest.
3327 *
3328 * @returns VBox status code.
3329 * @param pVM The cross context VM structure.
3330 */
3331static int hmR0VmxSetupShadowVmcsFieldsArrays(PVM pVM)
3332{
3333 /*
3334 * Paranoia. Ensure we haven't exposed the VMWRITE-All VMX feature to the guest
3335 * when the host does not support it.
3336 */
3337 bool const fGstVmwriteAll = pVM->cpum.ro.GuestFeatures.fVmxVmwriteAll;
3338 if ( !fGstVmwriteAll
3339 || (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL))
3340 { /* likely. */ }
3341 else
3342 {
3343 LogRelFunc(("VMX VMWRITE-All feature exposed to the guest but host CPU does not support it!\n"));
3344 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_GST_HOST_VMWRITE_ALL;
3345 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3346 }
3347
3348 uint32_t const cVmcsFields = RT_ELEMENTS(g_aVmcsFields);
3349 uint32_t cRwFields = 0;
3350 uint32_t cRoFields = 0;
3351 for (uint32_t i = 0; i < cVmcsFields; i++)
3352 {
3353 VMXVMCSFIELD VmcsField;
3354 VmcsField.u = g_aVmcsFields[i];
3355
3356 /*
3357 * We will be writing "FULL" (64-bit) fields while syncing the shadow VMCS.
3358 * Therefore, "HIGH" (32-bit portion of 64-bit) fields must not be included
3359 * in the shadow VMCS fields array as they would be redundant.
3360 *
3361 * If the VMCS field depends on a CPU feature that is not exposed to the guest,
3362 * we must not include it in the shadow VMCS fields array. Guests attempting to
3363 * VMREAD/VMWRITE such VMCS fields would cause a VM-exit and we shall emulate
3364 * the required behavior.
3365 */
3366 if ( VmcsField.n.fAccessType == VMX_VMCSFIELD_ACCESS_FULL
3367 && CPUMIsGuestVmxVmcsFieldValid(pVM, VmcsField.u))
3368 {
3369 /*
3370 * Read-only fields are placed in a separate array so that while syncing shadow
3371 * VMCS fields later (which is more performance critical) we can avoid branches.
3372 *
3373 * However, if the guest can write to all fields (including read-only fields),
3374 * we treat it a as read/write field. Otherwise, writing to these fields would
3375 * cause a VMWRITE instruction error while syncing the shadow VMCS .
3376 */
3377 if ( fGstVmwriteAll
3378 || !HMVmxIsVmcsFieldReadOnly(VmcsField.u))
3379 pVM->hm.s.vmx.paShadowVmcsFields[cRwFields++] = VmcsField.u;
3380 else
3381 pVM->hm.s.vmx.paShadowVmcsRoFields[cRoFields++] = VmcsField.u;
3382 }
3383 }
3384
3385 /* Update the counts. */
3386 pVM->hm.s.vmx.cShadowVmcsFields = cRwFields;
3387 pVM->hm.s.vmx.cShadowVmcsRoFields = cRoFields;
3388 return VINF_SUCCESS;
3389}
3390
3391
3392/**
3393 * Sets up the VMREAD and VMWRITE bitmaps.
3394 *
3395 * @param pVM The cross context VM structure.
3396 */
3397static void hmR0VmxSetupVmreadVmwriteBitmaps(PVM pVM)
3398{
3399 /*
3400 * By default, ensure guest attempts to acceses to any VMCS fields cause VM-exits.
3401 */
3402 uint32_t const cbBitmap = X86_PAGE_4K_SIZE;
3403 uint8_t *pbVmreadBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmreadBitmap;
3404 uint8_t *pbVmwriteBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmwriteBitmap;
3405 ASMMemFill32(pbVmreadBitmap, cbBitmap, UINT32_C(0xffffffff));
3406 ASMMemFill32(pbVmwriteBitmap, cbBitmap, UINT32_C(0xffffffff));
3407
3408 /*
3409 * Skip intercepting VMREAD/VMWRITE to guest read/write fields in the
3410 * VMREAD and VMWRITE bitmaps.
3411 */
3412 {
3413 uint32_t const *paShadowVmcsFields = pVM->hm.s.vmx.paShadowVmcsFields;
3414 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
3415 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
3416 {
3417 uint32_t const uVmcsField = paShadowVmcsFields[i];
3418 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3419 Assert(uVmcsField >> 3 < cbBitmap);
3420 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3421 ASMBitClear(pbVmwriteBitmap + (uVmcsField >> 3), uVmcsField & 7);
3422 }
3423 }
3424
3425 /*
3426 * Skip intercepting VMREAD for guest read-only fields in the VMREAD bitmap
3427 * if the host supports VMWRITE to all supported VMCS fields.
3428 */
3429 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
3430 {
3431 uint32_t const *paShadowVmcsRoFields = pVM->hm.s.vmx.paShadowVmcsRoFields;
3432 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
3433 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
3434 {
3435 uint32_t const uVmcsField = paShadowVmcsRoFields[i];
3436 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3437 Assert(uVmcsField >> 3 < cbBitmap);
3438 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3439 }
3440 }
3441}
3442#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
3443
3444
3445/**
3446 * Sets up the virtual-APIC page address for the VMCS.
3447 *
3448 * @returns VBox status code.
3449 * @param pVCpu The cross context virtual CPU structure.
3450 * @param pVmcsInfo The VMCS info. object.
3451 */
3452DECLINLINE(int) hmR0VmxSetupVmcsVirtApicAddr(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
3453{
3454 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
3455 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
3456 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
3457 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
3458 return VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
3459}
3460
3461
3462/**
3463 * Sets up the MSR-bitmap address for the VMCS.
3464 *
3465 * @returns VBox status code.
3466 * @param pVCpu The cross context virtual CPU structure.
3467 * @param pVmcsInfo The VMCS info. object.
3468 */
3469DECLINLINE(int) hmR0VmxSetupVmcsMsrBitmapAddr(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
3470{
3471 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
3472 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
3473 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
3474 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3475 return VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
3476}
3477
3478
3479/**
3480 * Sets up the APIC-access page address for the VMCS.
3481 *
3482 * @returns VBox status code.
3483 * @param pVCpu The cross context virtual CPU structure.
3484 */
3485DECLINLINE(int) hmR0VmxSetupVmcsApicAccessAddr(PVMCPU pVCpu)
3486{
3487 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysApicAccess;
3488 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
3489 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
3490 return VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
3491}
3492
3493
3494#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3495/**
3496 * Sets up the VMREAD bitmap address for the VMCS.
3497 *
3498 * @returns VBox status code.
3499 * @param pVCpu The cross context virtual CPU structure.
3500 */
3501DECLINLINE(int) hmR0VmxSetupVmcsVmreadBitmapAddr(PVMCPU pVCpu)
3502{
3503 RTHCPHYS const HCPhysVmreadBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmreadBitmap;
3504 Assert(HCPhysVmreadBitmap != NIL_RTHCPHYS);
3505 Assert(!(HCPhysVmreadBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3506 return VMXWriteVmcs64(VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL, HCPhysVmreadBitmap);
3507}
3508
3509
3510/**
3511 * Sets up the VMWRITE bitmap address for the VMCS.
3512 *
3513 * @returns VBox status code.
3514 * @param pVCpu The cross context virtual CPU structure.
3515 */
3516DECLINLINE(int) hmR0VmxSetupVmcsVmwriteBitmapAddr(PVMCPU pVCpu)
3517{
3518 RTHCPHYS const HCPhysVmwriteBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmwriteBitmap;
3519 Assert(HCPhysVmwriteBitmap != NIL_RTHCPHYS);
3520 Assert(!(HCPhysVmwriteBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3521 return VMXWriteVmcs64(VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL, HCPhysVmwriteBitmap);
3522}
3523#endif
3524
3525
3526/**
3527 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
3528 * in the VMCS.
3529 *
3530 * @returns VBox status code.
3531 * @param pVCpu The cross context virtual CPU structure.
3532 * @param pVmcsInfo The VMCS info. object.
3533 */
3534DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3535{
3536 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
3537
3538 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
3539 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
3540 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3541
3542 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
3543 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
3544 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
3545
3546 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
3547 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
3548 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3549
3550 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad);
3551 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore);
3552 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad);
3553 AssertRCReturn(rc, rc);
3554 return VINF_SUCCESS;
3555}
3556
3557
3558/**
3559 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
3560 *
3561 * @param pVCpu The cross context virtual CPU structure.
3562 * @param pVmcsInfo The VMCS info. object.
3563 */
3564static void hmR0VmxSetupVmcsMsrPermissions(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3565{
3566 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
3567
3568 /*
3569 * The guest can access the following MSRs (read, write) without causing
3570 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
3571 */
3572 PVM pVM = pVCpu->CTX_SUFF(pVM);
3573 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
3574 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
3575 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
3576 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3577 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
3578
3579 /*
3580 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
3581 * associated with then. We never need to intercept access (writes need to be
3582 * executed without causing a VM-exit, reads will #GP fault anyway).
3583 *
3584 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
3585 * read/write them. We swap the the guest/host MSR value using the
3586 * auto-load/store MSR area.
3587 */
3588 if (pVM->cpum.ro.GuestFeatures.fIbpb)
3589 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
3590 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
3591 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
3592 if (pVM->cpum.ro.GuestFeatures.fIbrs)
3593 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
3594
3595#if HC_ARCH_BITS == 64
3596 /*
3597 * Allow full read/write access for the following MSRs (mandatory for VT-x)
3598 * required for 64-bit guests.
3599 */
3600 if (pVM->hm.s.fAllow64BitGuests)
3601 {
3602 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
3603 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
3604 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
3605 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3606 }
3607#endif
3608
3609 /*
3610 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
3611 */
3612#ifdef VBOX_STRICT
3613 Assert(pVmcsInfo->pvMsrBitmap);
3614 uint32_t const fMsrpmEfer = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
3615 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
3616#endif
3617}
3618
3619
3620/**
3621 * Sets up pin-based VM-execution controls in the VMCS.
3622 *
3623 * @returns VBox status code.
3624 * @param pVCpu The cross context virtual CPU structure.
3625 * @param pVmcsInfo The VMCS info. object.
3626 */
3627static int hmR0VmxSetupVmcsPinCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3628{
3629 PVM pVM = pVCpu->CTX_SUFF(pVM);
3630 uint32_t fVal = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0; /* Bits set here must always be set. */
3631 uint32_t const fZap = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
3632
3633 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
3634 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
3635
3636 if (pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
3637 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
3638
3639 /* Enable the VMX-preemption timer. */
3640 if (pVM->hm.s.vmx.fUsePreemptTimer)
3641 {
3642 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
3643 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
3644 }
3645
3646#if 0
3647 /* Enable posted-interrupt processing. */
3648 if (pVM->hm.s.fPostedIntrs)
3649 {
3650 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
3651 Assert(pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
3652 fVal |= VMX_PIN_CTLS_POSTED_INT;
3653 }
3654#endif
3655
3656 if ((fVal & fZap) != fVal)
3657 {
3658 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3659 pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0, fVal, fZap));
3660 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
3661 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3662 }
3663
3664 /* Commit it to the VMCS and update our cache. */
3665 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
3666 AssertRCReturn(rc, rc);
3667 pVmcsInfo->u32PinCtls = fVal;
3668
3669 return VINF_SUCCESS;
3670}
3671
3672
3673/**
3674 * Sets up secondary processor-based VM-execution controls in the VMCS.
3675 *
3676 * @returns VBox status code.
3677 * @param pVCpu The cross context virtual CPU structure.
3678 * @param pVmcsInfo The VMCS info. object.
3679 */
3680static int hmR0VmxSetupVmcsProcCtls2(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3681{
3682 PVM pVM = pVCpu->CTX_SUFF(pVM);
3683 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
3684 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3685
3686 /* WBINVD causes a VM-exit. */
3687 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
3688 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
3689
3690 /* Enable EPT (aka nested-paging). */
3691 if (pVM->hm.s.fNestedPaging)
3692 fVal |= VMX_PROC_CTLS2_EPT;
3693
3694 /* Enable the INVPCID instruction if we expose it to the guest and is supported
3695 by the hardware. Without this, guest executing INVPCID would cause a #UD. */
3696 if ( pVM->cpum.ro.GuestFeatures.fInvpcid
3697 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID))
3698 fVal |= VMX_PROC_CTLS2_INVPCID;
3699
3700 /* Enable VPID. */
3701 if (pVM->hm.s.vmx.fVpid)
3702 fVal |= VMX_PROC_CTLS2_VPID;
3703
3704 /* Enable unrestricted guest execution. */
3705 if (pVM->hm.s.vmx.fUnrestrictedGuest)
3706 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
3707
3708#if 0
3709 if (pVM->hm.s.fVirtApicRegs)
3710 {
3711 /* Enable APIC-register virtualization. */
3712 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
3713 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
3714
3715 /* Enable virtual-interrupt delivery. */
3716 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
3717 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
3718 }
3719#endif
3720
3721 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is
3722 where the TPR shadow resides. */
3723 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
3724 * done dynamically. */
3725 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3726 {
3727 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
3728 int rc = hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3729 AssertRCReturn(rc, rc);
3730 }
3731
3732 /* Enable the RDTSCP instruction if we expose it to the guest and is supported
3733 by the hardware. Without this, guest executing RDTSCP would cause a #UD. */
3734 if ( pVM->cpum.ro.GuestFeatures.fRdTscP
3735 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP))
3736 fVal |= VMX_PROC_CTLS2_RDTSCP;
3737
3738 /* Enable Pause-Loop exiting. */
3739 if ( (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
3740 && pVM->hm.s.vmx.cPleGapTicks
3741 && pVM->hm.s.vmx.cPleWindowTicks)
3742 {
3743 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3744
3745 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks);
3746 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks);
3747 AssertRCReturn(rc, rc);
3748 }
3749
3750 if ((fVal & fZap) != fVal)
3751 {
3752 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3753 pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0, fVal, fZap));
3754 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3755 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3756 }
3757
3758 /* Commit it to the VMCS and update our cache. */
3759 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3760 AssertRCReturn(rc, rc);
3761 pVmcsInfo->u32ProcCtls2 = fVal;
3762
3763 return VINF_SUCCESS;
3764}
3765
3766
3767/**
3768 * Sets up processor-based VM-execution controls in the VMCS.
3769 *
3770 * @returns VBox status code.
3771 * @param pVCpu The cross context virtual CPU structure.
3772 * @param pVmcsInfo The VMCS info. object.
3773 */
3774static int hmR0VmxSetupVmcsProcCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3775{
3776 PVM pVM = pVCpu->CTX_SUFF(pVM);
3777
3778 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3779 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3780
3781 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3782 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3783 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3784 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3785 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3786 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3787 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3788
3789 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3790 if ( !(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3791 || (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3792 {
3793 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3794 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3795 }
3796
3797 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3798 if (!pVM->hm.s.fNestedPaging)
3799 {
3800 Assert(!pVM->hm.s.vmx.fUnrestrictedGuest);
3801 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3802 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3803 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3804 }
3805
3806 /* Use TPR shadowing if supported by the CPU. */
3807 if ( PDMHasApic(pVM)
3808 && pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
3809 {
3810 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
3811 /* CR8 writes cause a VM-exit based on TPR threshold. */
3812 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
3813 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
3814 int rc = hmR0VmxSetupVmcsVirtApicAddr(pVCpu, pVmcsInfo);
3815 AssertRCReturn(rc, rc);
3816 }
3817 else
3818 {
3819 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
3820 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
3821 if (pVM->hm.s.fAllow64BitGuests)
3822 {
3823 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
3824 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
3825 }
3826 }
3827
3828 /* Use MSR-bitmaps if supported by the CPU. */
3829 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3830 {
3831 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
3832 int rc = hmR0VmxSetupVmcsMsrBitmapAddr(pVCpu, pVmcsInfo);
3833 AssertRCReturn(rc, rc);
3834 }
3835
3836 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
3837 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3838 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
3839
3840 if ((fVal & fZap) != fVal)
3841 {
3842 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3843 pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0, fVal, fZap));
3844 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
3845 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3846 }
3847
3848 /* Commit it to the VMCS and update our cache. */
3849 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, fVal);
3850 AssertRCReturn(rc, rc);
3851 pVmcsInfo->u32ProcCtls = fVal;
3852
3853 /* Set up MSR permissions that don't change through the lifetime of the VM. */
3854 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3855 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo);
3856
3857 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
3858 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3859 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
3860
3861 /* Sanity check, should not really happen. */
3862 if (RT_LIKELY(!pVM->hm.s.vmx.fUnrestrictedGuest))
3863 { /* likely */ }
3864 else
3865 {
3866 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
3867 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3868 }
3869
3870 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
3871 return VINF_SUCCESS;
3872}
3873
3874
3875/**
3876 * Sets up miscellaneous (everything other than Pin, Processor and secondary
3877 * Processor-based VM-execution) control fields in the VMCS.
3878 *
3879 * @returns VBox status code.
3880 * @param pVCpu The cross context virtual CPU structure.
3881 * @param pVmcsInfo The VMCS info. object.
3882 */
3883static int hmR0VmxSetupVmcsMiscCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3884{
3885#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3886 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
3887 {
3888 int rc = hmR0VmxSetupVmcsVmreadBitmapAddr(pVCpu);
3889 rc |= hmR0VmxSetupVmcsVmwriteBitmapAddr(pVCpu);
3890 if (RT_SUCCESS(rc))
3891 { /* likely */ }
3892 else
3893 {
3894 LogRelFunc(("Failed to setup VMREAD/VMWRITE bitmap addresses. rc=%Rrc\n", rc));
3895 return rc;
3896 }
3897 }
3898#endif
3899
3900 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3901 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3902 if (RT_SUCCESS(rc))
3903 {
3904 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVCpu, pVmcsInfo);
3905 if (RT_SUCCESS(rc))
3906 {
3907 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
3908 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
3909 rc = VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
3910 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
3911 if (RT_SUCCESS(rc))
3912 {
3913 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
3914 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
3915 return VINF_SUCCESS;
3916 }
3917 LogRelFunc(("Failed to initialize VMCS CR0/CR4 guest/host mask. rc=%Rrc\n", rc));
3918 }
3919 else
3920 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
3921 }
3922 else
3923 LogRelFunc(("Failed to initialize VMCS link pointer. rc=%Rrc\n", rc));
3924 return rc;
3925}
3926
3927
3928/**
3929 * Sets up the initial exception bitmap in the VMCS based on static conditions.
3930 *
3931 * We shall setup those exception intercepts that don't change during the
3932 * lifetime of the VM here. The rest are done dynamically while loading the
3933 * guest state.
3934 *
3935 * @returns VBox status code.
3936 * @param pVCpu The cross context virtual CPU structure.
3937 * @param pVmcsInfo The VMCS info. object.
3938 */
3939static int hmR0VmxSetupVmcsXcptBitmap(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3940{
3941 /*
3942 * The following exceptions are always intercepted:
3943 *
3944 * #AC - To prevent the guest from hanging the CPU.
3945 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
3946 * recursive #DBs can cause a CPU hang.
3947 * #PF - To sync our shadow page tables when nested-paging is not used.
3948 */
3949 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging;
3950 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
3951 | RT_BIT(X86_XCPT_DB)
3952 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
3953
3954 /* Commit it to the VMCS. */
3955 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
3956 AssertRCReturn(rc, rc);
3957
3958 /* Update our cache of the exception bitmap. */
3959 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
3960 return VINF_SUCCESS;
3961}
3962
3963
3964#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3965/**
3966 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
3967 *
3968 * @returns VBox status code.
3969 * @param pVCpu The cross context virtual CPU structure.
3970 * @param pVmcsInfo The VMCS info. object.
3971 */
3972static int hmR0VmxSetupVmcsCtlsNested(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3973{
3974 PVM pVM = pVCpu->CTX_SUFF(pVM);
3975 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3976 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3977 if (RT_SUCCESS(rc))
3978 {
3979 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVCpu, pVmcsInfo);
3980 if (RT_SUCCESS(rc))
3981 {
3982 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3983 rc = hmR0VmxSetupVmcsMsrBitmapAddr(pVCpu, pVmcsInfo);
3984 if (RT_SUCCESS(rc))
3985 {
3986 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3987 rc = hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3988 if (RT_SUCCESS(rc))
3989 return VINF_SUCCESS;
3990
3991 LogRelFunc(("Failed to set up the APIC-access address in the nested-guest VMCS. rc=%Rrc\n", rc));
3992 }
3993 else
3994 LogRelFunc(("Failed to set up the MSR-bitmap address in the nested-guest VMCS. rc=%Rrc\n", rc));
3995 }
3996 else
3997 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
3998 }
3999 else
4000 LogRelFunc(("Failed to set up the auto-load/store MSR addresses in the nested-guest VMCS. rc=%Rrc\n", rc));
4001
4002 return rc;
4003}
4004#endif
4005
4006
4007/**
4008 * Sets up the VMCS for executing a guest (or nested-guest) using hardware-assisted
4009 * VMX.
4010 *
4011 * @returns VBox status code.
4012 * @param pVCpu The cross context virtual CPU structure.
4013 * @param pVmcsInfo The VMCS info. object.
4014 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
4015 */
4016static int hmR0VmxSetupVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
4017{
4018 Assert(pVmcsInfo->pvVmcs);
4019 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4020
4021 /* Set the CPU specified revision identifier at the beginning of the VMCS structure. */
4022 PVM pVM = pVCpu->CTX_SUFF(pVM);
4023 *(uint32_t *)pVmcsInfo->pvVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
4024 const char * const pszVmcs = fIsNstGstVmcs ? "nested-guest VMCS" : "guest VMCS";
4025
4026 LogFlowFunc(("\n"));
4027
4028 /*
4029 * Initialize the VMCS using VMCLEAR before loading the VMCS.
4030 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
4031 */
4032 int rc = hmR0VmxClearVmcs(pVmcsInfo);
4033 if (RT_SUCCESS(rc))
4034 {
4035 rc = hmR0VmxLoadVmcs(pVmcsInfo);
4036 if (RT_SUCCESS(rc))
4037 {
4038 if (!fIsNstGstVmcs)
4039 {
4040 rc = hmR0VmxSetupVmcsPinCtls(pVCpu, pVmcsInfo);
4041 if (RT_SUCCESS(rc))
4042 {
4043 rc = hmR0VmxSetupVmcsProcCtls(pVCpu, pVmcsInfo);
4044 if (RT_SUCCESS(rc))
4045 {
4046 rc = hmR0VmxSetupVmcsMiscCtls(pVCpu, pVmcsInfo);
4047 if (RT_SUCCESS(rc))
4048 {
4049 rc = hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
4050 if (RT_SUCCESS(rc))
4051 {
4052#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4053 /*
4054 * If a shadow VMCS is allocated for the VMCS info. object, initialize the
4055 * VMCS revision ID and shadow VMCS indicator bit. Also, clear the VMCS
4056 * making it fit for use when VMCS shadowing is later enabled.
4057 */
4058 if (pVmcsInfo->pvShadowVmcs)
4059 {
4060 VMXVMCSREVID VmcsRevId;
4061 VmcsRevId.u = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
4062 VmcsRevId.n.fIsShadowVmcs = 1;
4063 *(uint32_t *)pVmcsInfo->pvShadowVmcs = VmcsRevId.u;
4064 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
4065 if (RT_SUCCESS(rc))
4066 { /* likely */ }
4067 else
4068 LogRelFunc(("Failed to initialize shadow VMCS. rc=%Rrc\n", rc));
4069 }
4070#endif
4071 }
4072 else
4073 LogRelFunc(("Failed to initialize exception bitmap. rc=%Rrc\n", rc));
4074 }
4075 else
4076 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
4077 }
4078 else
4079 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
4080 }
4081 else
4082 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
4083 }
4084 else
4085 {
4086#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4087 rc = hmR0VmxSetupVmcsCtlsNested(pVCpu, pVmcsInfo);
4088 if (RT_SUCCESS(rc))
4089 { /* likely */ }
4090 else
4091 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
4092#else
4093 AssertFailed();
4094#endif
4095 }
4096 }
4097 else
4098 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
4099 }
4100 else
4101 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
4102
4103 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
4104 if (RT_SUCCESS(rc))
4105 {
4106 rc = hmR0VmxClearVmcs(pVmcsInfo);
4107 if (RT_SUCCESS(rc))
4108 { /* likely */ }
4109 else
4110 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
4111 }
4112
4113 /*
4114 * Update the last-error record both for failures and success, so we
4115 * can propagate the status code back to ring-3 for diagnostics.
4116 */
4117 hmR0VmxUpdateErrorRecord(pVCpu, rc);
4118 NOREF(pszVmcs);
4119 return rc;
4120}
4121
4122
4123/**
4124 * Does global VT-x initialization (called during module initialization).
4125 *
4126 * @returns VBox status code.
4127 */
4128VMMR0DECL(int) VMXR0GlobalInit(void)
4129{
4130#ifdef HMVMX_USE_FUNCTION_TABLE
4131 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_apfnVMExitHandlers));
4132# ifdef VBOX_STRICT
4133 for (unsigned i = 0; i < RT_ELEMENTS(g_apfnVMExitHandlers); i++)
4134 Assert(g_apfnVMExitHandlers[i]);
4135# endif
4136#endif
4137 return VINF_SUCCESS;
4138}
4139
4140
4141/**
4142 * Does global VT-x termination (called during module termination).
4143 */
4144VMMR0DECL(void) VMXR0GlobalTerm()
4145{
4146 /* Nothing to do currently. */
4147}
4148
4149
4150/**
4151 * Sets up and activates VT-x on the current CPU.
4152 *
4153 * @returns VBox status code.
4154 * @param pHostCpu The HM physical-CPU structure.
4155 * @param pVM The cross context VM structure. Can be
4156 * NULL after a host resume operation.
4157 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
4158 * fEnabledByHost is @c true).
4159 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
4160 * @a fEnabledByHost is @c true).
4161 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
4162 * enable VT-x on the host.
4163 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
4164 */
4165VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVM pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
4166 PCSUPHWVIRTMSRS pHwvirtMsrs)
4167{
4168 AssertPtr(pHostCpu);
4169 AssertPtr(pHwvirtMsrs);
4170 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4171
4172 /* Enable VT-x if it's not already enabled by the host. */
4173 if (!fEnabledByHost)
4174 {
4175 int rc = hmR0VmxEnterRootMode(pVM, HCPhysCpuPage, pvCpuPage);
4176 if (RT_FAILURE(rc))
4177 return rc;
4178 }
4179
4180 /*
4181 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
4182 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
4183 * invalidated when flushing by VPID.
4184 */
4185 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
4186 {
4187 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
4188 pHostCpu->fFlushAsidBeforeUse = false;
4189 }
4190 else
4191 pHostCpu->fFlushAsidBeforeUse = true;
4192
4193 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
4194 ++pHostCpu->cTlbFlushes;
4195
4196 return VINF_SUCCESS;
4197}
4198
4199
4200/**
4201 * Deactivates VT-x on the current CPU.
4202 *
4203 * @returns VBox status code.
4204 * @param pvCpuPage Pointer to the VMXON region.
4205 * @param HCPhysCpuPage Physical address of the VMXON region.
4206 *
4207 * @remarks This function should never be called when SUPR0EnableVTx() or
4208 * similar was used to enable VT-x on the host.
4209 */
4210VMMR0DECL(int) VMXR0DisableCpu(void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
4211{
4212 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
4213
4214 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4215 return hmR0VmxLeaveRootMode();
4216}
4217
4218
4219/**
4220 * Does per-VM VT-x initialization.
4221 *
4222 * @returns VBox status code.
4223 * @param pVM The cross context VM structure.
4224 */
4225VMMR0DECL(int) VMXR0InitVM(PVM pVM)
4226{
4227 AssertPtr(pVM);
4228 LogFlowFunc(("pVM=%p\n", pVM));
4229
4230 int rc = hmR0VmxStructsAlloc(pVM);
4231 if (RT_FAILURE(rc))
4232 {
4233 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
4234 return rc;
4235 }
4236
4237 return VINF_SUCCESS;
4238}
4239
4240
4241/**
4242 * Does per-VM VT-x termination.
4243 *
4244 * @returns VBox status code.
4245 * @param pVM The cross context VM structure.
4246 */
4247VMMR0DECL(int) VMXR0TermVM(PVM pVM)
4248{
4249 AssertPtr(pVM);
4250 LogFlowFunc(("pVM=%p\n", pVM));
4251
4252#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4253 if (pVM->hm.s.vmx.hMemObjScratch != NIL_RTR0MEMOBJ)
4254 {
4255 Assert(pVM->hm.s.vmx.pvScratch);
4256 ASMMemZero32(pVM->hm.s.vmx.pvScratch, X86_PAGE_4K_SIZE);
4257 }
4258#endif
4259 hmR0VmxStructsFree(pVM);
4260 return VINF_SUCCESS;
4261}
4262
4263
4264/**
4265 * Sets up the VM for execution using hardware-assisted VMX.
4266 * This function is only called once per-VM during initialization.
4267 *
4268 * @returns VBox status code.
4269 * @param pVM The cross context VM structure.
4270 */
4271VMMR0DECL(int) VMXR0SetupVM(PVM pVM)
4272{
4273 AssertPtr(pVM);
4274 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4275
4276 LogFlowFunc(("pVM=%p\n", pVM));
4277
4278 /*
4279 * At least verify if VMX is enabled, since we can't check if we're in
4280 * VMX root mode or not without causing a #GP.
4281 */
4282 RTCCUINTREG const uHostCr4 = ASMGetCR4();
4283 if (RT_LIKELY(uHostCr4 & X86_CR4_VMXE))
4284 { /* likely */ }
4285 else
4286 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
4287
4288 /*
4289 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
4290 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
4291 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
4292 */
4293 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
4294 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
4295 || !pVM->hm.s.vmx.pRealModeTSS))
4296 {
4297 LogRelFunc(("Invalid real-on-v86 state.\n"));
4298 return VERR_INTERNAL_ERROR;
4299 }
4300
4301 /* Initialize these always, see hmR3InitFinalizeR0().*/
4302 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
4303 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
4304
4305 /* Setup the tagged-TLB flush handlers. */
4306 int rc = hmR0VmxSetupTaggedTlb(pVM);
4307 if (RT_FAILURE(rc))
4308 {
4309 LogRelFunc(("Failed to setup tagged TLB. rc=%Rrc\n", rc));
4310 return rc;
4311 }
4312
4313#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4314 /* Setup the shadow VMCS fields array and VMREAD/VMWRITE bitmaps. */
4315 if (pVM->hm.s.vmx.fUseVmcsShadowing)
4316 {
4317 rc = hmR0VmxSetupShadowVmcsFieldsArrays(pVM);
4318 if (RT_SUCCESS(rc))
4319 hmR0VmxSetupVmreadVmwriteBitmaps(pVM);
4320 else
4321 {
4322 LogRelFunc(("Failed to setup shadow VMCS fields arrays. rc=%Rrc\n", rc));
4323 return rc;
4324 }
4325 }
4326#endif
4327
4328 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4329 {
4330 PVMCPU pVCpu = &pVM->aCpus[idCpu];
4331 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
4332
4333 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
4334 if (RT_SUCCESS(rc))
4335 {
4336#if HC_ARCH_BITS == 32
4337 hmR0VmxInitVmcsReadCache(pVCpu);
4338#endif
4339#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4340 if (pVM->cpum.ro.GuestFeatures.fVmx)
4341 {
4342 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
4343 if (RT_SUCCESS(rc))
4344 { /* likely */ }
4345 else
4346 {
4347 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
4348 return rc;
4349 }
4350 }
4351#endif
4352 }
4353 else
4354 {
4355 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
4356 return rc;
4357 }
4358 }
4359
4360 return VINF_SUCCESS;
4361}
4362
4363
4364#if HC_ARCH_BITS == 32
4365# ifdef VBOX_ENABLE_64_BITS_GUESTS
4366/**
4367 * Check if guest state allows safe use of 32-bit switcher again.
4368 *
4369 * Segment bases and protected mode structures must be 32-bit addressable
4370 * because the 32-bit switcher will ignore high dword when writing these VMCS
4371 * fields. See @bugref{8432} for details.
4372 *
4373 * @returns true if safe, false if must continue to use the 64-bit switcher.
4374 * @param pCtx Pointer to the guest-CPU context.
4375 *
4376 * @remarks No-long-jump zone!!!
4377 */
4378static bool hmR0VmxIs32BitSwitcherSafe(PCCPUMCTX pCtx)
4379{
4380 if (pCtx->gdtr.pGdt & UINT64_C(0xffffffff00000000)) return false;
4381 if (pCtx->idtr.pIdt & UINT64_C(0xffffffff00000000)) return false;
4382 if (pCtx->ldtr.u64Base & UINT64_C(0xffffffff00000000)) return false;
4383 if (pCtx->tr.u64Base & UINT64_C(0xffffffff00000000)) return false;
4384 if (pCtx->es.u64Base & UINT64_C(0xffffffff00000000)) return false;
4385 if (pCtx->cs.u64Base & UINT64_C(0xffffffff00000000)) return false;
4386 if (pCtx->ss.u64Base & UINT64_C(0xffffffff00000000)) return false;
4387 if (pCtx->ds.u64Base & UINT64_C(0xffffffff00000000)) return false;
4388 if (pCtx->fs.u64Base & UINT64_C(0xffffffff00000000)) return false;
4389 if (pCtx->gs.u64Base & UINT64_C(0xffffffff00000000)) return false;
4390
4391 /* All good, bases are 32-bit. */
4392 return true;
4393}
4394# endif /* VBOX_ENABLE_64_BITS_GUESTS */
4395
4396# ifdef VBOX_STRICT
4397static bool hmR0VmxIsValidWriteFieldInCache(uint32_t idxField)
4398{
4399 switch (idxField)
4400 {
4401 case VMX_VMCS_GUEST_RIP:
4402 case VMX_VMCS_GUEST_RSP:
4403 case VMX_VMCS_GUEST_SYSENTER_EIP:
4404 case VMX_VMCS_GUEST_SYSENTER_ESP:
4405 case VMX_VMCS_GUEST_GDTR_BASE:
4406 case VMX_VMCS_GUEST_IDTR_BASE:
4407 case VMX_VMCS_GUEST_CS_BASE:
4408 case VMX_VMCS_GUEST_DS_BASE:
4409 case VMX_VMCS_GUEST_ES_BASE:
4410 case VMX_VMCS_GUEST_FS_BASE:
4411 case VMX_VMCS_GUEST_GS_BASE:
4412 case VMX_VMCS_GUEST_SS_BASE:
4413 case VMX_VMCS_GUEST_LDTR_BASE:
4414 case VMX_VMCS_GUEST_TR_BASE:
4415 case VMX_VMCS_GUEST_CR3:
4416 return true;
4417 }
4418 return false;
4419}
4420
4421static bool hmR0VmxIsValidReadFieldInCache(uint32_t idxField)
4422{
4423 switch (idxField)
4424 {
4425 /* Read-only fields. */
4426 case VMX_VMCS_RO_EXIT_QUALIFICATION:
4427 return true;
4428 }
4429 /* Remaining readable fields should also be writable. */
4430 return hmR0VmxIsValidWriteFieldInCache(idxField);
4431}
4432# endif /* VBOX_STRICT */
4433
4434
4435/**
4436 * Executes the specified handler in 64-bit mode.
4437 *
4438 * @returns VBox status code (no informational status codes).
4439 * @param pVCpu The cross context virtual CPU structure.
4440 * @param enmOp The operation to perform.
4441 * @param cParams Number of parameters.
4442 * @param paParam Array of 32-bit parameters.
4443 */
4444VMMR0DECL(int) VMXR0Execute64BitsHandler(PVMCPU pVCpu, HM64ON32OP enmOp, uint32_t cParams, uint32_t *paParam)
4445{
4446 AssertPtr(pVCpu);
4447 PVM pVM = pVCpu->CTX_SUFF(pVM);
4448 AssertReturn(pVM->hm.s.pfnHost32ToGuest64R0, VERR_HM_NO_32_TO_64_SWITCHER);
4449 Assert(enmOp > HM64ON32OP_INVALID && enmOp < HM64ON32OP_END);
4450 Assert(pVCpu->hm.s.vmx.VmcsCache.Write.cValidEntries <= RT_ELEMENTS(pVCpu->hm.s.vmx.VmcsCache.Write.aField));
4451 Assert(pVCpu->hm.s.vmx.VmcsCache.Read.cValidEntries <= RT_ELEMENTS(pVCpu->hm.s.vmx.VmcsCache.Read.aField));
4452
4453#ifdef VBOX_STRICT
4454 for (uint32_t i = 0; i < pVCpu->hm.s.vmx.VmcsCache.Write.cValidEntries; i++)
4455 Assert(hmR0VmxIsValidWriteFieldInCache(pVCpu->hm.s.vmx.VmcsCache.Write.aField[i]));
4456
4457 for (uint32_t i = 0; i <pVCpu->hm.s.vmx.VmcsCache.Read.cValidEntries; i++)
4458 Assert(hmR0VmxIsValidReadFieldInCache(pVCpu->hm.s.vmx.VmcsCache.Read.aField[i]));
4459#endif
4460
4461 /* Disable interrupts. */
4462 RTCCUINTREG fOldEFlags = ASMIntDisableFlags();
4463
4464#ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
4465 RTCPUID idHostCpu = RTMpCpuId();
4466 CPUMR0SetLApic(pVCpu, idHostCpu);
4467#endif
4468
4469 /** @todo replace with hmR0VmxEnterRootMode() and hmR0VmxLeaveRootMode(). */
4470
4471 PCHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
4472 RTHCPHYS const HCPhysCpuPage = pHostCpu->HCPhysMemObj;
4473
4474 /* Clear VMCS. Marking it inactive, clearing implementation-specific data and writing VMCS data back to memory. */
4475 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
4476 hmR0VmxClearVmcs(pVmcsInfo);
4477
4478 /* Leave VMX root mode and disable VMX. */
4479 VMXDisable();
4480 SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
4481
4482 CPUMSetHyperESP(pVCpu, VMMGetStackRC(pVCpu));
4483 CPUMSetHyperEIP(pVCpu, enmOp);
4484 for (int i = (int)cParams - 1; i >= 0; i--)
4485 CPUMPushHyper(pVCpu, paParam[i]);
4486
4487 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatWorldSwitch3264, z);
4488
4489 /* Call the switcher. */
4490 int rc = pVM->hm.s.pfnHost32ToGuest64R0(pVM, RT_UOFFSETOF_DYN(VM, aCpus[pVCpu->idCpu].cpum) - RT_UOFFSETOF(VM, cpum));
4491 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatWorldSwitch3264, z);
4492
4493 /* Re-enable VMX to make sure the VMX instructions don't cause #UD faults. */
4494 SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
4495
4496 /* Re-enter VMX root mode. */
4497 int rc2 = VMXEnable(HCPhysCpuPage);
4498 if (RT_FAILURE(rc2))
4499 {
4500 SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
4501 ASMSetFlags(fOldEFlags);
4502 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
4503 return rc2;
4504 }
4505
4506 /* Restore the VMCS as the current VMCS. */
4507 rc2 = hmR0VmxLoadVmcs(pVmcsInfo);
4508 AssertRC(rc2);
4509 Assert(!(ASMGetFlags() & X86_EFL_IF));
4510 ASMSetFlags(fOldEFlags);
4511 return rc;
4512}
4513
4514
4515/**
4516 * Prepares for and executes VMLAUNCH (64-bit guests) for 32-bit hosts
4517 * supporting 64-bit guests.
4518 *
4519 * @returns VBox status code.
4520 * @param fResume Whether to VMLAUNCH or VMRESUME.
4521 * @param pCtx Pointer to the guest-CPU context.
4522 * @param pCache Pointer to the VMCS batch cache.
4523 * @param pVM The cross context VM structure.
4524 * @param pVCpu The cross context virtual CPU structure.
4525 */
4526DECLASM(int) VMXR0SwitcherStartVM64(RTHCUINT fResume, PCPUMCTX pCtx, PVMXVMCSCACHE pCache, PVM pVM, PVMCPU pVCpu)
4527{
4528 NOREF(fResume);
4529
4530 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
4531 PCHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
4532 RTHCPHYS const HCPhysCpuPage = pHostCpu->HCPhysMemObj;
4533
4534#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4535 pCache->uPos = 1;
4536 pCache->interPD = PGMGetInterPaeCR3(pVM);
4537 pCache->pSwitcher = (uint64_t)pVM->hm.s.pfnHost32ToGuest64R0;
4538#endif
4539
4540#if defined(DEBUG) && defined(VMX_USE_CACHED_VMCS_ACCESSES)
4541 pCache->TestIn.HCPhysCpuPage = 0;
4542 pCache->TestIn.HCPhysVmcs = 0;
4543 pCache->TestIn.pCache = 0;
4544 pCache->TestOut.HCPhysVmcs = 0;
4545 pCache->TestOut.pCache = 0;
4546 pCache->TestOut.pCtx = 0;
4547 pCache->TestOut.eflags = 0;
4548#else
4549 NOREF(pCache);
4550#endif
4551
4552 uint32_t aParam[10];
4553 aParam[0] = RT_LO_U32(HCPhysCpuPage); /* Param 1: VMXON physical address - Lo. */
4554 aParam[1] = RT_HI_U32(HCPhysCpuPage); /* Param 1: VMXON physical address - Hi. */
4555 aParam[2] = RT_LO_U32(pVmcsInfo->HCPhysVmcs); /* Param 2: VMCS physical address - Lo. */
4556 aParam[3] = RT_HI_U32(pVmcsInfo->HCPhysVmcs); /* Param 2: VMCS physical address - Hi. */
4557 aParam[4] = VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VmcsCache);
4558 aParam[5] = 0;
4559 aParam[6] = VM_RC_ADDR(pVM, pVM);
4560 aParam[7] = 0;
4561 aParam[8] = VM_RC_ADDR(pVM, pVCpu);
4562 aParam[9] = 0;
4563
4564#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4565 pCtx->dr[4] = pVM->hm.s.vmx.pScratchPhys + 16 + 8;
4566 *(uint32_t *)(pVM->hm.s.vmx.pScratch + 16 + 8) = 1;
4567#endif
4568 int rc = VMXR0Execute64BitsHandler(pVCpu, HM64ON32OP_VMXRCStartVM64, RT_ELEMENTS(aParam), &aParam[0]);
4569
4570#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4571 Assert(*(uint32_t *)(pVM->hm.s.vmx.pScratch + 16 + 8) == 5);
4572 Assert(pCtx->dr[4] == 10);
4573 *(uint32_t *)(pVM->hm.s.vmx.pScratch + 16 + 8) = 0xff;
4574#endif
4575
4576#if defined(DEBUG) && defined(VMX_USE_CACHED_VMCS_ACCESSES)
4577 AssertMsg(pCache->TestIn.HCPhysCpuPage == HCPhysCpuPage, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysCpuPage, HCPhysCpuPage));
4578 AssertMsg(pCache->TestIn.HCPhysVmcs == pVmcsInfo->HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs,
4579 pVmcsInfo->HCPhysVmcs));
4580 AssertMsg(pCache->TestIn.HCPhysVmcs == pCache->TestOut.HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs,
4581 pCache->TestOut.HCPhysVmcs));
4582 AssertMsg(pCache->TestIn.pCache == pCache->TestOut.pCache, ("%RGv vs %RGv\n", pCache->TestIn.pCache,
4583 pCache->TestOut.pCache));
4584 AssertMsg(pCache->TestIn.pCache == VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VmcsCache),
4585 ("%RGv vs %RGv\n", pCache->TestIn.pCache, VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VmcsCache)));
4586 AssertMsg(pCache->TestIn.pCtx == pCache->TestOut.pCtx, ("%RGv vs %RGv\n", pCache->TestIn.pCtx,
4587 pCache->TestOut.pCtx));
4588 Assert(!(pCache->TestOut.eflags & X86_EFL_IF));
4589#endif
4590 NOREF(pCtx);
4591 return rc;
4592}
4593#endif
4594
4595
4596/**
4597 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
4598 * the VMCS.
4599 *
4600 * @returns VBox status code.
4601 */
4602static int hmR0VmxExportHostControlRegs(void)
4603{
4604 RTCCUINTREG uReg = ASMGetCR0();
4605 int rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_CR0, uReg);
4606 AssertRCReturn(rc, rc);
4607
4608 uReg = ASMGetCR3();
4609 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_CR3, uReg);
4610 AssertRCReturn(rc, rc);
4611
4612 uReg = ASMGetCR4();
4613 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_CR4, uReg);
4614 AssertRCReturn(rc, rc);
4615 return rc;
4616}
4617
4618
4619/**
4620 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
4621 * the host-state area in the VMCS.
4622 *
4623 * @returns VBox status code.
4624 * @param pVCpu The cross context virtual CPU structure.
4625 */
4626static int hmR0VmxExportHostSegmentRegs(PVMCPU pVCpu)
4627{
4628#if HC_ARCH_BITS == 64
4629/**
4630 * Macro for adjusting host segment selectors to satisfy VT-x's VM-entry
4631 * requirements. See hmR0VmxExportHostSegmentRegs().
4632 */
4633# define VMXLOCAL_ADJUST_HOST_SEG(seg, selValue) \
4634 if ((selValue) & (X86_SEL_RPL | X86_SEL_LDT)) \
4635 { \
4636 bool fValidSelector = true; \
4637 if ((selValue) & X86_SEL_LDT) \
4638 { \
4639 uint32_t uAttr = ASMGetSegAttr((selValue)); \
4640 fValidSelector = RT_BOOL(uAttr != UINT32_MAX && (uAttr & X86_DESC_P)); \
4641 } \
4642 if (fValidSelector) \
4643 { \
4644 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##seg; \
4645 pVCpu->hm.s.vmx.RestoreHost.uHostSel##seg = (selValue); \
4646 } \
4647 (selValue) = 0; \
4648 }
4649
4650 /*
4651 * If we've executed guest code using hardware-assisted VMX, the host-state bits
4652 * will be messed up. We should -not- save the messed up state without restoring
4653 * the original host-state, see @bugref{7240}.
4654 *
4655 * This apparently can happen (most likely the FPU changes), deal with it rather than
4656 * asserting. Was observed booting Solaris 10u10 32-bit guest.
4657 */
4658 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
4659 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
4660 {
4661 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags,
4662 pVCpu->idCpu));
4663 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
4664 }
4665 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
4666#else
4667 RT_NOREF(pVCpu);
4668#endif
4669
4670 /*
4671 * Host DS, ES, FS and GS segment registers.
4672 */
4673#if HC_ARCH_BITS == 64
4674 RTSEL uSelDS = ASMGetDS();
4675 RTSEL uSelES = ASMGetES();
4676 RTSEL uSelFS = ASMGetFS();
4677 RTSEL uSelGS = ASMGetGS();
4678#else
4679 RTSEL uSelDS = 0;
4680 RTSEL uSelES = 0;
4681 RTSEL uSelFS = 0;
4682 RTSEL uSelGS = 0;
4683#endif
4684
4685 /*
4686 * Host CS and SS segment registers.
4687 */
4688 RTSEL uSelCS = ASMGetCS();
4689 RTSEL uSelSS = ASMGetSS();
4690
4691 /*
4692 * Host TR segment register.
4693 */
4694 RTSEL uSelTR = ASMGetTR();
4695
4696#if HC_ARCH_BITS == 64
4697 /*
4698 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
4699 * gain VM-entry and restore them before we get preempted.
4700 *
4701 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
4702 */
4703 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4704 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4705 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4706 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4707# undef VMXLOCAL_ADJUST_HOST_SEG
4708#endif
4709
4710 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
4711 Assert(!(uSelCS & X86_SEL_RPL)); Assert(!(uSelCS & X86_SEL_LDT));
4712 Assert(!(uSelSS & X86_SEL_RPL)); Assert(!(uSelSS & X86_SEL_LDT));
4713 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
4714 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
4715 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
4716 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
4717 Assert(!(uSelTR & X86_SEL_RPL)); Assert(!(uSelTR & X86_SEL_LDT));
4718 Assert(uSelCS);
4719 Assert(uSelTR);
4720
4721 /* Write these host selector fields into the host-state area in the VMCS. */
4722 int rc = VMXWriteVmcs32(VMX_VMCS16_HOST_CS_SEL, uSelCS);
4723 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_SS_SEL, uSelSS);
4724#if HC_ARCH_BITS == 64
4725 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_DS_SEL, uSelDS);
4726 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_ES_SEL, uSelES);
4727 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_FS_SEL, uSelFS);
4728 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_GS_SEL, uSelGS);
4729#else
4730 NOREF(uSelDS);
4731 NOREF(uSelES);
4732 NOREF(uSelFS);
4733 NOREF(uSelGS);
4734#endif
4735 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_TR_SEL, uSelTR);
4736 AssertRCReturn(rc, rc);
4737
4738 /*
4739 * Host GDTR and IDTR.
4740 */
4741 RTGDTR Gdtr;
4742 RTIDTR Idtr;
4743 RT_ZERO(Gdtr);
4744 RT_ZERO(Idtr);
4745 ASMGetGDTR(&Gdtr);
4746 ASMGetIDTR(&Idtr);
4747 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_GDTR_BASE, Gdtr.pGdt);
4748 rc |= VMXWriteVmcsHstN(VMX_VMCS_HOST_IDTR_BASE, Idtr.pIdt);
4749 AssertRCReturn(rc, rc);
4750
4751#if HC_ARCH_BITS == 64
4752 /*
4753 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
4754 * them to the maximum limit (0xffff) on every VM-exit.
4755 */
4756 if (Gdtr.cbGdt != 0xffff)
4757 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
4758
4759 /*
4760 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
4761 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
4762 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
4763 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
4764 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
4765 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
4766 * at 0xffff on hosts where we are sure it won't cause trouble.
4767 */
4768# if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
4769 if (Idtr.cbIdt < 0x0fff)
4770# else
4771 if (Idtr.cbIdt != 0xffff)
4772# endif
4773 {
4774 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4775 AssertCompile(sizeof(Idtr) == sizeof(X86XDTR64));
4776 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostIdtr, &Idtr, sizeof(X86XDTR64));
4777 }
4778#endif
4779
4780 /*
4781 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4782 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4783 * RPL should be too in most cases.
4784 */
4785 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= Gdtr.cbGdt,
4786 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, Gdtr.cbGdt), VERR_VMX_INVALID_HOST_STATE);
4787
4788 PCX86DESCHC pDesc = (PCX86DESCHC)(Gdtr.pGdt + (uSelTR & X86_SEL_MASK));
4789#if HC_ARCH_BITS == 64
4790 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4791
4792 /*
4793 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4794 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4795 * restoration if the host has something else. Task switching is not supported in 64-bit
4796 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4797 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4798 *
4799 * [1] See Intel spec. 3.5 "System Descriptor Types".
4800 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4801 */
4802 PVM pVM = pVCpu->CTX_SUFF(pVM);
4803 Assert(pDesc->System.u4Type == 11);
4804 if ( pDesc->System.u16LimitLow != 0x67
4805 || pDesc->System.u4LimitHigh)
4806 {
4807 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4808 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4809 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4810 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4811 pVCpu->hm.s.vmx.RestoreHost.uHostSelTR = uSelTR;
4812 }
4813
4814 /*
4815 * Store the GDTR as we need it when restoring the GDT and while restoring the TR.
4816 */
4817 if (pVCpu->hm.s.vmx.fRestoreHostFlags & (VMX_RESTORE_HOST_GDTR | VMX_RESTORE_HOST_SEL_TR))
4818 {
4819 AssertCompile(sizeof(Gdtr) == sizeof(X86XDTR64));
4820 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostGdtr, &Gdtr, sizeof(X86XDTR64));
4821 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4822 {
4823 /* The GDT is read-only but the writable GDT is available. */
4824 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4825 pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.cb = Gdtr.cbGdt;
4826 rc = SUPR0GetCurrentGdtRw(&pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4827 AssertRCReturn(rc, rc);
4828 }
4829 }
4830#else
4831 uintptr_t const uTRBase = X86DESC_BASE(pDesc);
4832#endif
4833 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_TR_BASE, uTRBase);
4834 AssertRCReturn(rc, rc);
4835
4836 /*
4837 * Host FS base and GS base.
4838 */
4839#if HC_ARCH_BITS == 64
4840 uint64_t const u64FSBase = ASMRdMsr(MSR_K8_FS_BASE);
4841 uint64_t const u64GSBase = ASMRdMsr(MSR_K8_GS_BASE);
4842 rc = VMXWriteVmcs64(VMX_VMCS_HOST_FS_BASE, u64FSBase);
4843 rc |= VMXWriteVmcs64(VMX_VMCS_HOST_GS_BASE, u64GSBase);
4844 AssertRCReturn(rc, rc);
4845
4846 /* Store the base if we have to restore FS or GS manually as we need to restore the base as well. */
4847 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_FS)
4848 pVCpu->hm.s.vmx.RestoreHost.uHostFSBase = u64FSBase;
4849 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_GS)
4850 pVCpu->hm.s.vmx.RestoreHost.uHostGSBase = u64GSBase;
4851#endif
4852 return VINF_SUCCESS;
4853}
4854
4855
4856/**
4857 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4858 * host-state area of the VMCS.
4859 *
4860 * These MSRs will be automatically restored on the host after every successful
4861 * VM-exit.
4862 *
4863 * @returns VBox status code.
4864 * @param pVCpu The cross context virtual CPU structure.
4865 *
4866 * @remarks No-long-jump zone!!!
4867 */
4868static int hmR0VmxExportHostMsrs(PVMCPU pVCpu)
4869{
4870 AssertPtr(pVCpu);
4871
4872 /*
4873 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4874 * rather than swapping them on every VM-entry.
4875 */
4876 hmR0VmxLazySaveHostMsrs(pVCpu);
4877
4878 /*
4879 * Host Sysenter MSRs.
4880 */
4881 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS));
4882#if HC_ARCH_BITS == 32
4883 rc |= VMXWriteVmcs32(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr_Low(MSR_IA32_SYSENTER_ESP));
4884 rc |= VMXWriteVmcs32(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr_Low(MSR_IA32_SYSENTER_EIP));
4885#else
4886 rc |= VMXWriteVmcs64(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP));
4887 rc |= VMXWriteVmcs64(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP));
4888#endif
4889 AssertRCReturn(rc, rc);
4890
4891 /*
4892 * Host EFER MSR.
4893 *
4894 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4895 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4896 */
4897 PVM pVM = pVCpu->CTX_SUFF(pVM);
4898 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
4899 {
4900 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, pVM->hm.s.vmx.u64HostMsrEfer);
4901 AssertRCReturn(rc, rc);
4902 }
4903
4904 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4905 * hmR0VmxExportGuestEntryExitCtls(). */
4906
4907 return VINF_SUCCESS;
4908}
4909
4910
4911/**
4912 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4913 *
4914 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4915 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4916 *
4917 * @returns true if we need to load guest EFER, false otherwise.
4918 * @param pVCpu The cross context virtual CPU structure.
4919 *
4920 * @remarks Requires EFER, CR4.
4921 * @remarks No-long-jump zone!!!
4922 */
4923static bool hmR0VmxShouldSwapEferMsr(PCVMCPU pVCpu)
4924{
4925#ifdef HMVMX_ALWAYS_SWAP_EFER
4926 RT_NOREF(pVCpu);
4927 return true;
4928#else
4929 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4930#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
4931 /* For 32-bit hosts running 64-bit guests, we always swap EFER MSR in the world-switcher. Nothing to do here. */
4932 if (CPUMIsGuestInLongModeEx(pCtx))
4933 return false;
4934#endif
4935
4936 PVM pVM = pVCpu->CTX_SUFF(pVM);
4937 uint64_t const u64HostEfer = pVM->hm.s.vmx.u64HostMsrEfer;
4938 uint64_t const u64GuestEfer = pCtx->msrEFER;
4939
4940 /*
4941 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4942 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4943 */
4944 if ( CPUMIsGuestInLongModeEx(pCtx)
4945 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4946 return true;
4947
4948 /*
4949 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4950 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4951 *
4952 * See Intel spec. 4.5 "IA-32e Paging".
4953 * See Intel spec. 4.1.1 "Three Paging Modes".
4954 *
4955 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4956 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4957 */
4958 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4959 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4960 if ( (pCtx->cr4 & X86_CR4_PAE)
4961 && (pCtx->cr0 & X86_CR0_PG)
4962 && (u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4963 {
4964 /* Assert that host is NX capable. */
4965 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4966 return true;
4967 }
4968
4969 return false;
4970#endif
4971}
4972
4973/**
4974 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
4975 * VMCS.
4976 *
4977 * This is typically required when the guest changes paging mode.
4978 *
4979 * @returns VBox status code.
4980 * @param pVCpu The cross context virtual CPU structure.
4981 * @param pVmxTransient The VMX-transient structure.
4982 *
4983 * @remarks Requires EFER.
4984 * @remarks No-long-jump zone!!!
4985 */
4986static int hmR0VmxExportGuestEntryExitCtls(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
4987{
4988 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
4989 {
4990 PVM pVM = pVCpu->CTX_SUFF(pVM);
4991 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4992
4993 /*
4994 * VM-entry controls.
4995 */
4996 {
4997 uint32_t fVal = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4998 uint32_t const fZap = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4999
5000 /*
5001 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
5002 * The first VT-x capable CPUs only supported the 1-setting of this bit.
5003 *
5004 * For nested-guests, this is a mandatory VM-entry control. It's also
5005 * required because we do not want to leak host bits to the nested-guest.
5006 */
5007 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
5008
5009 /*
5010 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
5011 *
5012 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
5013 * required to get the nested-guest working with hardware-assisted VMX execution.
5014 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a guest hypervisor
5015 * can skip intercepting changes to the EFER MSR. This is why it it needs to be done
5016 * here rather than while merging the guest VMCS controls.
5017 */
5018 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
5019 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
5020 else
5021 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
5022
5023 /*
5024 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
5025 *
5026 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
5027 * regardless of whether the nested-guest VMCS specifies it because we are free to
5028 * load whatever MSRs we require and we do not need to modify the guest visible copy
5029 * of the VM-entry MSR load area.
5030 */
5031 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
5032 && hmR0VmxShouldSwapEferMsr(pVCpu))
5033 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
5034 else
5035 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
5036
5037 /*
5038 * The following should -not- be set (since we're not in SMM mode):
5039 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
5040 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
5041 */
5042
5043 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
5044 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
5045
5046 if ((fVal & fZap) == fVal)
5047 { /* likely */ }
5048 else
5049 {
5050 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
5051 pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0, fVal, fZap));
5052 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
5053 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5054 }
5055
5056 /* Commit it to the VMCS. */
5057 if (pVmcsInfo->u32EntryCtls != fVal)
5058 {
5059 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
5060 AssertRCReturn(rc, rc);
5061 pVmcsInfo->u32EntryCtls = fVal;
5062 }
5063 }
5064
5065 /*
5066 * VM-exit controls.
5067 */
5068 {
5069 uint32_t fVal = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
5070 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
5071
5072 /*
5073 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
5074 * supported the 1-setting of this bit.
5075 *
5076 * For nested-guests, we set the "save debug controls" as the converse
5077 * "load debug controls" is mandatory for nested-guests anyway.
5078 */
5079 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
5080
5081 /*
5082 * Set the host long mode active (EFER.LMA) bit (which Intel calls
5083 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
5084 * host EFER.LMA and EFER.LME bit to this value. See assertion in
5085 * hmR0VmxExportHostMsrs().
5086 *
5087 * For nested-guests, we always set this bit as we do not support 32-bit
5088 * hosts.
5089 */
5090#if HC_ARCH_BITS == 64
5091 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
5092#else
5093 Assert(!pVmxTransient->fIsNestedGuest);
5094 Assert( pVmcsInfo->pfnStartVM == VMXR0SwitcherStartVM64
5095 || pVmcsInfo->pfnStartVM == VMXR0StartVM32);
5096 /* Set the host address-space size based on the switcher, not guest state. See @bugref{8432}. */
5097 if (pVmcsInfo->pfnStartVM == VMXR0SwitcherStartVM64)
5098 {
5099 /* The switcher returns to long mode, the EFER MSR is managed by the switcher. */
5100 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
5101 }
5102 else
5103 Assert(!(fVal & VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE));
5104#endif
5105
5106 /*
5107 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
5108 *
5109 * For nested-guests, we should use the "save IA32_EFER" control if we also
5110 * used the "load IA32_EFER" control while exporting VM-entry controls.
5111 */
5112 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
5113 && hmR0VmxShouldSwapEferMsr(pVCpu))
5114 {
5115 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
5116 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
5117 }
5118
5119 /*
5120 * Enable saving of the VMX-preemption timer value on VM-exit.
5121 * For nested-guests, currently not exposed/used.
5122 */
5123 if ( pVM->hm.s.vmx.fUsePreemptTimer
5124 && (pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER))
5125 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
5126
5127 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
5128 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
5129
5130 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
5131 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
5132 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
5133
5134 if ((fVal & fZap) == fVal)
5135 { /* likely */ }
5136 else
5137 {
5138 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
5139 pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0, fVal, fZap));
5140 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
5141 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5142 }
5143
5144 /* Commit it to the VMCS. */
5145 if (pVmcsInfo->u32ExitCtls != fVal)
5146 {
5147 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
5148 AssertRCReturn(rc, rc);
5149 pVmcsInfo->u32ExitCtls = fVal;
5150 }
5151 }
5152
5153 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
5154 }
5155 return VINF_SUCCESS;
5156}
5157
5158
5159/**
5160 * Sets the TPR threshold in the VMCS.
5161 *
5162 * @returns VBox status code.
5163 * @param pVCpu The cross context virtual CPU structure.
5164 * @param pVmcsInfo The VMCS info. object.
5165 * @param u32TprThreshold The TPR threshold (task-priority class only).
5166 */
5167DECLINLINE(int) hmR0VmxApicSetTprThreshold(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
5168{
5169 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
5170 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
5171 RT_NOREF2(pVCpu, pVmcsInfo);
5172 return VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
5173}
5174
5175
5176/**
5177 * Exports the guest APIC TPR state into the VMCS.
5178 *
5179 * @returns VBox status code.
5180 * @param pVCpu The cross context virtual CPU structure.
5181 * @param pVmxTransient The VMX-transient structure.
5182 *
5183 * @remarks No-long-jump zone!!!
5184 */
5185static int hmR0VmxExportGuestApicTpr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5186{
5187 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
5188 {
5189 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
5190
5191 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5192 if (!pVmxTransient->fIsNestedGuest)
5193 {
5194 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
5195 && APICIsEnabled(pVCpu))
5196 {
5197 /*
5198 * Setup TPR shadowing.
5199 */
5200 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
5201 {
5202 bool fPendingIntr = false;
5203 uint8_t u8Tpr = 0;
5204 uint8_t u8PendingIntr = 0;
5205 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
5206 AssertRCReturn(rc, rc);
5207
5208 /*
5209 * If there are interrupts pending but masked by the TPR, instruct VT-x to
5210 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
5211 * priority of the pending interrupt so we can deliver the interrupt. If there
5212 * are no interrupts pending, set threshold to 0 to not cause any
5213 * TPR-below-threshold VM-exits.
5214 */
5215 uint32_t u32TprThreshold = 0;
5216 if (fPendingIntr)
5217 {
5218 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
5219 (which is the Task-Priority Class). */
5220 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
5221 const uint8_t u8TprPriority = u8Tpr >> 4;
5222 if (u8PendingPriority <= u8TprPriority)
5223 u32TprThreshold = u8PendingPriority;
5224 }
5225
5226 rc = hmR0VmxApicSetTprThreshold(pVCpu, pVmcsInfo, u32TprThreshold);
5227 AssertRCReturn(rc, rc);
5228 }
5229 }
5230 }
5231 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
5232 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
5233 }
5234 return VINF_SUCCESS;
5235}
5236
5237
5238/**
5239 * Gets the guest interruptibility-state.
5240 *
5241 * @returns Guest's interruptibility-state.
5242 * @param pVCpu The cross context virtual CPU structure.
5243 * @param pVmxTransient The VMX-transient structure.
5244 *
5245 * @remarks No-long-jump zone!!!
5246 */
5247static uint32_t hmR0VmxGetGuestIntrState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5248{
5249 /*
5250 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
5251 */
5252 uint32_t fIntrState = 0;
5253 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5254 {
5255 /* If inhibition is active, RIP and RFLAGS should've been updated
5256 (i.e. read previously from the VMCS or from ring-3). */
5257 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5258#ifdef VBOX_STRICT
5259 uint64_t const fExtrn = ASMAtomicUoReadU64(&pCtx->fExtrn);
5260 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
5261 AssertMsg(!(fExtrn & (CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS)), ("%#x\n", fExtrn));
5262#endif
5263 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
5264 {
5265 if (pCtx->eflags.Bits.u1IF)
5266 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
5267 else
5268 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
5269 }
5270 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5271 {
5272 /*
5273 * We can clear the inhibit force flag as even if we go back to the recompiler
5274 * without executing guest code in VT-x, the flag's condition to be cleared is
5275 * met and thus the cleared state is correct.
5276 */
5277 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
5278 }
5279 }
5280
5281 /*
5282 * NMIs to the guest are blocked after an NMI is injected until the guest executes an IRET. We only
5283 * bother with virtual-NMI blocking when we have support for virtual NMIs in the CPU, otherwise
5284 * setting this would block host-NMIs and IRET will not clear the blocking.
5285 *
5286 * We always set NMI-exiting so when the host receives an NMI we get a VM-exit.
5287 *
5288 * See Intel spec. 26.6.1 "Interruptibility state". See @bugref{7445}.
5289 */
5290 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5291 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
5292 && CPUMIsGuestNmiBlocking(pVCpu))
5293 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
5294
5295 return fIntrState;
5296}
5297
5298
5299/**
5300 * Exports the exception intercepts required for guest execution in the VMCS.
5301 *
5302 * @returns VBox status code.
5303 * @param pVCpu The cross context virtual CPU structure.
5304 * @param pVmxTransient The VMX-transient structure.
5305 *
5306 * @remarks No-long-jump zone!!!
5307 */
5308static int hmR0VmxExportGuestXcptIntercepts(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5309{
5310 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
5311 {
5312 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
5313 if ( !pVmxTransient->fIsNestedGuest
5314 && pVCpu->hm.s.fGIMTrapXcptUD)
5315 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
5316 else
5317 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
5318
5319 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
5320 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
5321 }
5322 return VINF_SUCCESS;
5323}
5324
5325
5326/**
5327 * Exports the guest's RIP into the guest-state area in the VMCS.
5328 *
5329 * @returns VBox status code.
5330 * @param pVCpu The cross context virtual CPU structure.
5331 *
5332 * @remarks No-long-jump zone!!!
5333 */
5334static int hmR0VmxExportGuestRip(PVMCPU pVCpu)
5335{
5336 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
5337 {
5338 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
5339
5340 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
5341 AssertRCReturn(rc, rc);
5342
5343 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
5344 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
5345 }
5346 return VINF_SUCCESS;
5347}
5348
5349
5350/**
5351 * Exports the guest's RSP into the guest-state area in the VMCS.
5352 *
5353 * @returns VBox status code.
5354 * @param pVCpu The cross context virtual CPU structure.
5355 *
5356 * @remarks No-long-jump zone!!!
5357 */
5358static int hmR0VmxExportGuestRsp(PVMCPU pVCpu)
5359{
5360 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
5361 {
5362 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
5363
5364 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
5365 AssertRCReturn(rc, rc);
5366
5367 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
5368 }
5369 return VINF_SUCCESS;
5370}
5371
5372
5373/**
5374 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
5375 *
5376 * @returns VBox status code.
5377 * @param pVCpu The cross context virtual CPU structure.
5378 * @param pVmxTransient The VMX-transient structure.
5379 *
5380 * @remarks No-long-jump zone!!!
5381 */
5382static int hmR0VmxExportGuestRflags(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5383{
5384 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
5385 {
5386 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5387
5388 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
5389 Let us assert it as such and use 32-bit VMWRITE. */
5390 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
5391 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
5392 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
5393 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
5394
5395 /*
5396 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
5397 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
5398 * can run the real-mode guest code under Virtual 8086 mode.
5399 */
5400 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5401 if (pVmcsInfo->RealMode.fRealOnV86Active)
5402 {
5403 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
5404 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
5405 Assert(!pVmxTransient->fIsNestedGuest);
5406 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
5407 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
5408 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
5409 }
5410
5411 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
5412 AssertRCReturn(rc, rc);
5413
5414 /*
5415 * Setup pending debug exceptions if the guest is single-stepping using EFLAGS.TF.
5416 *
5417 * We must avoid setting any automatic debug exceptions delivery when single-stepping
5418 * through the hypervisor debugger using EFLAGS.TF.
5419 */
5420 if ( !pVmxTransient->fIsNestedGuest
5421 && !pVCpu->hm.s.fSingleInstruction
5422 && fEFlags.Bits.u1TF)
5423 {
5424 /** @todo r=ramshankar: Warning!! We ASSUME EFLAGS.TF will not cleared on
5425 * premature trips to ring-3 esp since IEM does not yet handle it. */
5426 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BS);
5427 AssertRCReturn(rc, rc);
5428 }
5429 /** @todo NSTVMX: Handling copying of VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS from
5430 * nested-guest VMCS. */
5431
5432 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5433 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5434 }
5435 return VINF_SUCCESS;
5436}
5437
5438
5439#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5440/**
5441 * Copies the nested-guest VMCS to the shadow VMCS.
5442 *
5443 * @returns VBox status code.
5444 * @param pVCpu The cross context virtual CPU structure.
5445 * @param pVmcsInfo The VMCS info. object.
5446 *
5447 * @remarks No-long-jump zone!!!
5448 */
5449static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5450{
5451 PVM pVM = pVCpu->CTX_SUFF(pVM);
5452 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5453
5454 /*
5455 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5456 * current VMCS, as we may try saving guest lazy MSRs.
5457 *
5458 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5459 * calling the import VMCS code which is currently performing the guest MSR reads
5460 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5461 * and the rest of the VMX leave session machinery.
5462 */
5463 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5464
5465 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5466 if (RT_SUCCESS(rc))
5467 {
5468 /*
5469 * Copy all guest read/write VMCS fields.
5470 *
5471 * We don't check for VMWRITE failures here for performance reasons and
5472 * because they are not expected to fail, barring irrecoverable conditions
5473 * like hardware errors.
5474 */
5475 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5476 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5477 {
5478 uint64_t u64Val;
5479 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5480 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5481 VMXWriteVmcs64(uVmcsField, u64Val);
5482 }
5483
5484 /*
5485 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5486 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5487 */
5488 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
5489 {
5490 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
5491 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5492 {
5493 uint64_t u64Val;
5494 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsRoFields[i];
5495 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5496 VMXWriteVmcs64(uVmcsField, u64Val);
5497 }
5498 }
5499
5500 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5501 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5502 }
5503
5504 ASMSetFlags(fEFlags);
5505 return rc;
5506}
5507
5508
5509/**
5510 * Copies the shadow VMCS to the nested-guest VMCS.
5511 *
5512 * @returns VBox status code.
5513 * @param pVCpu The cross context virtual CPU structure.
5514 * @param pVmcsInfo The VMCS info. object.
5515 *
5516 * @remarks Called with interrupts disabled.
5517 */
5518static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5519{
5520 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5521 PVM pVM = pVCpu->CTX_SUFF(pVM);
5522 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5523
5524 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5525 if (RT_SUCCESS(rc))
5526 {
5527 /*
5528 * Copy guest read/write fields from the shadow VMCS.
5529 * Guest read-only fields cannot be modified, so no need to copy them.
5530 *
5531 * We don't check for VMREAD failures here for performance reasons and
5532 * because they are not expected to fail, barring irrecoverable conditions
5533 * like hardware errors.
5534 */
5535 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5536 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5537 {
5538 uint64_t u64Val;
5539 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5540 VMXReadVmcs64(uVmcsField, &u64Val);
5541 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5542 }
5543
5544 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5545 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5546 }
5547 return rc;
5548}
5549
5550
5551/**
5552 * Enables VMCS shadowing for the given VMCS info. object.
5553 *
5554 * @param pVCpu The cross context virtual CPU structure.
5555 * @param pVmcsInfo The VMCS info. object.
5556 *
5557 * @remarks No-long-jump zone!!!
5558 */
5559static void hmR0VmxEnableVmcsShadowing(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5560{
5561 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
5562
5563 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5564 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5565 {
5566 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5567 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5568 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2);
5569 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs);
5570 AssertRC(rc);
5571
5572 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5573 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5574 Log4Func(("Enabled\n"));
5575 }
5576}
5577
5578
5579/**
5580 * Disables VMCS shadowing for the given VMCS info. object.
5581 *
5582 * @param pVCpu The cross context virtual CPU structure.
5583 * @param pVmcsInfo The VMCS info. object.
5584 *
5585 * @remarks No-long-jump zone!!!
5586 */
5587static void hmR0VmxDisableVmcsShadowing(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5588{
5589 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
5590
5591 /*
5592 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5593 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5594 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5595 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5596 *
5597 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5598 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5599 */
5600 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5601 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5602 {
5603 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5604 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2);
5605 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
5606 AssertRC(rc);
5607
5608 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5609 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5610 Log4Func(("Disabled\n"));
5611 }
5612}
5613#endif
5614
5615
5616/**
5617 * Exports the guest hardware-virtualization state.
5618 *
5619 * @returns VBox status code.
5620 * @param pVCpu The cross context virtual CPU structure.
5621 * @param pVmxTransient The VMX-transient structure.
5622 *
5623 * @remarks No-long-jump zone!!!
5624 */
5625static int hmR0VmxExportGuestHwvirtState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5626{
5627 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5628 {
5629#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5630 /*
5631 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5632 * VMCS shadowing.
5633 */
5634 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
5635 {
5636 /*
5637 * If the guest hypervisor has loaded a current VMCS and is in VMX root mode,
5638 * copy the guest hypervisor's current VMCS into the shadow VMCS and enable
5639 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5640 *
5641 * We check for VMX root mode here in case the guest executes VMXOFF without
5642 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5643 * not clear the current VMCS pointer.
5644 */
5645 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5646 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5647 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5648 && CPUMIsGuestVmxCurrentVmcsValid(pVCpu, &pVCpu->cpum.GstCtx))
5649 {
5650 /* Paranoia. */
5651 Assert(!pVmxTransient->fIsNestedGuest);
5652
5653 /*
5654 * For performance reasons, also check if the guest hypervisor's current VMCS
5655 * was newly loaded or modified before copying it to the shadow VMCS.
5656 */
5657 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5658 {
5659 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5660 AssertRCReturn(rc, rc);
5661 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5662 }
5663 hmR0VmxEnableVmcsShadowing(pVCpu, pVmcsInfo);
5664 }
5665 else
5666 hmR0VmxDisableVmcsShadowing(pVCpu, pVmcsInfo);
5667 }
5668#else
5669 NOREF(pVmxTransient);
5670#endif
5671 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5672 }
5673 return VINF_SUCCESS;
5674}
5675
5676
5677/**
5678 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5679 *
5680 * The guest FPU state is always pre-loaded hence we don't need to bother about
5681 * sharing FPU related CR0 bits between the guest and host.
5682 *
5683 * @returns VBox status code.
5684 * @param pVCpu The cross context virtual CPU structure.
5685 * @param pVmxTransient The VMX-transient structure.
5686 *
5687 * @remarks No-long-jump zone!!!
5688 */
5689static int hmR0VmxExportGuestCR0(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5690{
5691 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5692 {
5693 PVM pVM = pVCpu->CTX_SUFF(pVM);
5694 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5695
5696 /*
5697 * Figure out fixed CR0 bits in VMX operation.
5698 */
5699 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
5700 uint64_t fSetCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5701 uint64_t const fZapCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5702 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5703 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5704 else
5705 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5706
5707 if (!pVmxTransient->fIsNestedGuest)
5708 {
5709 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5710 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5711 uint64_t const u64ShadowCr0 = u64GuestCr0;
5712 Assert(!RT_HI_U32(u64GuestCr0));
5713
5714 /*
5715 * Setup VT-x's view of the guest CR0.
5716 */
5717 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5718 if (pVM->hm.s.fNestedPaging)
5719 {
5720 if (CPUMIsGuestPagingEnabled(pVCpu))
5721 {
5722 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5723 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5724 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5725 }
5726 else
5727 {
5728 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5729 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5730 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5731 }
5732
5733 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5734 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5735 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5736 }
5737 else
5738 {
5739 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5740 u64GuestCr0 |= X86_CR0_WP;
5741 }
5742
5743 /*
5744 * Guest FPU bits.
5745 *
5746 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5747 * using CR0.TS.
5748 *
5749 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5750 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5751 */
5752 u64GuestCr0 |= X86_CR0_NE;
5753
5754 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5755 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5756
5757 /*
5758 * Update exception intercepts.
5759 */
5760 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5761 if (pVmcsInfo->RealMode.fRealOnV86Active)
5762 {
5763 Assert(PDMVmmDevHeapIsEnabled(pVM));
5764 Assert(pVM->hm.s.vmx.pRealModeTSS);
5765 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5766 }
5767 else
5768 {
5769 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5770 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5771 if (fInterceptMF)
5772 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5773 }
5774
5775 /* Additional intercepts for debugging, define these yourself explicitly. */
5776#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5777 uXcptBitmap |= 0
5778 | RT_BIT(X86_XCPT_BP)
5779 | RT_BIT(X86_XCPT_DE)
5780 | RT_BIT(X86_XCPT_NM)
5781 | RT_BIT(X86_XCPT_TS)
5782 | RT_BIT(X86_XCPT_UD)
5783 | RT_BIT(X86_XCPT_NP)
5784 | RT_BIT(X86_XCPT_SS)
5785 | RT_BIT(X86_XCPT_GP)
5786 | RT_BIT(X86_XCPT_PF)
5787 | RT_BIT(X86_XCPT_MF)
5788 ;
5789#elif defined(HMVMX_ALWAYS_TRAP_PF)
5790 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5791#endif
5792 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5793 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5794 Assert(pVM->hm.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5795
5796 /* Apply the hardware specified fixed CR0 bits and enable caching. */
5797 u64GuestCr0 |= fSetCr0;
5798 u64GuestCr0 &= fZapCr0;
5799 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5800
5801 /* Commit the CR0 and related fields to the guest VMCS. */
5802 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_CR0, u64GuestCr0); /** @todo Fix to 64-bit when we drop 32-bit. */
5803 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0);
5804 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5805 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5806 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5807 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5808 AssertRCReturn(rc, rc);
5809
5810 /* Update our caches. */
5811 pVmcsInfo->u32ProcCtls = uProcCtls;
5812 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5813
5814 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5815 }
5816 else
5817 {
5818 /*
5819 * With nested-guests, we may have extended the guest/host mask here since we
5820 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5821 * (to read from the nested-guest CR0 read-shadow) than the guest hypervisor
5822 * originally supplied. We must copy those bits from the nested-guest CR0 into
5823 * the nested-guest CR0 read-shadow.
5824 */
5825 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5826 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5827 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(pVCpu, &pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5828 Assert(!RT_HI_U32(u64GuestCr0));
5829 Assert(u64GuestCr0 & X86_CR0_NE);
5830
5831 /*
5832 * Apply the hardware specified fixed CR0 bits and enable caching.
5833 * Note! We could be altering our VMX emulation's fixed bits. We thus
5834 * need to re-apply them while importing CR0.
5835 */
5836 u64GuestCr0 |= fSetCr0;
5837 u64GuestCr0 &= fZapCr0;
5838 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5839
5840 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5841 /** @todo NSTVMX: Fix to 64-bit when we drop 32-bit. */
5842 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_CR0, u64GuestCr0);
5843 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0);
5844 AssertRCReturn(rc, rc);
5845
5846 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5847 }
5848
5849 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5850 }
5851
5852 return VINF_SUCCESS;
5853}
5854
5855
5856/**
5857 * Exports the guest control registers (CR3, CR4) into the guest-state area
5858 * in the VMCS.
5859 *
5860 * @returns VBox strict status code.
5861 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5862 * without unrestricted guest access and the VMMDev is not presently
5863 * mapped (e.g. EFI32).
5864 *
5865 * @param pVCpu The cross context virtual CPU structure.
5866 * @param pVmxTransient The VMX-transient structure.
5867 *
5868 * @remarks No-long-jump zone!!!
5869 */
5870static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5871{
5872 int rc = VINF_SUCCESS;
5873 PVM pVM = pVCpu->CTX_SUFF(pVM);
5874
5875 /*
5876 * Guest CR2.
5877 * It's always loaded in the assembler code. Nothing to do here.
5878 */
5879
5880 /*
5881 * Guest CR3.
5882 */
5883 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5884 {
5885 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5886
5887 RTGCPHYS GCPhysGuestCr3 = NIL_RTGCPHYS;
5888 if (pVM->hm.s.fNestedPaging)
5889 {
5890 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5891 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5892
5893 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5894 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5895 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5896 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5897
5898 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5899 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5900 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5901
5902 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5903 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5904 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5905 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5906 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5907 || (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5908 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5909
5910 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5911 AssertRCReturn(rc, rc);
5912
5913 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5914 if ( pVM->hm.s.vmx.fUnrestrictedGuest
5915 || CPUMIsGuestPagingEnabledEx(pCtx))
5916 {
5917 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5918 if (CPUMIsGuestInPAEModeEx(pCtx))
5919 {
5920 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5921 AssertRCReturn(rc, rc);
5922 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u);
5923 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u);
5924 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u);
5925 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u);
5926 AssertRCReturn(rc, rc);
5927 }
5928
5929 /*
5930 * The guest's view of its CR3 is unblemished with nested paging when the
5931 * guest is using paging or we have unrestricted guest execution to handle
5932 * the guest when it's not using paging.
5933 */
5934 GCPhysGuestCr3 = pCtx->cr3;
5935 }
5936 else
5937 {
5938 /*
5939 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5940 * thinks it accesses physical memory directly, we use our identity-mapped
5941 * page table to map guest-linear to guest-physical addresses. EPT takes care
5942 * of translating it to host-physical addresses.
5943 */
5944 RTGCPHYS GCPhys;
5945 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5946
5947 /* We obtain it here every time as the guest could have relocated this PCI region. */
5948 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5949 if (RT_SUCCESS(rc))
5950 { /* likely */ }
5951 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5952 {
5953 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5954 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5955 }
5956 else
5957 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5958
5959 GCPhysGuestCr3 = GCPhys;
5960 }
5961
5962 Log4Func(("u32GuestCr3=%#RGp (GstN)\n", GCPhysGuestCr3));
5963 rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_CR3, GCPhysGuestCr3);
5964 AssertRCReturn(rc, rc);
5965 }
5966 else
5967 {
5968 /* Non-nested paging case, just use the hypervisor's CR3. */
5969 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5970
5971 Log4Func(("u32GuestCr3=%#RHv (HstN)\n", HCPhysGuestCr3));
5972 rc = VMXWriteVmcsHstN(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5973 AssertRCReturn(rc, rc);
5974 }
5975
5976 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5977 }
5978
5979 /*
5980 * Guest CR4.
5981 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
5982 */
5983 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
5984 {
5985 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5986 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5987
5988 /*
5989 * Figure out fixed CR4 bits in VMX operation.
5990 */
5991 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
5992 uint64_t const fSetCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5993 uint64_t const fZapCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5994
5995 /*
5996 * With nested-guests, we may have extended the guest/host mask here (since we
5997 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
5998 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
5999 * the guest hypervisor originally supplied. Thus, we should, in essence, copy
6000 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
6001 */
6002 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
6003 uint64_t u64GuestCr4 = pCtx->cr4;
6004 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
6005 ? pCtx->cr4
6006 : CPUMGetGuestVmxMaskedCr4(pVCpu, pCtx, pVmcsInfo->u64Cr4Mask);
6007 Assert(!RT_HI_U32(u64GuestCr4));
6008
6009 /*
6010 * Setup VT-x's view of the guest CR4.
6011 *
6012 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
6013 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
6014 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
6015 *
6016 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
6017 */
6018 if (pVmcsInfo->RealMode.fRealOnV86Active)
6019 {
6020 Assert(pVM->hm.s.vmx.pRealModeTSS);
6021 Assert(PDMVmmDevHeapIsEnabled(pVM));
6022 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
6023 }
6024
6025 if (pVM->hm.s.fNestedPaging)
6026 {
6027 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
6028 && !pVM->hm.s.vmx.fUnrestrictedGuest)
6029 {
6030 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
6031 u64GuestCr4 |= X86_CR4_PSE;
6032 /* Our identity mapping is a 32-bit page directory. */
6033 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
6034 }
6035 /* else use guest CR4.*/
6036 }
6037 else
6038 {
6039 Assert(!pVmxTransient->fIsNestedGuest);
6040
6041 /*
6042 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
6043 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
6044 */
6045 switch (pVCpu->hm.s.enmShadowMode)
6046 {
6047 case PGMMODE_REAL: /* Real-mode. */
6048 case PGMMODE_PROTECTED: /* Protected mode without paging. */
6049 case PGMMODE_32_BIT: /* 32-bit paging. */
6050 {
6051 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
6052 break;
6053 }
6054
6055 case PGMMODE_PAE: /* PAE paging. */
6056 case PGMMODE_PAE_NX: /* PAE paging with NX. */
6057 {
6058 u64GuestCr4 |= X86_CR4_PAE;
6059 break;
6060 }
6061
6062 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
6063 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
6064#ifdef VBOX_ENABLE_64_BITS_GUESTS
6065 break;
6066#endif
6067 default:
6068 AssertFailed();
6069 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
6070 }
6071 }
6072
6073 /*
6074 * Apply the hardware specified fixed CR4 bits (mainly CR4.VMXE).
6075 * Note! For nested-guests, we could be altering our VMX emulation's
6076 * fixed bits. We thus need to re-apply them while importing CR4.
6077 */
6078 u64GuestCr4 |= fSetCr4;
6079 u64GuestCr4 &= fZapCr4;
6080
6081 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
6082 /** @todo Fix to 64-bit when we drop 32-bit. */
6083 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_CR4, u64GuestCr4);
6084 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4);
6085 AssertRCReturn(rc, rc);
6086
6087 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
6088 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
6089
6090 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
6091
6092 Log4Func(("cr4=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
6093 }
6094 return rc;
6095}
6096
6097
6098/**
6099 * Exports the guest debug registers into the guest-state area in the VMCS.
6100 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
6101 *
6102 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
6103 *
6104 * @returns VBox status code.
6105 * @param pVCpu The cross context virtual CPU structure.
6106 * @param pVmxTransient The VMX-transient structure.
6107 *
6108 * @remarks No-long-jump zone!!!
6109 */
6110static int hmR0VmxExportSharedDebugState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6111{
6112 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
6113
6114 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
6115 * stepping. */
6116 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6117 if (pVmxTransient->fIsNestedGuest)
6118 {
6119 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
6120 AssertRCReturn(rc, rc);
6121 return VINF_SUCCESS;
6122 }
6123
6124#ifdef VBOX_STRICT
6125 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
6126 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
6127 {
6128 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
6129 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
6130 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
6131 }
6132#endif
6133
6134 bool fSteppingDB = false;
6135 bool fInterceptMovDRx = false;
6136 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
6137 if (pVCpu->hm.s.fSingleInstruction)
6138 {
6139 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
6140 PVM pVM = pVCpu->CTX_SUFF(pVM);
6141 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
6142 {
6143 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
6144 Assert(fSteppingDB == false);
6145 }
6146 else
6147 {
6148 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
6149 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
6150 pVCpu->hm.s.fClearTrapFlag = true;
6151 fSteppingDB = true;
6152 }
6153 }
6154
6155 uint32_t u32GuestDr7;
6156 if ( fSteppingDB
6157 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
6158 {
6159 /*
6160 * Use the combined guest and host DRx values found in the hypervisor register set
6161 * because the hypervisor debugger has breakpoints active or someone is single stepping
6162 * on the host side without a monitor trap flag.
6163 *
6164 * Note! DBGF expects a clean DR6 state before executing guest code.
6165 */
6166#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
6167 if ( CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
6168 && !CPUMIsHyperDebugStateActivePending(pVCpu))
6169 {
6170 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
6171 Assert(CPUMIsHyperDebugStateActivePending(pVCpu));
6172 Assert(!CPUMIsGuestDebugStateActivePending(pVCpu));
6173 }
6174 else
6175#endif
6176 if (!CPUMIsHyperDebugStateActive(pVCpu))
6177 {
6178 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
6179 Assert(CPUMIsHyperDebugStateActive(pVCpu));
6180 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
6181 }
6182
6183 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
6184 u32GuestDr7 = (uint32_t)CPUMGetHyperDR7(pVCpu);
6185 pVCpu->hm.s.fUsingHyperDR7 = true;
6186 fInterceptMovDRx = true;
6187 }
6188 else
6189 {
6190 /*
6191 * If the guest has enabled debug registers, we need to load them prior to
6192 * executing guest code so they'll trigger at the right time.
6193 */
6194 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
6195 {
6196#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
6197 if ( CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
6198 && !CPUMIsGuestDebugStateActivePending(pVCpu))
6199 {
6200 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6201 Assert(CPUMIsGuestDebugStateActivePending(pVCpu));
6202 Assert(!CPUMIsHyperDebugStateActivePending(pVCpu));
6203 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
6204 }
6205 else
6206#endif
6207 if (!CPUMIsGuestDebugStateActive(pVCpu))
6208 {
6209 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6210 Assert(CPUMIsGuestDebugStateActive(pVCpu));
6211 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
6212 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
6213 }
6214 Assert(!fInterceptMovDRx);
6215 }
6216 /*
6217 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
6218 * must intercept #DB in order to maintain a correct DR6 guest value, and
6219 * because we need to intercept it to prevent nested #DBs from hanging the
6220 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
6221 */
6222#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
6223 else if ( !CPUMIsGuestDebugStateActivePending(pVCpu)
6224 && !CPUMIsGuestDebugStateActive(pVCpu))
6225#else
6226 else if (!CPUMIsGuestDebugStateActive(pVCpu))
6227#endif
6228 {
6229 fInterceptMovDRx = true;
6230 }
6231
6232 /* Update DR7 with the actual guest value. */
6233 u32GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
6234 pVCpu->hm.s.fUsingHyperDR7 = false;
6235 }
6236
6237 if (fInterceptMovDRx)
6238 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
6239 else
6240 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
6241
6242 /*
6243 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
6244 * monitor-trap flag and update our cache.
6245 */
6246 if (uProcCtls != pVmcsInfo->u32ProcCtls)
6247 {
6248 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
6249 AssertRCReturn(rc2, rc2);
6250 pVmcsInfo->u32ProcCtls = uProcCtls;
6251 }
6252
6253 /*
6254 * Update guest DR7.
6255 */
6256 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_DR7, u32GuestDr7);
6257 AssertRCReturn(rc, rc);
6258
6259 /*
6260 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
6261 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
6262 *
6263 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
6264 */
6265 if (fSteppingDB)
6266 {
6267 Assert(pVCpu->hm.s.fSingleInstruction);
6268 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
6269
6270 uint32_t fIntrState = 0;
6271 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
6272 AssertRCReturn(rc, rc);
6273
6274 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
6275 {
6276 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
6277 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
6278 AssertRCReturn(rc, rc);
6279 }
6280 }
6281
6282 return VINF_SUCCESS;
6283}
6284
6285
6286#ifdef VBOX_STRICT
6287/**
6288 * Strict function to validate segment registers.
6289 *
6290 * @param pVCpu The cross context virtual CPU structure.
6291 * @param pVmcsInfo The VMCS info. object.
6292 *
6293 * @remarks Will import guest CR0 on strict builds during validation of
6294 * segments.
6295 */
6296static void hmR0VmxValidateSegmentRegs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
6297{
6298 /*
6299 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
6300 *
6301 * The reason we check for attribute value 0 in this function and not just the unusable bit is
6302 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
6303 * unusable bit and doesn't change the guest-context value.
6304 */
6305 PVM pVM = pVCpu->CTX_SUFF(pVM);
6306 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6307 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
6308 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
6309 && ( !CPUMIsGuestInRealModeEx(pCtx)
6310 && !CPUMIsGuestInV86ModeEx(pCtx)))
6311 {
6312 /* Protected mode checks */
6313 /* CS */
6314 Assert(pCtx->cs.Attr.n.u1Present);
6315 Assert(!(pCtx->cs.Attr.u & 0xf00));
6316 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
6317 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
6318 || !(pCtx->cs.Attr.n.u1Granularity));
6319 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
6320 || (pCtx->cs.Attr.n.u1Granularity));
6321 /* CS cannot be loaded with NULL in protected mode. */
6322 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
6323 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
6324 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
6325 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
6326 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
6327 else
6328 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
6329 /* SS */
6330 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6331 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
6332 if ( !(pCtx->cr0 & X86_CR0_PE)
6333 || pCtx->cs.Attr.n.u4Type == 3)
6334 {
6335 Assert(!pCtx->ss.Attr.n.u2Dpl);
6336 }
6337 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
6338 {
6339 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6340 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
6341 Assert(pCtx->ss.Attr.n.u1Present);
6342 Assert(!(pCtx->ss.Attr.u & 0xf00));
6343 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
6344 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
6345 || !(pCtx->ss.Attr.n.u1Granularity));
6346 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
6347 || (pCtx->ss.Attr.n.u1Granularity));
6348 }
6349 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
6350 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
6351 {
6352 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6353 Assert(pCtx->ds.Attr.n.u1Present);
6354 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
6355 Assert(!(pCtx->ds.Attr.u & 0xf00));
6356 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
6357 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
6358 || !(pCtx->ds.Attr.n.u1Granularity));
6359 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
6360 || (pCtx->ds.Attr.n.u1Granularity));
6361 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6362 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
6363 }
6364 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
6365 {
6366 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6367 Assert(pCtx->es.Attr.n.u1Present);
6368 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
6369 Assert(!(pCtx->es.Attr.u & 0xf00));
6370 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
6371 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
6372 || !(pCtx->es.Attr.n.u1Granularity));
6373 Assert( !(pCtx->es.u32Limit & 0xfff00000)
6374 || (pCtx->es.Attr.n.u1Granularity));
6375 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6376 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
6377 }
6378 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
6379 {
6380 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6381 Assert(pCtx->fs.Attr.n.u1Present);
6382 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
6383 Assert(!(pCtx->fs.Attr.u & 0xf00));
6384 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
6385 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
6386 || !(pCtx->fs.Attr.n.u1Granularity));
6387 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
6388 || (pCtx->fs.Attr.n.u1Granularity));
6389 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6390 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6391 }
6392 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
6393 {
6394 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6395 Assert(pCtx->gs.Attr.n.u1Present);
6396 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
6397 Assert(!(pCtx->gs.Attr.u & 0xf00));
6398 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
6399 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
6400 || !(pCtx->gs.Attr.n.u1Granularity));
6401 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
6402 || (pCtx->gs.Attr.n.u1Granularity));
6403 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6404 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6405 }
6406 /* 64-bit capable CPUs. */
6407# if HC_ARCH_BITS == 64
6408 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6409 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
6410 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
6411 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
6412# endif
6413 }
6414 else if ( CPUMIsGuestInV86ModeEx(pCtx)
6415 || ( CPUMIsGuestInRealModeEx(pCtx)
6416 && !pVM->hm.s.vmx.fUnrestrictedGuest))
6417 {
6418 /* Real and v86 mode checks. */
6419 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
6420 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
6421 if (pVmcsInfo->RealMode.fRealOnV86Active)
6422 {
6423 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
6424 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
6425 }
6426 else
6427 {
6428 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
6429 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
6430 }
6431
6432 /* CS */
6433 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
6434 Assert(pCtx->cs.u32Limit == 0xffff);
6435 Assert(u32CSAttr == 0xf3);
6436 /* SS */
6437 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
6438 Assert(pCtx->ss.u32Limit == 0xffff);
6439 Assert(u32SSAttr == 0xf3);
6440 /* DS */
6441 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
6442 Assert(pCtx->ds.u32Limit == 0xffff);
6443 Assert(u32DSAttr == 0xf3);
6444 /* ES */
6445 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
6446 Assert(pCtx->es.u32Limit == 0xffff);
6447 Assert(u32ESAttr == 0xf3);
6448 /* FS */
6449 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
6450 Assert(pCtx->fs.u32Limit == 0xffff);
6451 Assert(u32FSAttr == 0xf3);
6452 /* GS */
6453 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
6454 Assert(pCtx->gs.u32Limit == 0xffff);
6455 Assert(u32GSAttr == 0xf3);
6456 /* 64-bit capable CPUs. */
6457# if HC_ARCH_BITS == 64
6458 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6459 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6460 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6461 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6462# endif
6463 }
6464}
6465#endif /* VBOX_STRICT */
6466
6467
6468/**
6469 * Exports a guest segment register into the guest-state area in the VMCS.
6470 *
6471 * @returns VBox status code.
6472 * @param pVCpu The cross context virtual CPU structure.
6473 * @param pVmcsInfo The VMCS info. object.
6474 * @param iSegReg The segment register number (X86_SREG_XXX).
6475 * @param pSelReg Pointer to the segment selector.
6476 *
6477 * @remarks No-long-jump zone!!!
6478 */
6479static int hmR0VmxExportGuestSegReg(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, uint8_t iSegReg, PCCPUMSELREG pSelReg)
6480{
6481 Assert(iSegReg < X86_SREG_COUNT);
6482 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
6483 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
6484 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
6485 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
6486
6487 uint32_t u32Access = pSelReg->Attr.u;
6488 if (pVmcsInfo->RealMode.fRealOnV86Active)
6489 {
6490 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6491 u32Access = 0xf3;
6492 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6493 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6494 RT_NOREF_PV(pVCpu);
6495 }
6496 else
6497 {
6498 /*
6499 * The way to differentiate between whether this is really a null selector or was just
6500 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6501 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6502 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6503 * NULL selectors loaded in protected-mode have their attribute as 0.
6504 */
6505 if (!u32Access)
6506 u32Access = X86DESCATTR_UNUSABLE;
6507 }
6508
6509 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6510 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6511 ("Access bit not set for usable segment. idx=%#x sel=%#x attr %#x\n", idxBase, pSelReg, pSelReg->Attr.u));
6512
6513 /*
6514 * Commit it to the VMCS.
6515 */
6516 int rc = VMXWriteVmcs32(idxSel, pSelReg->Sel);
6517 rc |= VMXWriteVmcs32(idxLimit, pSelReg->u32Limit);
6518 rc |= VMXWriteVmcsGstN(idxBase, pSelReg->u64Base);
6519 rc |= VMXWriteVmcs32(idxAttr, u32Access);
6520 AssertRCReturn(rc, rc);
6521 return rc;
6522}
6523
6524
6525/**
6526 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6527 * area in the VMCS.
6528 *
6529 * @returns VBox status code.
6530 * @param pVCpu The cross context virtual CPU structure.
6531 * @param pVmxTransient The VMX-transient structure.
6532 *
6533 * @remarks Will import guest CR0 on strict builds during validation of
6534 * segments.
6535 * @remarks No-long-jump zone!!!
6536 */
6537static int hmR0VmxExportGuestSegRegsXdtr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6538{
6539 int rc = VERR_INTERNAL_ERROR_5;
6540 PVM pVM = pVCpu->CTX_SUFF(pVM);
6541 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6542 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6543
6544 /*
6545 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6546 */
6547 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6548 {
6549#ifdef VBOX_WITH_REM
6550 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
6551 {
6552 Assert(!pVmxTransient->fIsNestedGuest);
6553 Assert(pVM->hm.s.vmx.pRealModeTSS);
6554 AssertCompile(PGMMODE_REAL < PGMMODE_PROTECTED);
6555 if ( pVmcsInfo->fWasInRealMode
6556 && PGMGetGuestMode(pVCpu) >= PGMMODE_PROTECTED)
6557 {
6558 /*
6559 * Notify the recompiler must flush its code-cache as the guest -may-
6560 * rewrite code it in real-mode (e.g. OpenBSD 4.0).
6561 */
6562 REMFlushTBs(pVM);
6563 Log4Func(("Switch to protected mode detected!\n"));
6564 pVmcsInfo->fWasInRealMode = false;
6565 }
6566 }
6567#endif
6568 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6569 {
6570 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6571 if (pVmcsInfo->RealMode.fRealOnV86Active)
6572 pVmcsInfo->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6573 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6574 AssertRCReturn(rc, rc);
6575 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6576 }
6577
6578 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6579 {
6580 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6581 if (pVmcsInfo->RealMode.fRealOnV86Active)
6582 pVmcsInfo->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6583 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6584 AssertRCReturn(rc, rc);
6585 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6586 }
6587
6588 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6589 {
6590 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6591 if (pVmcsInfo->RealMode.fRealOnV86Active)
6592 pVmcsInfo->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6593 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6594 AssertRCReturn(rc, rc);
6595 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6596 }
6597
6598 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6599 {
6600 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6601 if (pVmcsInfo->RealMode.fRealOnV86Active)
6602 pVmcsInfo->RealMode.AttrES.u = pCtx->es.Attr.u;
6603 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6604 AssertRCReturn(rc, rc);
6605 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6606 }
6607
6608 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6609 {
6610 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6611 if (pVmcsInfo->RealMode.fRealOnV86Active)
6612 pVmcsInfo->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6613 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6614 AssertRCReturn(rc, rc);
6615 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6616 }
6617
6618 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6619 {
6620 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6621 if (pVmcsInfo->RealMode.fRealOnV86Active)
6622 pVmcsInfo->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6623 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6624 AssertRCReturn(rc, rc);
6625 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6626 }
6627
6628#ifdef VBOX_STRICT
6629 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6630#endif
6631 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6632 pCtx->cs.Attr.u));
6633 }
6634
6635 /*
6636 * Guest TR.
6637 */
6638 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6639 {
6640 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6641
6642 /*
6643 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6644 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6645 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6646 */
6647 uint16_t u16Sel;
6648 uint32_t u32Limit;
6649 uint64_t u64Base;
6650 uint32_t u32AccessRights;
6651 if (!pVmcsInfo->RealMode.fRealOnV86Active)
6652 {
6653 u16Sel = pCtx->tr.Sel;
6654 u32Limit = pCtx->tr.u32Limit;
6655 u64Base = pCtx->tr.u64Base;
6656 u32AccessRights = pCtx->tr.Attr.u;
6657 }
6658 else
6659 {
6660 Assert(!pVmxTransient->fIsNestedGuest);
6661 Assert(pVM->hm.s.vmx.pRealModeTSS);
6662 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6663
6664 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6665 RTGCPHYS GCPhys;
6666 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6667 AssertRCReturn(rc, rc);
6668
6669 X86DESCATTR DescAttr;
6670 DescAttr.u = 0;
6671 DescAttr.n.u1Present = 1;
6672 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6673
6674 u16Sel = 0;
6675 u32Limit = HM_VTX_TSS_SIZE;
6676 u64Base = GCPhys;
6677 u32AccessRights = DescAttr.u;
6678 }
6679
6680 /* Validate. */
6681 Assert(!(u16Sel & RT_BIT(2)));
6682 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6683 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6684 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6685 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6686 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6687 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6688 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6689 Assert( (u32Limit & 0xfff) == 0xfff
6690 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6691 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6692 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6693
6694 rc = VMXWriteVmcs32(VMX_VMCS16_GUEST_TR_SEL, u16Sel);
6695 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit);
6696 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights);
6697 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_TR_BASE, u64Base);
6698 AssertRCReturn(rc, rc);
6699
6700 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6701 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6702 }
6703
6704 /*
6705 * Guest GDTR.
6706 */
6707 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6708 {
6709 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6710
6711 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt);
6712 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt);
6713 AssertRCReturn(rc, rc);
6714
6715 /* Validate. */
6716 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6717
6718 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6719 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6720 }
6721
6722 /*
6723 * Guest LDTR.
6724 */
6725 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6726 {
6727 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6728
6729 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6730 uint32_t u32Access;
6731 if ( !pVmxTransient->fIsNestedGuest
6732 && !pCtx->ldtr.Attr.u)
6733 u32Access = X86DESCATTR_UNUSABLE;
6734 else
6735 u32Access = pCtx->ldtr.Attr.u;
6736
6737 rc = VMXWriteVmcs32(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel);
6738 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit);
6739 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access);
6740 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base);
6741 AssertRCReturn(rc, rc);
6742
6743 /* Validate. */
6744 if (!(u32Access & X86DESCATTR_UNUSABLE))
6745 {
6746 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6747 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6748 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6749 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6750 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6751 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6752 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6753 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6754 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6755 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6756 }
6757
6758 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6759 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6760 }
6761
6762 /*
6763 * Guest IDTR.
6764 */
6765 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6766 {
6767 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6768
6769 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt);
6770 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt);
6771 AssertRCReturn(rc, rc);
6772
6773 /* Validate. */
6774 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6775
6776 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6777 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6778 }
6779
6780 return VINF_SUCCESS;
6781}
6782
6783
6784/**
6785 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6786 * areas.
6787 *
6788 * These MSRs will automatically be loaded to the host CPU on every successful
6789 * VM-entry and stored from the host CPU on every successful VM-exit.
6790 *
6791 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6792 * actual host MSR values are not- updated here for performance reasons. See
6793 * hmR0VmxExportHostMsrs().
6794 *
6795 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6796 *
6797 * @returns VBox status code.
6798 * @param pVCpu The cross context virtual CPU structure.
6799 * @param pVmxTransient The VMX-transient structure.
6800 *
6801 * @remarks No-long-jump zone!!!
6802 */
6803static int hmR0VmxExportGuestMsrs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6804{
6805 AssertPtr(pVCpu);
6806 AssertPtr(pVmxTransient);
6807
6808 PVM pVM = pVCpu->CTX_SUFF(pVM);
6809 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6810
6811 /*
6812 * MSRs that we use the auto-load/store MSR area in the VMCS.
6813 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs().
6814 * The host MSR values are updated when it's safe in hmR0VmxLazySaveHostMsrs().
6815 *
6816 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6817 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6818 * emulation, nothing to do here.
6819 */
6820 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6821 {
6822 if ( !pVmxTransient->fIsNestedGuest
6823 && pVM->hm.s.fAllow64BitGuests)
6824 {
6825#if HC_ARCH_BITS == 32
6826 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSCALL_MSRS | CPUMCTX_EXTRN_KERNEL_GS_BASE);
6827 Assert(!pVmxTransient->fIsNestedGuest);
6828
6829 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_LSTAR, pCtx->msrLSTAR, true, false);
6830 rc |= hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_STAR, pCtx->msrSTAR, true, false);
6831 rc |= hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_SF_MASK, pCtx->msrSFMASK, true, false);
6832 rc |= hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE, true, false);
6833 AssertRCReturn(rc, rc);
6834#endif
6835 }
6836 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6837 }
6838
6839 /*
6840 * Guest Sysenter MSRs.
6841 */
6842 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6843 {
6844 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6845
6846 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6847 {
6848 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6849 AssertRCReturn(rc, rc);
6850 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6851 }
6852
6853 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6854 {
6855 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6856 AssertRCReturn(rc, rc);
6857 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6858 }
6859
6860 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6861 {
6862 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6863 AssertRCReturn(rc, rc);
6864 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6865 }
6866 }
6867
6868 /*
6869 * Guest/host EFER MSR.
6870 */
6871 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6872 {
6873 /* Whether we are using the VMCS to swap the EFER MSR must have been
6874 determined earlier while exporting VM-entry/VM-exit controls. */
6875 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6876 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6877
6878 if (hmR0VmxShouldSwapEferMsr(pVCpu))
6879 {
6880 /*
6881 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6882 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6883 */
6884 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
6885 {
6886 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, pCtx->msrEFER);
6887 AssertRCReturn(rc, rc);
6888 }
6889 else
6890 {
6891 /*
6892 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6893 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6894 */
6895 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, pCtx->msrEFER,
6896 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6897 AssertRCReturn(rc, rc);
6898 }
6899 }
6900 else if (!pVM->hm.s.vmx.fSupportsVmcsEfer)
6901 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6902
6903 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6904 }
6905
6906 /*
6907 * Other MSRs.
6908 * Speculation Control (R/W).
6909 */
6910 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6911 {
6912 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6913 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6914 {
6915 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6916 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6917 AssertRCReturn(rc, rc);
6918 }
6919 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6920 }
6921
6922 return VINF_SUCCESS;
6923}
6924
6925
6926/**
6927 * Selects up the appropriate function to run guest code.
6928 *
6929 * @returns VBox status code.
6930 * @param pVCpu The cross context virtual CPU structure.
6931 * @param pVmxTransient The VMX-transient structure.
6932 *
6933 * @remarks No-long-jump zone!!!
6934 */
6935static int hmR0VmxSelectVMRunHandler(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6936{
6937 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6938 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6939
6940 if (CPUMIsGuestInLongModeEx(pCtx))
6941 {
6942#ifndef VBOX_ENABLE_64_BITS_GUESTS
6943 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
6944#endif
6945 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests); /* Guaranteed by hmR3InitFinalizeR0(). */
6946#if HC_ARCH_BITS == 32
6947 /* 32-bit host. We need to switch to 64-bit before running the 64-bit guest. */
6948 if (pVmcsInfo->pfnStartVM != VMXR0SwitcherStartVM64)
6949 {
6950#ifdef VBOX_STRICT
6951 if (pVmcsInfo->pfnStartVM != NULL) /* Very first VM-entry would have saved host-state already, ignore it. */
6952 {
6953 /* Currently, all mode changes sends us back to ring-3, so these should be set. See @bugref{6944}. */
6954 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
6955 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
6956 AssertMsg(fCtxChanged & (HM_CHANGED_VMX_ENTRY_EXIT_CTLS | HM_CHANGED_GUEST_EFER_MSR),
6957 ("fCtxChanged=%#RX64\n", fCtxChanged));
6958 }
6959#endif
6960 pVmcsInfo->pfnStartVM = VMXR0SwitcherStartVM64;
6961
6962 /* Mark that we've switched to 64-bit handler, we can't safely switch back to 32-bit for
6963 the rest of the VM run (until VM reset). See @bugref{8432#c7}. */
6964 pVmcsInfo->fSwitchedTo64on32 = true;
6965 Log4Func(("Selected 64-bit switcher\n"));
6966 }
6967#else
6968 /* 64-bit host. */
6969 pVmcsInfo->pfnStartVM = VMXR0StartVM64;
6970#endif
6971 }
6972 else
6973 {
6974 /* Guest is not in long mode, use the 32-bit handler. */
6975#if HC_ARCH_BITS == 32
6976 if ( pVmcsInfo->pfnStartVM != VMXR0StartVM32
6977 && !pVmcsInfo->fSwitchedTo64on32 /* If set, guest mode change does not imply switcher change. */
6978 && pVmcsInfo->pfnStartVM != NULL) /* Very first VM-entry would have saved host-state already, ignore it. */
6979 {
6980# ifdef VBOX_STRICT
6981 /* Currently, all mode changes sends us back to ring-3, so these should be set. See @bugref{6944}. */
6982 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
6983 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
6984 AssertMsg(fCtxChanged & (HM_CHANGED_VMX_ENTRY_EXIT_CTLS | HM_CHANGED_GUEST_EFER_MSR),
6985 ("fCtxChanged=%#RX64\n", fCtxChanged));
6986# endif
6987 }
6988# ifdef VBOX_ENABLE_64_BITS_GUESTS
6989 /*
6990 * Keep using the 64-bit switcher even though we're in 32-bit because of bad Intel
6991 * design, see @bugref{8432#c7}. If real-on-v86 mode is active, clear the 64-bit
6992 * switcher flag now because we know the guest is in a sane state where it's safe
6993 * to use the 32-bit switcher. Otherwise, check the guest state if it's safe to use
6994 * the much faster 32-bit switcher again.
6995 */
6996 if (!pVmcsInfo->fSwitchedTo64on32)
6997 {
6998 if (pVmcsInfo->pfnStartVM != VMXR0StartVM32)
6999 Log4Func(("Selected 32-bit switcher\n"));
7000 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
7001 }
7002 else
7003 {
7004 Assert(pVmcsInfo->pfnStartVM == VMXR0SwitcherStartVM64);
7005 if ( pVmcsInfo->RealMode.fRealOnV86Active
7006 || hmR0VmxIs32BitSwitcherSafe(pCtx))
7007 {
7008 pVmcsInfo->fSwitchedTo64on32 = false;
7009 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
7010 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR
7011 | HM_CHANGED_VMX_ENTRY_EXIT_CTLS
7012 | HM_CHANGED_HOST_CONTEXT);
7013 Log4Func(("Selected 32-bit switcher (safe)\n"));
7014 }
7015 }
7016# else
7017 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
7018# endif
7019#else
7020 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
7021#endif
7022 }
7023 Assert(pVmcsInfo->pfnStartVM);
7024 return VINF_SUCCESS;
7025}
7026
7027
7028/**
7029 * Wrapper for running the guest code in VT-x.
7030 *
7031 * @returns VBox status code, no informational status codes.
7032 * @param pVCpu The cross context virtual CPU structure.
7033 * @param pVmxTransient The VMX-transient structure.
7034 *
7035 * @remarks No-long-jump zone!!!
7036 */
7037DECLINLINE(int) hmR0VmxRunGuest(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient)
7038{
7039 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
7040 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7041 pCtx->fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
7042
7043 /** @todo Add stats for VMRESUME vs VMLAUNCH. */
7044
7045 /*
7046 * 64-bit Windows uses XMM registers in the kernel as the Microsoft compiler expresses
7047 * floating-point operations using SSE instructions. Some XMM registers (XMM6-XMM15) are
7048 * callee-saved and thus the need for this XMM wrapper.
7049 *
7050 * See MSDN "Configuring Programs for 64-bit/x64 Software Conventions / Register Usage".
7051 */
7052 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
7053 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
7054 PVM pVM = pVCpu->CTX_SUFF(pVM);
7055#ifdef VBOX_WITH_KERNEL_USING_XMM
7056 int rc = hmR0VMXStartVMWrapXMM(fResumeVM, pCtx, &pVCpu->hm.s.vmx.VmcsCache, pVM, pVCpu, pVmcsInfo->pfnStartVM);
7057#else
7058 int rc = pVmcsInfo->pfnStartVM(fResumeVM, pCtx, &pVCpu->hm.s.vmx.VmcsCache, pVM, pVCpu);
7059#endif
7060 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
7061 return rc;
7062}
7063
7064
7065/**
7066 * Reports world-switch error and dumps some useful debug info.
7067 *
7068 * @param pVCpu The cross context virtual CPU structure.
7069 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
7070 * @param pVmxTransient The VMX-transient structure (only
7071 * exitReason updated).
7072 */
7073static void hmR0VmxReportWorldSwitchError(PVMCPU pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
7074{
7075 Assert(pVCpu);
7076 Assert(pVmxTransient);
7077 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
7078
7079 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
7080 switch (rcVMRun)
7081 {
7082 case VERR_VMX_INVALID_VMXON_PTR:
7083 AssertFailed();
7084 break;
7085 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
7086 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
7087 {
7088 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
7089 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
7090 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
7091 AssertRC(rc);
7092
7093 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
7094 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
7095 Cannot do it here as we may have been long preempted. */
7096
7097#ifdef VBOX_STRICT
7098 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7099 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
7100 pVmxTransient->uExitReason));
7101 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
7102 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
7103 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
7104 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
7105 else
7106 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
7107 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
7108 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
7109
7110 /* VMX control bits. */
7111 uint32_t u32Val;
7112 uint64_t u64Val;
7113 RTHCUINTREG uHCReg;
7114 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val); AssertRC(rc);
7115 Log4(("VMX_VMCS32_CTRL_PIN_EXEC %#RX32\n", u32Val));
7116 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val); AssertRC(rc);
7117 Log4(("VMX_VMCS32_CTRL_PROC_EXEC %#RX32\n", u32Val));
7118 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
7119 {
7120 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val); AssertRC(rc);
7121 Log4(("VMX_VMCS32_CTRL_PROC_EXEC2 %#RX32\n", u32Val));
7122 }
7123 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val); AssertRC(rc);
7124 Log4(("VMX_VMCS32_CTRL_ENTRY %#RX32\n", u32Val));
7125 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val); AssertRC(rc);
7126 Log4(("VMX_VMCS32_CTRL_EXIT %#RX32\n", u32Val));
7127 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_CR3_TARGET_COUNT, &u32Val); AssertRC(rc);
7128 Log4(("VMX_VMCS32_CTRL_CR3_TARGET_COUNT %#RX32\n", u32Val));
7129 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32Val); AssertRC(rc);
7130 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", u32Val));
7131 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &u32Val); AssertRC(rc);
7132 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", u32Val));
7133 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &u32Val); AssertRC(rc);
7134 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %u\n", u32Val));
7135 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, &u32Val); AssertRC(rc);
7136 Log4(("VMX_VMCS32_CTRL_TPR_THRESHOLD %u\n", u32Val));
7137 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &u32Val); AssertRC(rc);
7138 Log4(("VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT %u (guest MSRs)\n", u32Val));
7139 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &u32Val); AssertRC(rc);
7140 Log4(("VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT %u (host MSRs)\n", u32Val));
7141 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &u32Val); AssertRC(rc);
7142 Log4(("VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT %u (guest MSRs)\n", u32Val));
7143 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val); AssertRC(rc);
7144 Log4(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP %#RX32\n", u32Val));
7145 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, &u32Val); AssertRC(rc);
7146 Log4(("VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK %#RX32\n", u32Val));
7147 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, &u32Val); AssertRC(rc);
7148 Log4(("VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH %#RX32\n", u32Val));
7149 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, &uHCReg); AssertRC(rc);
7150 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RHr\n", uHCReg));
7151 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, &uHCReg); AssertRC(rc);
7152 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
7153 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, &uHCReg); AssertRC(rc);
7154 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RHr\n", uHCReg));
7155 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_READ_SHADOW, &uHCReg); AssertRC(rc);
7156 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
7157 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
7158 {
7159 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
7160 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
7161 }
7162
7163 /* Guest bits. */
7164 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RIP, &u64Val); AssertRC(rc);
7165 Log4(("Old Guest Rip %#RX64 New %#RX64\n", pVCpu->cpum.GstCtx.rip, u64Val));
7166 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RSP, &u64Val); AssertRC(rc);
7167 Log4(("Old Guest Rsp %#RX64 New %#RX64\n", pVCpu->cpum.GstCtx.rsp, u64Val));
7168 rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &u32Val); AssertRC(rc);
7169 Log4(("Old Guest Rflags %#RX32 New %#RX32\n", pVCpu->cpum.GstCtx.eflags.u32, u32Val));
7170 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid)
7171 {
7172 rc = VMXReadVmcs32(VMX_VMCS16_VPID, &u32Val); AssertRC(rc);
7173 Log4(("VMX_VMCS16_VPID %u\n", u32Val));
7174 }
7175
7176 /* Host bits. */
7177 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_CR0, &uHCReg); AssertRC(rc);
7178 Log4(("Host CR0 %#RHr\n", uHCReg));
7179 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_CR3, &uHCReg); AssertRC(rc);
7180 Log4(("Host CR3 %#RHr\n", uHCReg));
7181 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_CR4, &uHCReg); AssertRC(rc);
7182 Log4(("Host CR4 %#RHr\n", uHCReg));
7183
7184 RTGDTR HostGdtr;
7185 PCX86DESCHC pDesc;
7186 ASMGetGDTR(&HostGdtr);
7187 rc = VMXReadVmcs32(VMX_VMCS16_HOST_CS_SEL, &u32Val); AssertRC(rc);
7188 Log4(("Host CS %#08x\n", u32Val));
7189 if (u32Val < HostGdtr.cbGdt)
7190 {
7191 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7192 hmR0DumpDescriptor(pDesc, u32Val, "CS: ");
7193 }
7194
7195 rc = VMXReadVmcs32(VMX_VMCS16_HOST_DS_SEL, &u32Val); AssertRC(rc);
7196 Log4(("Host DS %#08x\n", u32Val));
7197 if (u32Val < HostGdtr.cbGdt)
7198 {
7199 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7200 hmR0DumpDescriptor(pDesc, u32Val, "DS: ");
7201 }
7202
7203 rc = VMXReadVmcs32(VMX_VMCS16_HOST_ES_SEL, &u32Val); AssertRC(rc);
7204 Log4(("Host ES %#08x\n", u32Val));
7205 if (u32Val < HostGdtr.cbGdt)
7206 {
7207 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7208 hmR0DumpDescriptor(pDesc, u32Val, "ES: ");
7209 }
7210
7211 rc = VMXReadVmcs32(VMX_VMCS16_HOST_FS_SEL, &u32Val); AssertRC(rc);
7212 Log4(("Host FS %#08x\n", u32Val));
7213 if (u32Val < HostGdtr.cbGdt)
7214 {
7215 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7216 hmR0DumpDescriptor(pDesc, u32Val, "FS: ");
7217 }
7218
7219 rc = VMXReadVmcs32(VMX_VMCS16_HOST_GS_SEL, &u32Val); AssertRC(rc);
7220 Log4(("Host GS %#08x\n", u32Val));
7221 if (u32Val < HostGdtr.cbGdt)
7222 {
7223 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7224 hmR0DumpDescriptor(pDesc, u32Val, "GS: ");
7225 }
7226
7227 rc = VMXReadVmcs32(VMX_VMCS16_HOST_SS_SEL, &u32Val); AssertRC(rc);
7228 Log4(("Host SS %#08x\n", u32Val));
7229 if (u32Val < HostGdtr.cbGdt)
7230 {
7231 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7232 hmR0DumpDescriptor(pDesc, u32Val, "SS: ");
7233 }
7234
7235 rc = VMXReadVmcs32(VMX_VMCS16_HOST_TR_SEL, &u32Val); AssertRC(rc);
7236 Log4(("Host TR %#08x\n", u32Val));
7237 if (u32Val < HostGdtr.cbGdt)
7238 {
7239 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7240 hmR0DumpDescriptor(pDesc, u32Val, "TR: ");
7241 }
7242
7243 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_TR_BASE, &uHCReg); AssertRC(rc);
7244 Log4(("Host TR Base %#RHv\n", uHCReg));
7245 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_GDTR_BASE, &uHCReg); AssertRC(rc);
7246 Log4(("Host GDTR Base %#RHv\n", uHCReg));
7247 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_IDTR_BASE, &uHCReg); AssertRC(rc);
7248 Log4(("Host IDTR Base %#RHv\n", uHCReg));
7249 rc = VMXReadVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, &u32Val); AssertRC(rc);
7250 Log4(("Host SYSENTER CS %#08x\n", u32Val));
7251 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_SYSENTER_EIP, &uHCReg); AssertRC(rc);
7252 Log4(("Host SYSENTER EIP %#RHv\n", uHCReg));
7253 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_SYSENTER_ESP, &uHCReg); AssertRC(rc);
7254 Log4(("Host SYSENTER ESP %#RHv\n", uHCReg));
7255 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_RSP, &uHCReg); AssertRC(rc);
7256 Log4(("Host RSP %#RHv\n", uHCReg));
7257 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_RIP, &uHCReg); AssertRC(rc);
7258 Log4(("Host RIP %#RHv\n", uHCReg));
7259# if HC_ARCH_BITS == 64
7260 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
7261 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
7262 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
7263 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
7264 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
7265 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
7266# endif
7267#endif /* VBOX_STRICT */
7268 break;
7269 }
7270
7271 default:
7272 /* Impossible */
7273 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
7274 break;
7275 }
7276}
7277
7278
7279#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
7280# ifndef VMX_USE_CACHED_VMCS_ACCESSES
7281# error "VMX_USE_CACHED_VMCS_ACCESSES not defined when it should be!"
7282# endif
7283
7284/**
7285 * Initialize the VMCS-Read cache.
7286 *
7287 * The VMCS cache is used for 32-bit hosts running 64-bit guests (except 32-bit
7288 * Darwin which runs with 64-bit paging in 32-bit mode) for 64-bit fields that
7289 * cannot be accessed in 32-bit mode. Some 64-bit fields -can- be accessed
7290 * (those that have a 32-bit FULL & HIGH part).
7291 *
7292 * @param pVCpu The cross context virtual CPU structure.
7293 */
7294static void hmR0VmxInitVmcsReadCache(PVMCPU pVCpu)
7295{
7296#define VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, idxField) \
7297 do { \
7298 Assert(pCache->Read.aField[idxField##_CACHE_IDX] == 0); \
7299 pCache->Read.aField[idxField##_CACHE_IDX] = idxField; \
7300 pCache->Read.aFieldVal[idxField##_CACHE_IDX] = 0; \
7301 ++cReadFields; \
7302 } while (0)
7303
7304 PVMXVMCSCACHE pCache = &pVCpu->hm.s.vmx.VmcsCache;
7305 uint32_t cReadFields = 0;
7306
7307 /*
7308 * Don't remove the #if 0'd fields in this code. They're listed here for consistency
7309 * and serve to indicate exceptions to the rules.
7310 */
7311
7312 /* Guest-natural selector base fields. */
7313#if 0
7314 /* These are 32-bit in practice. See Intel spec. 2.5 "Control Registers". */
7315 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR0);
7316 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR4);
7317#endif
7318 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_ES_BASE);
7319 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CS_BASE);
7320 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_SS_BASE);
7321 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_DS_BASE);
7322 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_FS_BASE);
7323 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_GS_BASE);
7324 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_LDTR_BASE);
7325 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_TR_BASE);
7326 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_GDTR_BASE);
7327 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_IDTR_BASE);
7328 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_RSP);
7329 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_RIP);
7330#if 0
7331 /* Unused natural width guest-state fields. */
7332 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS);
7333 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR3); /* Handled in nested paging case */
7334#endif
7335 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_SYSENTER_ESP);
7336 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_SYSENTER_EIP);
7337
7338 /* 64-bit guest-state fields; unused as we use two 32-bit VMREADs for
7339 these 64-bit fields (using "FULL" and "HIGH" fields). */
7340#if 0
7341 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL);
7342 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_DEBUGCTL_FULL);
7343 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PAT_FULL);
7344 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_EFER_FULL);
7345 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL);
7346 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE0_FULL);
7347 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE1_FULL);
7348 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE2_FULL);
7349 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE3_FULL);
7350#endif
7351
7352 /* Natural width guest-state fields. */
7353 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_RO_EXIT_QUALIFICATION);
7354 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_RO_GUEST_LINEAR_ADDR);
7355
7356 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
7357 {
7358 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR3);
7359 AssertMsg(cReadFields == VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX, ("cReadFields=%u expected %u\n", cReadFields,
7360 VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX));
7361 pCache->Read.cValidEntries = VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX;
7362 }
7363 else
7364 {
7365 AssertMsg(cReadFields == VMX_VMCS_MAX_CACHE_IDX, ("cReadFields=%u expected %u\n", cReadFields, VMX_VMCS_MAX_CACHE_IDX));
7366 pCache->Read.cValidEntries = VMX_VMCS_MAX_CACHE_IDX;
7367 }
7368
7369#undef VMXLOCAL_INIT_READ_CACHE_FIELD
7370}
7371
7372
7373/**
7374 * Writes a field into the VMCS. This can either directly invoke a VMWRITE or
7375 * queue up the VMWRITE by using the VMCS write cache (on 32-bit hosts, except
7376 * darwin, running 64-bit guests).
7377 *
7378 * @returns VBox status code.
7379 * @param pVCpu The cross context virtual CPU structure.
7380 * @param idxField The VMCS field encoding.
7381 * @param u64Val 16, 32 or 64-bit value.
7382 */
7383VMMR0DECL(int) VMXWriteVmcs64Ex(PVMCPU pVCpu, uint32_t idxField, uint64_t u64Val)
7384{
7385 AssertPtr(pVCpu);
7386 int rc;
7387 switch (idxField)
7388 {
7389 /*
7390 * These fields consists of a "FULL" and a "HIGH" part which can be written to individually.
7391 */
7392 /* 64-bit Control fields. */
7393 case VMX_VMCS64_CTRL_IO_BITMAP_A_FULL:
7394 case VMX_VMCS64_CTRL_IO_BITMAP_B_FULL:
7395 case VMX_VMCS64_CTRL_MSR_BITMAP_FULL:
7396 case VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL:
7397 case VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL:
7398 case VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL:
7399 case VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL:
7400 case VMX_VMCS64_CTRL_TSC_OFFSET_FULL:
7401 case VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL:
7402 case VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL:
7403 case VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL:
7404 case VMX_VMCS64_CTRL_EPTP_FULL:
7405 case VMX_VMCS64_CTRL_EPTP_LIST_FULL:
7406 /* 64-bit Guest-state fields. */
7407 case VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL:
7408 case VMX_VMCS64_GUEST_DEBUGCTL_FULL:
7409 case VMX_VMCS64_GUEST_PAT_FULL:
7410 case VMX_VMCS64_GUEST_EFER_FULL:
7411 case VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL:
7412 case VMX_VMCS64_GUEST_PDPTE0_FULL:
7413 case VMX_VMCS64_GUEST_PDPTE1_FULL:
7414 case VMX_VMCS64_GUEST_PDPTE2_FULL:
7415 case VMX_VMCS64_GUEST_PDPTE3_FULL:
7416 /* 64-bit Host-state fields. */
7417 case VMX_VMCS64_HOST_PAT_FULL:
7418 case VMX_VMCS64_HOST_EFER_FULL:
7419 case VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL:
7420 {
7421 rc = VMXWriteVmcs32(idxField, RT_LO_U32(u64Val));
7422 rc |= VMXWriteVmcs32(idxField + 1, RT_HI_U32(u64Val));
7423 break;
7424 }
7425
7426 /*
7427 * These fields do not have high and low parts. Queue up the VMWRITE by using the VMCS write-cache (for 64-bit
7428 * values). When we switch the host to 64-bit mode for running 64-bit guests, these VMWRITEs get executed then.
7429 */
7430 /* Natural-width Guest-state fields. */
7431 case VMX_VMCS_GUEST_CR3:
7432 case VMX_VMCS_GUEST_ES_BASE:
7433 case VMX_VMCS_GUEST_CS_BASE:
7434 case VMX_VMCS_GUEST_SS_BASE:
7435 case VMX_VMCS_GUEST_DS_BASE:
7436 case VMX_VMCS_GUEST_FS_BASE:
7437 case VMX_VMCS_GUEST_GS_BASE:
7438 case VMX_VMCS_GUEST_LDTR_BASE:
7439 case VMX_VMCS_GUEST_TR_BASE:
7440 case VMX_VMCS_GUEST_GDTR_BASE:
7441 case VMX_VMCS_GUEST_IDTR_BASE:
7442 case VMX_VMCS_GUEST_RSP:
7443 case VMX_VMCS_GUEST_RIP:
7444 case VMX_VMCS_GUEST_SYSENTER_ESP:
7445 case VMX_VMCS_GUEST_SYSENTER_EIP:
7446 {
7447 if (!(RT_HI_U32(u64Val)))
7448 {
7449 /* If this field is 64-bit, VT-x will zero out the top bits. */
7450 rc = VMXWriteVmcs32(idxField, RT_LO_U32(u64Val));
7451 }
7452 else
7453 {
7454 /* Assert that only the 32->64 switcher case should ever come here. */
7455 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests);
7456 rc = VMXWriteCachedVmcsEx(pVCpu, idxField, u64Val);
7457 }
7458 break;
7459 }
7460
7461 default:
7462 {
7463 AssertMsgFailed(("VMXWriteVmcs64Ex: Invalid field %#RX32 (pVCpu=%p u64Val=%#RX64)\n", idxField, pVCpu, u64Val));
7464 pVCpu->hm.s.u32HMError = idxField;
7465 rc = VERR_INVALID_PARAMETER;
7466 break;
7467 }
7468 }
7469 AssertRCReturn(rc, rc);
7470 return rc;
7471}
7472
7473
7474/**
7475 * Queue up a VMWRITE by using the VMCS write cache.
7476 * This is only used on 32-bit hosts (except darwin) for 64-bit guests.
7477 *
7478 * @param pVCpu The cross context virtual CPU structure.
7479 * @param idxField The VMCS field encoding.
7480 * @param u64Val 16, 32 or 64-bit value.
7481 */
7482VMMR0DECL(int) VMXWriteCachedVmcsEx(PVMCPU pVCpu, uint32_t idxField, uint64_t u64Val)
7483{
7484 AssertPtr(pVCpu);
7485 PVMXVMCSCACHE pCache = &pVCpu->hm.s.vmx.VmcsCache;
7486
7487 AssertMsgReturn(pCache->Write.cValidEntries < VMX_VMCS_CACHE_MAX_ENTRY - 1,
7488 ("entries=%u\n", pCache->Write.cValidEntries), VERR_ACCESS_DENIED);
7489
7490 /* Make sure there are no duplicates. */
7491 for (uint32_t i = 0; i < pCache->Write.cValidEntries; i++)
7492 {
7493 if (pCache->Write.aField[i] == idxField)
7494 {
7495 pCache->Write.aFieldVal[i] = u64Val;
7496 return VINF_SUCCESS;
7497 }
7498 }
7499
7500 pCache->Write.aField[pCache->Write.cValidEntries] = idxField;
7501 pCache->Write.aFieldVal[pCache->Write.cValidEntries] = u64Val;
7502 pCache->Write.cValidEntries++;
7503 return VINF_SUCCESS;
7504}
7505#endif /* HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS) */
7506
7507
7508/**
7509 * Sets up the usage of TSC-offsetting and updates the VMCS.
7510 *
7511 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
7512 * VMX-preemption timer.
7513 *
7514 * @returns VBox status code.
7515 * @param pVCpu The cross context virtual CPU structure.
7516 * @param pVmxTransient The VMX-transient structure.
7517 *
7518 * @remarks No-long-jump zone!!!
7519 */
7520static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
7521{
7522 bool fOffsettedTsc;
7523 bool fParavirtTsc;
7524 uint64_t uTscOffset;
7525 PVM pVM = pVCpu->CTX_SUFF(pVM);
7526 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7527
7528 if (pVM->hm.s.vmx.fUsePreemptTimer)
7529 {
7530 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc);
7531
7532 /* Make sure the returned values have sane upper and lower boundaries. */
7533 uint64_t u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
7534 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second */
7535 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
7536 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
7537
7538 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
7539 * preemption timers here. We probably need to clamp the preemption timer,
7540 * after converting the timer value to the host. */
7541 uint32_t cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
7542 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
7543 AssertRC(rc);
7544 }
7545 else
7546 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
7547
7548 if (fParavirtTsc)
7549 {
7550 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
7551 information before every VM-entry, hence disable it for performance sake. */
7552#if 0
7553 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
7554 AssertRC(rc);
7555#endif
7556 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
7557 }
7558
7559 if ( fOffsettedTsc
7560 && RT_LIKELY(!pVCpu->hm.s.fDebugWantRdTscExit))
7561 {
7562 if (pVmxTransient->fIsNestedGuest)
7563 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
7564 hmR0VmxSetTscOffsetVmcs(pVCpu, pVmcsInfo, uTscOffset);
7565 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7566 }
7567 else
7568 {
7569 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
7570 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7571 }
7572}
7573
7574
7575/**
7576 * Gets the IEM exception flags for the specified vector and IDT vectoring /
7577 * VM-exit interruption info type.
7578 *
7579 * @returns The IEM exception flags.
7580 * @param uVector The event vector.
7581 * @param uVmxEventType The VMX event type.
7582 *
7583 * @remarks This function currently only constructs flags required for
7584 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
7585 * and CR2 aspects of an exception are not included).
7586 */
7587static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
7588{
7589 uint32_t fIemXcptFlags;
7590 switch (uVmxEventType)
7591 {
7592 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
7593 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
7594 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
7595 break;
7596
7597 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
7598 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
7599 break;
7600
7601 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
7602 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
7603 break;
7604
7605 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
7606 {
7607 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7608 if (uVector == X86_XCPT_BP)
7609 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
7610 else if (uVector == X86_XCPT_OF)
7611 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
7612 else
7613 {
7614 fIemXcptFlags = 0;
7615 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
7616 }
7617 break;
7618 }
7619
7620 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
7621 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7622 break;
7623
7624 default:
7625 fIemXcptFlags = 0;
7626 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
7627 break;
7628 }
7629 return fIemXcptFlags;
7630}
7631
7632
7633/**
7634 * Sets an event as a pending event to be injected into the guest.
7635 *
7636 * @param pVCpu The cross context virtual CPU structure.
7637 * @param u32IntInfo The VM-entry interruption-information field.
7638 * @param cbInstr The VM-entry instruction length in bytes (for software
7639 * interrupts, exceptions and privileged software
7640 * exceptions).
7641 * @param u32ErrCode The VM-entry exception error code.
7642 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
7643 * page-fault.
7644 */
7645DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPU pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
7646 RTGCUINTPTR GCPtrFaultAddress)
7647{
7648 Assert(!pVCpu->hm.s.Event.fPending);
7649 pVCpu->hm.s.Event.fPending = true;
7650 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
7651 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
7652 pVCpu->hm.s.Event.cbInstr = cbInstr;
7653 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
7654}
7655
7656
7657/**
7658 * Sets an external interrupt as pending-for-injection into the VM.
7659 *
7660 * @param pVCpu The cross context virtual CPU structure.
7661 * @param u8Interrupt The external interrupt vector.
7662 */
7663DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPU pVCpu, uint8_t u8Interrupt)
7664{
7665 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
7666 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
7667 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7668 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7669 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7670}
7671
7672
7673/**
7674 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
7675 *
7676 * @param pVCpu The cross context virtual CPU structure.
7677 */
7678DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPU pVCpu)
7679{
7680 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
7681 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
7682 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7683 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7684 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7685}
7686
7687
7688/**
7689 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
7690 *
7691 * @param pVCpu The cross context virtual CPU structure.
7692 */
7693DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPU pVCpu)
7694{
7695 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
7696 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7697 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7698 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7699 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7700}
7701
7702
7703/**
7704 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
7705 *
7706 * @param pVCpu The cross context virtual CPU structure.
7707 */
7708DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPU pVCpu)
7709{
7710 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
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, 0)
7713 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7714 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7715}
7716
7717
7718/**
7719 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
7720 *
7721 * @param pVCpu The cross context virtual CPU structure.
7722 */
7723DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPU pVCpu)
7724{
7725 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
7726 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7727 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7728 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7729 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7730}
7731
7732
7733#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7734/**
7735 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
7736 *
7737 * @param pVCpu The cross context virtual CPU structure.
7738 * @param u32ErrCode The error code for the general-protection exception.
7739 */
7740DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPU pVCpu, uint32_t u32ErrCode)
7741{
7742 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
7743 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7744 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7745 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7746 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7747}
7748
7749
7750/**
7751 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
7752 *
7753 * @param pVCpu The cross context virtual CPU structure.
7754 * @param u32ErrCode The error code for the stack exception.
7755 */
7756DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPU pVCpu, uint32_t u32ErrCode)
7757{
7758 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
7759 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7760 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7761 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7762 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7763}
7764#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
7765
7766
7767/**
7768 * Fixes up attributes for the specified segment register.
7769 *
7770 * @param pVCpu The cross context virtual CPU structure.
7771 * @param pSelReg The segment register that needs fixing.
7772 * @param idxSel The VMCS field for the corresponding segment register.
7773 */
7774static void hmR0VmxFixUnusableSegRegAttr(PVMCPU pVCpu, PCPUMSELREG pSelReg, uint32_t idxSel)
7775{
7776 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
7777
7778 /*
7779 * If VT-x marks the segment as unusable, most other bits remain undefined:
7780 * - For CS the L, D and G bits have meaning.
7781 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
7782 * - For the remaining data segments no bits are defined.
7783 *
7784 * The present bit and the unusable bit has been observed to be set at the
7785 * same time (the selector was supposed to be invalid as we started executing
7786 * a V8086 interrupt in ring-0).
7787 *
7788 * What should be important for the rest of the VBox code, is that the P bit is
7789 * cleared. Some of the other VBox code recognizes the unusable bit, but
7790 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7791 * safe side here, we'll strip off P and other bits we don't care about. If
7792 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7793 *
7794 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7795 */
7796#ifdef VBOX_STRICT
7797 uint32_t const uAttr = pSelReg->Attr.u;
7798#endif
7799
7800 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7801 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7802 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7803
7804#ifdef VBOX_STRICT
7805 VMMRZCallRing3Disable(pVCpu);
7806 Log4Func(("Unusable %#x: sel=%#x attr=%#x -> %#x\n", idxSel, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7807# ifdef DEBUG_bird
7808 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7809 ("%#x: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7810 idxSel, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7811# endif
7812 VMMRZCallRing3Enable(pVCpu);
7813 NOREF(uAttr);
7814#endif
7815 RT_NOREF2(pVCpu, idxSel);
7816}
7817
7818
7819/**
7820 * Imports a guest segment register from the current VMCS into the guest-CPU
7821 * context.
7822 *
7823 * @returns VBox status code.
7824 * @param pVCpu The cross context virtual CPU structure.
7825 * @param iSegReg The segment register number (X86_SREG_XXX).
7826 *
7827 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7828 * do not log!
7829 */
7830static int hmR0VmxImportGuestSegReg(PVMCPU pVCpu, uint8_t iSegReg)
7831{
7832 Assert(iSegReg < X86_SREG_COUNT);
7833
7834 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
7835 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
7836 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
7837#ifdef VMX_USE_CACHED_VMCS_ACCESSES
7838 uint32_t const idxBase = g_aVmcsCacheSegBase[iSegReg];
7839#else
7840 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
7841#endif
7842 uint64_t u64Base;
7843 uint32_t u32Sel, u32Limit, u32Attr;
7844 int rc = VMXReadVmcs32(idxSel, &u32Sel);
7845 rc |= VMXReadVmcs32(idxLimit, &u32Limit);
7846 rc |= VMXReadVmcs32(idxAttr, &u32Attr);
7847 rc |= VMXReadVmcsGstNByIdxVal(idxBase, &u64Base);
7848 if (RT_SUCCESS(rc))
7849 {
7850 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7851 pSelReg->Sel = u32Sel;
7852 pSelReg->ValidSel = u32Sel;
7853 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7854 pSelReg->u32Limit = u32Limit;
7855 pSelReg->u64Base = u64Base;
7856 pSelReg->Attr.u = u32Attr;
7857 if (u32Attr & X86DESCATTR_UNUSABLE)
7858 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, idxSel);
7859 }
7860 return rc;
7861}
7862
7863
7864/**
7865 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7866 *
7867 * @returns VBox status code.
7868 * @param pVCpu The cross context virtual CPU structure.
7869 *
7870 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7871 * do not log!
7872 */
7873static int hmR0VmxImportGuestLdtr(PVMCPU pVCpu)
7874{
7875 uint64_t u64Base;
7876 uint32_t u32Sel, u32Limit, u32Attr;
7877 int rc = VMXReadVmcs32(VMX_VMCS16_GUEST_LDTR_SEL, &u32Sel);
7878 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit);
7879 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr);
7880 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_LDTR_BASE, &u64Base);
7881 if (RT_SUCCESS(rc))
7882 {
7883 pVCpu->cpum.GstCtx.ldtr.Sel = u32Sel;
7884 pVCpu->cpum.GstCtx.ldtr.ValidSel = u32Sel;
7885 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7886 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7887 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7888 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7889 if (u32Attr & X86DESCATTR_UNUSABLE)
7890 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, VMX_VMCS16_GUEST_LDTR_SEL);
7891 }
7892 return rc;
7893}
7894
7895
7896/**
7897 * Imports the guest TR from the current VMCS into the guest-CPU context.
7898 *
7899 * @returns VBox status code.
7900 * @param pVCpu The cross context virtual CPU structure.
7901 *
7902 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7903 * do not log!
7904 */
7905static int hmR0VmxImportGuestTr(PVMCPU pVCpu)
7906{
7907 uint32_t u32Sel, u32Limit, u32Attr;
7908 uint64_t u64Base;
7909 int rc = VMXReadVmcs32(VMX_VMCS16_GUEST_TR_SEL, &u32Sel);
7910 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit);
7911 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr);
7912 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_TR_BASE, &u64Base);
7913 AssertRCReturn(rc, rc);
7914
7915 pVCpu->cpum.GstCtx.tr.Sel = u32Sel;
7916 pVCpu->cpum.GstCtx.tr.ValidSel = u32Sel;
7917 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7918 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7919 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7920 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7921 /* TR is the only selector that can never be unusable. */
7922 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7923 return VINF_SUCCESS;
7924}
7925
7926
7927/**
7928 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7929 *
7930 * @returns VBox status code.
7931 * @param pVCpu The cross context virtual CPU structure.
7932 *
7933 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7934 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7935 * instead!!!
7936 */
7937static int hmR0VmxImportGuestRip(PVMCPU pVCpu)
7938{
7939 uint64_t u64Val;
7940 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7941 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7942 {
7943 int rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RIP, &u64Val);
7944 if (RT_SUCCESS(rc))
7945 {
7946 pCtx->rip = u64Val;
7947 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7948 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7949 }
7950 return rc;
7951 }
7952 return VINF_SUCCESS;
7953}
7954
7955
7956/**
7957 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7958 *
7959 * @returns VBox status code.
7960 * @param pVCpu The cross context virtual CPU structure.
7961 * @param pVmcsInfo The VMCS info. object.
7962 *
7963 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7964 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7965 * instead!!!
7966 */
7967static int hmR0VmxImportGuestRFlags(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
7968{
7969 uint32_t u32Val;
7970 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7971 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7972 {
7973 int rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &u32Val);
7974 if (RT_SUCCESS(rc))
7975 {
7976 pCtx->eflags.u32 = u32Val;
7977
7978 /* Restore eflags for real-on-v86-mode hack. */
7979 if (pVmcsInfo->RealMode.fRealOnV86Active)
7980 {
7981 pCtx->eflags.Bits.u1VM = 0;
7982 pCtx->eflags.Bits.u2IOPL = pVmcsInfo->RealMode.Eflags.Bits.u2IOPL;
7983 }
7984 }
7985 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7986 return rc;
7987 }
7988 return VINF_SUCCESS;
7989}
7990
7991
7992/**
7993 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7994 * context.
7995 *
7996 * @returns VBox status code.
7997 * @param pVCpu The cross context virtual CPU structure.
7998 * @param pVmcsInfo The VMCS info. object.
7999 *
8000 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
8001 * do not log!
8002 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
8003 * instead!!!
8004 */
8005static int hmR0VmxImportGuestIntrState(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
8006{
8007 uint32_t u32Val;
8008 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val);
8009 if (RT_SUCCESS(rc))
8010 {
8011 if (!u32Val)
8012 {
8013 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
8014 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
8015
8016 CPUMSetGuestNmiBlocking(pVCpu, false);
8017 }
8018 else
8019 {
8020 /*
8021 * We must import RIP here to set our EM interrupt-inhibited state.
8022 * We also import RFLAGS as our code that evaluates pending interrupts
8023 * before VM-entry requires it.
8024 */
8025 rc = hmR0VmxImportGuestRip(pVCpu);
8026 rc |= hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
8027 if (RT_SUCCESS(rc))
8028 {
8029 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
8030 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
8031 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
8032 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
8033
8034 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
8035 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
8036 }
8037 }
8038 }
8039 return rc;
8040}
8041
8042
8043/**
8044 * Worker for VMXR0ImportStateOnDemand.
8045 *
8046 * @returns VBox status code.
8047 * @param pVCpu The cross context virtual CPU structure.
8048 * @param pVmcsInfo The VMCS info. object.
8049 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
8050 */
8051static int hmR0VmxImportGuestState(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
8052{
8053#define VMXLOCAL_BREAK_RC(a_rc) \
8054 if (RT_SUCCESS(a_rc)) \
8055 { } \
8056 else \
8057 break
8058
8059 int rc = VINF_SUCCESS;
8060 PVM pVM = pVCpu->CTX_SUFF(pVM);
8061 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8062 uint64_t u64Val;
8063 uint32_t u32Val;
8064
8065 /*
8066 * Note! This is hack to workaround a mysterious BSOD observed with release builds
8067 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
8068 * neither are other host platforms.
8069 *
8070 * Committing this temporarily as it prevents BSOD.
8071 *
8072 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
8073 */
8074#ifdef RT_OS_WINDOWS
8075 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
8076 return VERR_HM_IPE_1;
8077#endif
8078
8079 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
8080
8081 /*
8082 * We disable interrupts to make the updating of the state and in particular
8083 * the fExtrn modification atomic wrt to preemption hooks.
8084 */
8085 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
8086
8087 fWhat &= pCtx->fExtrn;
8088 if (fWhat)
8089 {
8090 do
8091 {
8092 if (fWhat & CPUMCTX_EXTRN_RIP)
8093 {
8094 rc = hmR0VmxImportGuestRip(pVCpu);
8095 VMXLOCAL_BREAK_RC(rc);
8096 }
8097
8098 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
8099 {
8100 rc = hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
8101 VMXLOCAL_BREAK_RC(rc);
8102 }
8103
8104 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
8105 {
8106 rc = hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
8107 VMXLOCAL_BREAK_RC(rc);
8108 }
8109
8110 if (fWhat & CPUMCTX_EXTRN_RSP)
8111 {
8112 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RSP, &u64Val);
8113 VMXLOCAL_BREAK_RC(rc);
8114 pCtx->rsp = u64Val;
8115 }
8116
8117 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
8118 {
8119 bool const fRealOnV86Active = pVmcsInfo->RealMode.fRealOnV86Active;
8120 if (fWhat & CPUMCTX_EXTRN_CS)
8121 {
8122 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
8123 rc |= hmR0VmxImportGuestRip(pVCpu);
8124 if (fRealOnV86Active)
8125 pCtx->cs.Attr.u = pVmcsInfo->RealMode.AttrCS.u;
8126 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
8127 }
8128 if (fWhat & CPUMCTX_EXTRN_SS)
8129 {
8130 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
8131 if (fRealOnV86Active)
8132 pCtx->ss.Attr.u = pVmcsInfo->RealMode.AttrSS.u;
8133 }
8134 if (fWhat & CPUMCTX_EXTRN_DS)
8135 {
8136 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
8137 if (fRealOnV86Active)
8138 pCtx->ds.Attr.u = pVmcsInfo->RealMode.AttrDS.u;
8139 }
8140 if (fWhat & CPUMCTX_EXTRN_ES)
8141 {
8142 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
8143 if (fRealOnV86Active)
8144 pCtx->es.Attr.u = pVmcsInfo->RealMode.AttrES.u;
8145 }
8146 if (fWhat & CPUMCTX_EXTRN_FS)
8147 {
8148 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
8149 if (fRealOnV86Active)
8150 pCtx->fs.Attr.u = pVmcsInfo->RealMode.AttrFS.u;
8151 }
8152 if (fWhat & CPUMCTX_EXTRN_GS)
8153 {
8154 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
8155 if (fRealOnV86Active)
8156 pCtx->gs.Attr.u = pVmcsInfo->RealMode.AttrGS.u;
8157 }
8158 VMXLOCAL_BREAK_RC(rc);
8159 }
8160
8161 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
8162 {
8163 if (fWhat & CPUMCTX_EXTRN_LDTR)
8164 rc |= hmR0VmxImportGuestLdtr(pVCpu);
8165
8166 if (fWhat & CPUMCTX_EXTRN_GDTR)
8167 {
8168 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
8169 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
8170 pCtx->gdtr.pGdt = u64Val;
8171 pCtx->gdtr.cbGdt = u32Val;
8172 }
8173
8174 /* Guest IDTR. */
8175 if (fWhat & CPUMCTX_EXTRN_IDTR)
8176 {
8177 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
8178 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
8179 pCtx->idtr.pIdt = u64Val;
8180 pCtx->idtr.cbIdt = u32Val;
8181 }
8182
8183 /* Guest TR. */
8184 if (fWhat & CPUMCTX_EXTRN_TR)
8185 {
8186 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
8187 don't need to import that one. */
8188 if (!pVmcsInfo->RealMode.fRealOnV86Active)
8189 rc |= hmR0VmxImportGuestTr(pVCpu);
8190 }
8191 VMXLOCAL_BREAK_RC(rc);
8192 }
8193
8194 if (fWhat & CPUMCTX_EXTRN_DR7)
8195 {
8196 if (!pVCpu->hm.s.fUsingHyperDR7)
8197 {
8198 /* Upper 32-bits are always zero. See Intel spec. 2.7.3 "Loading and Storing Debug Registers". */
8199 rc = VMXReadVmcs32(VMX_VMCS_GUEST_DR7, &u32Val);
8200 VMXLOCAL_BREAK_RC(rc);
8201 pCtx->dr[7] = u32Val;
8202 }
8203 }
8204
8205 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
8206 {
8207 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip);
8208 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp);
8209 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val);
8210 pCtx->SysEnter.cs = u32Val;
8211 VMXLOCAL_BREAK_RC(rc);
8212 }
8213
8214#if HC_ARCH_BITS == 64
8215 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
8216 {
8217 if ( pVM->hm.s.fAllow64BitGuests
8218 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
8219 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
8220 }
8221
8222 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
8223 {
8224 if ( pVM->hm.s.fAllow64BitGuests
8225 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
8226 {
8227 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
8228 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
8229 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
8230 }
8231 }
8232#endif
8233
8234 if ( (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
8235#if HC_ARCH_BITS == 32
8236 || (fWhat & (CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS))
8237#endif
8238 )
8239 {
8240 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
8241 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
8242 Assert(pMsrs);
8243 Assert(cMsrs <= VMX_MISC_MAX_MSRS(pVM->hm.s.vmx.Msrs.u64Misc));
8244 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
8245 for (uint32_t i = 0; i < cMsrs; i++)
8246 {
8247 uint32_t const idMsr = pMsrs[i].u32Msr;
8248 switch (idMsr)
8249 {
8250 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
8251 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
8252 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
8253#if HC_ARCH_BITS == 32
8254 case MSR_K8_LSTAR: pCtx->msrLSTAR = pMsrs[i].u64Value; break;
8255 case MSR_K6_STAR: pCtx->msrSTAR = pMsrs[i].u64Value; break;
8256 case MSR_K8_SF_MASK: pCtx->msrSFMASK = pMsrs[i].u64Value; break;
8257 case MSR_K8_KERNEL_GS_BASE: pCtx->msrKERNELGSBASE = pMsrs[i].u64Value; break;
8258#endif
8259 default:
8260 {
8261 pCtx->fExtrn = 0;
8262 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
8263 ASMSetFlags(fEFlags);
8264 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
8265 return VERR_HM_UNEXPECTED_LD_ST_MSR;
8266 }
8267 }
8268 }
8269 }
8270
8271 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
8272 {
8273 uint64_t u64Shadow;
8274 if (fWhat & CPUMCTX_EXTRN_CR0)
8275 {
8276 /** @todo r=ramshankar: We only read 32-bits here for legacy/convenience reasons,
8277 * remove when we drop 32-bit host w/ 64-bit host support, see
8278 * @bugref{9180#c39}. */
8279 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32Val);
8280#if HC_ARCH_BITS == 32
8281 uint32_t u32Shadow;
8282 rc |= VMXReadVmcs32(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u32Shadow);
8283 u64Shadow = u32Shadow;
8284#else
8285 rc |= VMXReadVmcs64(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow);
8286#endif
8287 VMXLOCAL_BREAK_RC(rc);
8288 u64Val = u32Val;
8289 u64Val = (u64Val & ~pVmcsInfo->u64Cr0Mask)
8290 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
8291#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8292 /*
8293 * Reapply the nested-guest's CR0 fixed bits that might have been altered while
8294 * exporting the nested-guest CR0 for executing using hardware-assisted VMX.
8295 */
8296 if (CPUMIsGuestInVmxNonRootMode(pCtx))
8297 {
8298 u64Val |= pCtx->hwvirt.vmx.Msrs.u64Cr0Fixed0;
8299 u64Val &= pCtx->hwvirt.vmx.Msrs.u64Cr0Fixed1;
8300 }
8301#endif
8302 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
8303 CPUMSetGuestCR0(pVCpu, u64Val);
8304 VMMRZCallRing3Enable(pVCpu);
8305 }
8306
8307 if (fWhat & CPUMCTX_EXTRN_CR4)
8308 {
8309 /** @todo r=ramshankar: We only read 32-bits here for legacy/convenience reasons,
8310 * remove when we drop 32-bit host w/ 64-bit host support, see
8311 * @bugref{9180#c39}. */
8312 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR4, &u32Val);
8313#if HC_ARCH_BITS == 32
8314 uint32_t u32Shadow;
8315 rc |= VMXReadVmcs32(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u32Shadow);
8316 u64Shadow = u32Shadow;
8317#else
8318 rc |= VMXReadVmcs64(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow);
8319#endif
8320 VMXLOCAL_BREAK_RC(rc);
8321 u64Val = u32Val;
8322 u64Val = (u64Val & ~pVmcsInfo->u64Cr4Mask)
8323 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
8324#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8325 /*
8326 * Reapply the nested-guest's CR4 fixed bits that might have been altered while
8327 * exporting the nested-guest CR4 for executing using hardware-assisted VMX.
8328 */
8329 if (CPUMIsGuestInVmxNonRootMode(pCtx))
8330 {
8331 u64Val |= pCtx->hwvirt.vmx.Msrs.u64Cr4Fixed0;
8332 u64Val &= pCtx->hwvirt.vmx.Msrs.u64Cr4Fixed1;
8333 }
8334#endif
8335 pCtx->cr4 = u64Val;
8336 }
8337
8338 if (fWhat & CPUMCTX_EXTRN_CR3)
8339 {
8340 /* CR0.PG bit changes are always intercepted, so it's up to date. */
8341 if ( pVM->hm.s.vmx.fUnrestrictedGuest
8342 || ( pVM->hm.s.fNestedPaging
8343 && CPUMIsGuestPagingEnabledEx(pCtx)))
8344 {
8345 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_CR3, &u64Val);
8346 VMXLOCAL_BREAK_RC(rc);
8347 if (pCtx->cr3 != u64Val)
8348 {
8349 pCtx->cr3 = u64Val;
8350 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
8351 }
8352
8353 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
8354 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
8355 if (CPUMIsGuestInPAEModeEx(pCtx))
8356 {
8357 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u);
8358 rc |= VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u);
8359 rc |= VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u);
8360 rc |= VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u);
8361 VMXLOCAL_BREAK_RC(rc);
8362 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
8363 }
8364 }
8365 }
8366 }
8367
8368#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8369 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
8370 {
8371 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
8372 && !CPUMIsGuestInVmxNonRootMode(pCtx))
8373 {
8374 Assert(CPUMIsGuestInVmxRootMode(pCtx));
8375 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
8376 VMXLOCAL_BREAK_RC(rc);
8377 }
8378 }
8379#endif
8380 } while (0);
8381
8382 if (RT_SUCCESS(rc))
8383 {
8384 /* Update fExtrn. */
8385 pCtx->fExtrn &= ~fWhat;
8386
8387 /* If everything has been imported, clear the HM keeper bit. */
8388 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
8389 {
8390 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
8391 Assert(!pCtx->fExtrn);
8392 }
8393 }
8394 }
8395 else
8396 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
8397
8398 ASMSetFlags(fEFlags);
8399
8400 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
8401
8402 if (RT_SUCCESS(rc))
8403 { /* likely */ }
8404 else
8405 return rc;
8406
8407 /*
8408 * Honor any pending CR3 updates.
8409 *
8410 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> hmR0VmxCallRing3Callback()
8411 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
8412 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
8413 *
8414 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
8415 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
8416 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
8417 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
8418 *
8419 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
8420 */
8421 if (VMMRZCallRing3IsEnabled(pVCpu))
8422 {
8423 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
8424 {
8425 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
8426 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
8427 }
8428
8429 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
8430 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
8431
8432 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
8433 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
8434 }
8435
8436 return VINF_SUCCESS;
8437#undef VMXLOCAL_BREAK_RC
8438}
8439
8440
8441/**
8442 * Saves the guest state from the VMCS into the guest-CPU context.
8443 *
8444 * @returns VBox status code.
8445 * @param pVCpu The cross context virtual CPU structure.
8446 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
8447 */
8448VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPU pVCpu, uint64_t fWhat)
8449{
8450 AssertPtr(pVCpu);
8451 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8452 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
8453}
8454
8455
8456/**
8457 * Check per-VM and per-VCPU force flag actions that require us to go back to
8458 * ring-3 for one reason or another.
8459 *
8460 * @returns Strict VBox status code (i.e. informational status codes too)
8461 * @retval VINF_SUCCESS if we don't have any actions that require going back to
8462 * ring-3.
8463 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
8464 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
8465 * interrupts)
8466 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
8467 * all EMTs to be in ring-3.
8468 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
8469 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
8470 * to the EM loop.
8471 *
8472 * @param pVCpu The cross context virtual CPU structure.
8473 * @param fStepping Whether we are single-stepping the guest using the
8474 * hypervisor debugger.
8475 */
8476static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPU pVCpu, bool fStepping)
8477{
8478 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8479
8480 /*
8481 * Update pending interrupts into the APIC's IRR.
8482 */
8483 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
8484 APICUpdatePendingInterrupts(pVCpu);
8485
8486 /*
8487 * Anything pending? Should be more likely than not if we're doing a good job.
8488 */
8489 PVM pVM = pVCpu->CTX_SUFF(pVM);
8490 if ( !fStepping
8491 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
8492 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
8493 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
8494 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
8495 return VINF_SUCCESS;
8496
8497 /* Pending PGM C3 sync. */
8498 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
8499 {
8500 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8501 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
8502 VBOXSTRICTRC rcStrict2 = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
8503 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
8504 if (rcStrict2 != VINF_SUCCESS)
8505 {
8506 AssertRC(VBOXSTRICTRC_VAL(rcStrict2));
8507 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict2)));
8508 return rcStrict2;
8509 }
8510 }
8511
8512 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
8513 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
8514 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
8515 {
8516 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
8517 int rc2 = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
8518 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc2));
8519 return rc2;
8520 }
8521
8522 /* Pending VM request packets, such as hardware interrupts. */
8523 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
8524 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
8525 {
8526 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
8527 Log4Func(("Pending VM request forcing us back to ring-3\n"));
8528 return VINF_EM_PENDING_REQUEST;
8529 }
8530
8531 /* Pending PGM pool flushes. */
8532 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
8533 {
8534 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
8535 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
8536 return VINF_PGM_POOL_FLUSH_PENDING;
8537 }
8538
8539 /* Pending DMA requests. */
8540 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
8541 {
8542 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
8543 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
8544 return VINF_EM_RAW_TO_R3;
8545 }
8546
8547 return VINF_SUCCESS;
8548}
8549
8550
8551/**
8552 * Converts any TRPM trap into a pending HM event. This is typically used when
8553 * entering from ring-3 (not longjmp returns).
8554 *
8555 * @param pVCpu The cross context virtual CPU structure.
8556 */
8557static void hmR0VmxTrpmTrapToPendingEvent(PVMCPU pVCpu)
8558{
8559 Assert(TRPMHasTrap(pVCpu));
8560 Assert(!pVCpu->hm.s.Event.fPending);
8561
8562 uint8_t uVector;
8563 TRPMEVENT enmTrpmEvent;
8564 RTGCUINT uErrCode;
8565 RTGCUINTPTR GCPtrFaultAddress;
8566 uint8_t cbInstr;
8567
8568 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr);
8569 AssertRC(rc);
8570
8571 uint32_t u32IntInfo;
8572 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
8573 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent);
8574
8575 rc = TRPMResetTrap(pVCpu);
8576 AssertRC(rc);
8577 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
8578 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
8579
8580 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
8581}
8582
8583
8584/**
8585 * Converts the pending HM event into a TRPM trap.
8586 *
8587 * @param pVCpu The cross context virtual CPU structure.
8588 */
8589static void hmR0VmxPendingEventToTrpmTrap(PVMCPU pVCpu)
8590{
8591 Assert(pVCpu->hm.s.Event.fPending);
8592
8593 /* If a trap was already pending, we did something wrong! */
8594 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
8595
8596 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
8597 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
8598 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
8599
8600 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
8601
8602 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
8603 AssertRC(rc);
8604
8605 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8606 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
8607
8608 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
8609 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
8610 else if (VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo) == VMX_IDT_VECTORING_INFO_TYPE_SW_INT)
8611 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
8612
8613 /* We're now done converting the pending event. */
8614 pVCpu->hm.s.Event.fPending = false;
8615}
8616
8617
8618/**
8619 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
8620 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
8621 *
8622 * @param pVCpu The cross context virtual CPU structure.
8623 * @param pVmcsInfo The VMCS info. object.
8624 */
8625static void hmR0VmxSetIntWindowExitVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
8626{
8627 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8628 {
8629 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
8630 {
8631 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
8632 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8633 AssertRC(rc);
8634 }
8635 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
8636}
8637
8638
8639/**
8640 * Clears the interrupt-window exiting control in the VMCS.
8641 *
8642 * @param pVmcsInfo The VMCS info. object.
8643 */
8644DECLINLINE(int) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8645{
8646 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8647 {
8648 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
8649 return VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8650 }
8651 return VINF_SUCCESS;
8652}
8653
8654
8655/**
8656 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
8657 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
8658 *
8659 * @param pVCpu The cross context virtual CPU structure.
8660 * @param pVmcsInfo The VMCS info. object.
8661 */
8662static void hmR0VmxSetNmiWindowExitVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
8663{
8664 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8665 {
8666 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
8667 {
8668 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8669 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8670 AssertRC(rc);
8671 Log4Func(("Setup NMI-window exiting\n"));
8672 }
8673 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
8674}
8675
8676
8677/**
8678 * Clears the NMI-window exiting control in the VMCS.
8679 *
8680 * @param pVmcsInfo The VMCS info. object.
8681 */
8682DECLINLINE(int) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8683{
8684 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8685 {
8686 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8687 return VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8688 }
8689 return VINF_SUCCESS;
8690}
8691
8692
8693/**
8694 * Does the necessary state syncing before returning to ring-3 for any reason
8695 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
8696 *
8697 * @returns VBox status code.
8698 * @param pVCpu The cross context virtual CPU structure.
8699 * @param fImportState Whether to import the guest state from the VMCS back
8700 * to the guest-CPU context.
8701 *
8702 * @remarks No-long-jmp zone!!!
8703 */
8704static int hmR0VmxLeave(PVMCPU pVCpu, bool fImportState)
8705{
8706 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8707 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8708
8709 RTCPUID const idCpu = RTMpCpuId();
8710 Log4Func(("HostCpuId=%u\n", idCpu));
8711
8712 /*
8713 * !!! IMPORTANT !!!
8714 * If you modify code here, check whether hmR0VmxCallRing3Callback() needs to be updated too.
8715 */
8716
8717 /* Save the guest state if necessary. */
8718 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8719 if (fImportState)
8720 {
8721 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8722 AssertRCReturn(rc, rc);
8723 }
8724
8725 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
8726 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8727 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
8728
8729 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
8730#ifdef VBOX_STRICT
8731 if (CPUMIsHyperDebugStateActive(pVCpu))
8732 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
8733#endif
8734 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8735 Assert(!CPUMIsGuestDebugStateActive(pVCpu) && !CPUMIsGuestDebugStateActivePending(pVCpu));
8736 Assert(!CPUMIsHyperDebugStateActive(pVCpu) && !CPUMIsHyperDebugStateActivePending(pVCpu));
8737
8738#if HC_ARCH_BITS == 64
8739 /* Restore host-state bits that VT-x only restores partially. */
8740 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8741 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8742 {
8743 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags, idCpu));
8744 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8745 }
8746 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8747#endif
8748
8749 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8750 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8751 {
8752 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
8753 if (!fImportState)
8754 {
8755 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
8756 AssertRCReturn(rc, rc);
8757 }
8758 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8759 Assert(!pVCpu->hm.s.vmx.fLazyMsrs);
8760 }
8761 else
8762 pVCpu->hm.s.vmx.fLazyMsrs = 0;
8763
8764 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8765 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8766
8767 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
8768 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
8769 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
8770 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
8771 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
8772 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
8773 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
8774 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
8775 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
8776 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8777
8778 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8779
8780 /** @todo This partially defeats the purpose of having preemption hooks.
8781 * The problem is, deregistering the hooks should be moved to a place that
8782 * lasts until the EMT is about to be destroyed not everytime while leaving HM
8783 * context.
8784 */
8785 int rc = hmR0VmxClearVmcs(pVmcsInfo);
8786 AssertRCReturn(rc, rc);
8787
8788#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8789 /*
8790 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
8791 * clear a shadow VMCS before allowing that VMCS to become active on another
8792 * logical processor. We may or may not be importing guest state which clears
8793 * it, so cover for it here.
8794 *
8795 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
8796 */
8797 if ( pVmcsInfo->pvShadowVmcs
8798 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
8799 {
8800 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
8801 AssertRCReturn(rc, rc);
8802 }
8803
8804 /*
8805 * Flag that we need to re-import the host state if we switch to this VMCS before
8806 * executing guest or nested-guest code.
8807 */
8808 pVmcsInfo->idHostCpu = NIL_RTCPUID;
8809#endif
8810
8811 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
8812 NOREF(idCpu);
8813 return VINF_SUCCESS;
8814}
8815
8816
8817/**
8818 * Leaves the VT-x session.
8819 *
8820 * @returns VBox status code.
8821 * @param pVCpu The cross context virtual CPU structure.
8822 *
8823 * @remarks No-long-jmp zone!!!
8824 */
8825static int hmR0VmxLeaveSession(PVMCPU pVCpu)
8826{
8827 HM_DISABLE_PREEMPT(pVCpu);
8828 HMVMX_ASSERT_CPU_SAFE(pVCpu);
8829 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8830 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8831
8832 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
8833 and done this from the VMXR0ThreadCtxCallback(). */
8834 if (!pVCpu->hm.s.fLeaveDone)
8835 {
8836 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
8837 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
8838 pVCpu->hm.s.fLeaveDone = true;
8839 }
8840 Assert(!pVCpu->cpum.GstCtx.fExtrn);
8841
8842 /*
8843 * !!! IMPORTANT !!!
8844 * If you modify code here, make sure to check whether hmR0VmxCallRing3Callback() needs to be updated too.
8845 */
8846
8847 /* Deregister hook now that we've left HM context before re-enabling preemption. */
8848 /** @todo Deregistering here means we need to VMCLEAR always
8849 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
8850 * for calling VMMR0ThreadCtxHookDisable here! */
8851 VMMR0ThreadCtxHookDisable(pVCpu);
8852
8853 /* Leave HM context. This takes care of local init (term). */
8854 int rc = HMR0LeaveCpu(pVCpu);
8855
8856 HM_RESTORE_PREEMPT();
8857 return rc;
8858}
8859
8860
8861/**
8862 * Does the necessary state syncing before doing a longjmp to ring-3.
8863 *
8864 * @returns VBox status code.
8865 * @param pVCpu The cross context virtual CPU structure.
8866 *
8867 * @remarks No-long-jmp zone!!!
8868 */
8869DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPU pVCpu)
8870{
8871 return hmR0VmxLeaveSession(pVCpu);
8872}
8873
8874
8875/**
8876 * Take necessary actions before going back to ring-3.
8877 *
8878 * An action requires us to go back to ring-3. This function does the necessary
8879 * steps before we can safely return to ring-3. This is not the same as longjmps
8880 * to ring-3, this is voluntary and prepares the guest so it may continue
8881 * executing outside HM (recompiler/IEM).
8882 *
8883 * @returns VBox status code.
8884 * @param pVCpu The cross context virtual CPU structure.
8885 * @param rcExit The reason for exiting to ring-3. Can be
8886 * VINF_VMM_UNKNOWN_RING3_CALL.
8887 */
8888static int hmR0VmxExitToRing3(PVMCPU pVCpu, VBOXSTRICTRC rcExit)
8889{
8890 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8891
8892 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8893 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8894 {
8895 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8896 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8897 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
8898 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8899 }
8900
8901 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8902 VMMRZCallRing3Disable(pVCpu);
8903 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8904
8905 /*
8906 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8907 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8908 *
8909 * This is because execution may continue from ring-3 and we would need to inject
8910 * the event from there (hence place it back in TRPM).
8911 */
8912 if (pVCpu->hm.s.Event.fPending)
8913 {
8914 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8915 Assert(!pVCpu->hm.s.Event.fPending);
8916
8917 /* Clear the events from the VMCS. */
8918 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0);
8919 AssertRCReturn(rc, rc);
8920 }
8921#ifdef VBOX_STRICT
8922 else
8923 {
8924 /*
8925 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8926 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8927 * occasionally, see @bugref{9180#c42}.
8928 *
8929 * However, if the VM-entry failed, any VM entry-interruption info. field would
8930 * be left unmodified as the event would not have been injected to the guest. In
8931 * such cases, don't assert, we're not going to continue guest execution anyway.
8932 */
8933 uint32_t uExitReason;
8934 uint32_t uEntryIntInfo;
8935 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8936 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8937 AssertRC(rc);
8938 Assert(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo));
8939 }
8940#endif
8941
8942 /*
8943 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8944 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8945 * (e.g. TPR below threshold).
8946 */
8947 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8948 {
8949 int rc = hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8950 rc |= hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8951 AssertRCReturn(rc, rc);
8952 }
8953
8954 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8955 and if we're injecting an event we should have a TRPM trap pending. */
8956 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8957#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8958 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8959#endif
8960
8961 /* Save guest state and restore host state bits. */
8962 int rc = hmR0VmxLeaveSession(pVCpu);
8963 AssertRCReturn(rc, rc);
8964 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8965
8966 /* Thread-context hooks are unregistered at this point!!! */
8967
8968 /* Sync recompiler state. */
8969 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8970 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8971 | CPUM_CHANGED_LDTR
8972 | CPUM_CHANGED_GDTR
8973 | CPUM_CHANGED_IDTR
8974 | CPUM_CHANGED_TR
8975 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8976 if ( pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging
8977 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8978 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8979
8980 Assert(!pVCpu->hm.s.fClearTrapFlag);
8981
8982 /* Update the exit-to-ring 3 reason. */
8983 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8984
8985 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8986 if ( rcExit != VINF_EM_RAW_INTERRUPT
8987 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8988 {
8989 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8990 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8991 }
8992
8993 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8994
8995 /* We do -not- want any longjmp notifications after this! We must return to ring-3 ASAP. */
8996 VMMRZCallRing3RemoveNotification(pVCpu);
8997 VMMRZCallRing3Enable(pVCpu);
8998
8999 return rc;
9000}
9001
9002
9003/**
9004 * VMMRZCallRing3() callback wrapper which saves the guest state before we
9005 * longjump to ring-3 and possibly get preempted.
9006 *
9007 * @returns VBox status code.
9008 * @param pVCpu The cross context virtual CPU structure.
9009 * @param enmOperation The operation causing the ring-3 longjump.
9010 * @param pvUser User argument, currently unused, NULL.
9011 */
9012static DECLCALLBACK(int) hmR0VmxCallRing3Callback(PVMCPU pVCpu, VMMCALLRING3 enmOperation, void *pvUser)
9013{
9014 RT_NOREF(pvUser);
9015 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
9016 {
9017 /*
9018 * !!! IMPORTANT !!!
9019 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
9020 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
9021 */
9022 VMMRZCallRing3RemoveNotification(pVCpu);
9023 VMMRZCallRing3Disable(pVCpu);
9024 RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
9025 RTThreadPreemptDisable(&PreemptState);
9026
9027 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
9028 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
9029 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
9030 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
9031
9032#if HC_ARCH_BITS == 64
9033 /* Restore host-state bits that VT-x only restores partially. */
9034 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
9035 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
9036 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
9037 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
9038#endif
9039
9040 /* Restore the lazy host MSRs as we're leaving VT-x context. */
9041 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
9042 hmR0VmxLazyRestoreHostMsrs(pVCpu);
9043
9044 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
9045 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
9046 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
9047
9048 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
9049 cleared as part of importing the guest state above. */
9050 hmR0VmxClearVmcs(pVmcsInfo);
9051
9052 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
9053 VMMR0ThreadCtxHookDisable(pVCpu);
9054 HMR0LeaveCpu(pVCpu);
9055 RTThreadPreemptRestore(&PreemptState);
9056 return VINF_SUCCESS;
9057 }
9058
9059 Assert(pVCpu);
9060 Assert(pvUser);
9061 Assert(VMMRZCallRing3IsEnabled(pVCpu));
9062 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9063
9064 VMMRZCallRing3Disable(pVCpu);
9065 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9066
9067 Log4Func((" -> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
9068
9069 int rc = hmR0VmxLongJmpToRing3(pVCpu);
9070 AssertRCReturn(rc, rc);
9071
9072 VMMRZCallRing3Enable(pVCpu);
9073 return VINF_SUCCESS;
9074}
9075
9076
9077/**
9078 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
9079 * stack.
9080 *
9081 * @returns Strict VBox status code (i.e. informational status codes too).
9082 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
9083 * @param pVCpu The cross context virtual CPU structure.
9084 * @param uValue The value to push to the guest stack.
9085 */
9086static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPU pVCpu, uint16_t uValue)
9087{
9088 /*
9089 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
9090 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
9091 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
9092 */
9093 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9094 if (pCtx->sp == 1)
9095 return VINF_EM_RESET;
9096 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
9097 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
9098 AssertRC(rc);
9099 return rc;
9100}
9101
9102
9103/**
9104 * Injects an event into the guest upon VM-entry by updating the relevant fields
9105 * in the VM-entry area in the VMCS.
9106 *
9107 * @returns Strict VBox status code (i.e. informational status codes too).
9108 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
9109 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
9110 *
9111 * @param pVCpu The cross context virtual CPU structure.
9112 * @param pVmxTransient The VMX-transient structure.
9113 * @param pEvent The event being injected.
9114 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
9115 * will be updated if necessary. This cannot not be NULL.
9116 * @param fStepping Whether we're single-stepping guest execution and should
9117 * return VINF_EM_DBG_STEPPED if the event is injected
9118 * directly (registers modified by us, not by hardware on
9119 * VM-entry).
9120 */
9121static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
9122 uint32_t *pfIntrState)
9123{
9124 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
9125 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
9126 Assert(pfIntrState);
9127
9128 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9129 uint32_t u32IntInfo = pEvent->u64IntInfo;
9130 uint32_t const u32ErrCode = pEvent->u32ErrCode;
9131 uint32_t const cbInstr = pEvent->cbInstr;
9132 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
9133 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
9134 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
9135
9136#ifdef VBOX_STRICT
9137 /*
9138 * Validate the error-code-valid bit for hardware exceptions.
9139 * No error codes for exceptions in real-mode.
9140 *
9141 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
9142 */
9143 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
9144 && !CPUMIsGuestInRealModeEx(pCtx))
9145 {
9146 switch (uVector)
9147 {
9148 case X86_XCPT_PF:
9149 case X86_XCPT_DF:
9150 case X86_XCPT_TS:
9151 case X86_XCPT_NP:
9152 case X86_XCPT_SS:
9153 case X86_XCPT_GP:
9154 case X86_XCPT_AC:
9155 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
9156 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
9157 RT_FALL_THRU();
9158 default:
9159 break;
9160 }
9161 }
9162
9163 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
9164 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
9165 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9166#endif
9167
9168 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
9169
9170 /*
9171 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
9172 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
9173 * interrupt handler in the (real-mode) guest.
9174 *
9175 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
9176 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
9177 */
9178 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
9179 {
9180 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest)
9181 {
9182 /*
9183 * For CPUs with unrestricted guest execution enabled and with the guest
9184 * in real-mode, we must not set the deliver-error-code bit.
9185 *
9186 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
9187 */
9188 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
9189 }
9190 else
9191 {
9192 PVM pVM = pVCpu->CTX_SUFF(pVM);
9193 Assert(PDMVmmDevHeapIsEnabled(pVM));
9194 Assert(pVM->hm.s.vmx.pRealModeTSS);
9195 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
9196
9197 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
9198 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9199 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
9200 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
9201 AssertRCReturn(rc2, rc2);
9202
9203 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
9204 size_t const cbIdtEntry = sizeof(X86IDTR16);
9205 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
9206 {
9207 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
9208 if (uVector == X86_XCPT_DF)
9209 return VINF_EM_RESET;
9210
9211 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
9212 No error codes for exceptions in real-mode. */
9213 if (uVector == X86_XCPT_GP)
9214 {
9215 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
9216 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
9217 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
9218 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
9219 HMEVENT EventXcptDf;
9220 RT_ZERO(EventXcptDf);
9221 EventXcptDf.u64IntInfo = uXcptDfInfo;
9222 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
9223 }
9224
9225 /*
9226 * If we're injecting an event with no valid IDT entry, inject a #GP.
9227 * No error codes for exceptions in real-mode.
9228 *
9229 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
9230 */
9231 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
9232 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
9233 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
9234 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
9235 HMEVENT EventXcptGp;
9236 RT_ZERO(EventXcptGp);
9237 EventXcptGp.u64IntInfo = uXcptGpInfo;
9238 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
9239 }
9240
9241 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
9242 uint16_t uGuestIp = pCtx->ip;
9243 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
9244 {
9245 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
9246 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
9247 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
9248 }
9249 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
9250 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
9251
9252 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
9253 X86IDTR16 IdtEntry;
9254 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
9255 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
9256 AssertRCReturn(rc2, rc2);
9257
9258 /* Construct the stack frame for the interrupt/exception handler. */
9259 VBOXSTRICTRC rcStrict;
9260 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
9261 if (rcStrict == VINF_SUCCESS)
9262 {
9263 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
9264 if (rcStrict == VINF_SUCCESS)
9265 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
9266 }
9267
9268 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
9269 if (rcStrict == VINF_SUCCESS)
9270 {
9271 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
9272 pCtx->rip = IdtEntry.offSel;
9273 pCtx->cs.Sel = IdtEntry.uSel;
9274 pCtx->cs.ValidSel = IdtEntry.uSel;
9275 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
9276 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
9277 && uVector == X86_XCPT_PF)
9278 pCtx->cr2 = GCPtrFault;
9279
9280 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
9281 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
9282 | HM_CHANGED_GUEST_RSP);
9283
9284 /*
9285 * If we delivered a hardware exception (other than an NMI) and if there was
9286 * block-by-STI in effect, we should clear it.
9287 */
9288 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9289 {
9290 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
9291 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
9292 Log4Func(("Clearing inhibition due to STI\n"));
9293 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
9294 }
9295
9296 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
9297 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
9298
9299 /*
9300 * The event has been truly dispatched to the guest. Mark it as no longer pending so
9301 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
9302 */
9303 pVCpu->hm.s.Event.fPending = false;
9304
9305 /*
9306 * If we eventually support nested-guest execution without unrestricted guest execution,
9307 * we should set fInterceptEvents here.
9308 */
9309 Assert(!pVmxTransient->fIsNestedGuest);
9310
9311 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
9312 if (fStepping)
9313 rcStrict = VINF_EM_DBG_STEPPED;
9314 }
9315 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
9316 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
9317 return rcStrict;
9318 }
9319 }
9320
9321 /*
9322 * Validate.
9323 */
9324 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
9325 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
9326
9327 /*
9328 * Inject the event into the VMCS.
9329 */
9330 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
9331 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
9332 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
9333 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
9334 AssertRCReturn(rc, rc);
9335
9336 /*
9337 * Update guest CR2 if this is a page-fault.
9338 */
9339 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
9340 pCtx->cr2 = GCPtrFault;
9341
9342 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
9343 return VINF_SUCCESS;
9344}
9345
9346
9347/**
9348 * Evaluates the event to be delivered to the guest and sets it as the pending
9349 * event.
9350 *
9351 * @returns Strict VBox status code (i.e. informational status codes too).
9352 * @param pVCpu The cross context virtual CPU structure.
9353 * @param pVmxTransient The VMX-transient structure.
9354 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
9355 */
9356static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
9357{
9358 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9359 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9360 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
9361
9362 /* Get the current interruptibility-state of the guest and then figure out what can be injected. */
9363 uint32_t const fIntrState = hmR0VmxGetGuestIntrState(pVCpu, pVmxTransient);
9364 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
9365 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
9366 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
9367
9368 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_RFLAGS));
9369 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
9370 Assert(!fBlockSti || pCtx->eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
9371 Assert(!TRPMHasTrap(pVCpu));
9372 Assert(pfIntrState);
9373
9374 *pfIntrState = fIntrState;
9375
9376 /*
9377 * Toggling of interrupt force-flags here is safe since we update TRPM on premature exits
9378 * to ring-3 before executing guest code, see hmR0VmxExitToRing3(). We must NOT restore these force-flags.
9379 */
9380 /** @todo SMI. SMIs take priority over NMIs. */
9381 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI)) /* NMI. NMIs take priority over regular interrupts. */
9382 {
9383 /* On some CPUs block-by-STI also blocks NMIs. See Intel spec. 26.3.1.5 "Checks On Guest Non-Register State". */
9384 if ( !pVCpu->hm.s.Event.fPending
9385 && !fBlockNmi
9386 && !fBlockSti
9387 && !fBlockMovSS)
9388 {
9389#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9390 if ( fIsNestedGuest
9391 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_NMI_EXIT))
9392 return IEMExecVmxVmexitXcptNmi(pVCpu);
9393#endif
9394 hmR0VmxSetPendingXcptNmi(pVCpu);
9395 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
9396 Log4Func(("Pending NMI\n"));
9397 }
9398 else if (!fIsNestedGuest)
9399 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
9400 }
9401 /*
9402 * Check if the guest can receive external interrupts (PIC/APIC). Once PDMGetInterrupt() returns
9403 * a valid interrupt we -must- deliver the interrupt. We can no longer re-request it from the APIC.
9404 */
9405 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
9406 && !pVCpu->hm.s.fSingleInstruction)
9407 {
9408 Assert(!DBGFIsStepping(pVCpu));
9409 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
9410 AssertRCReturn(rc, rc);
9411 bool const fBlockInt = !(pCtx->eflags.u32 & X86_EFL_IF);
9412 if ( !pVCpu->hm.s.Event.fPending
9413 && !fBlockInt
9414 && !fBlockSti
9415 && !fBlockMovSS)
9416 {
9417#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9418 if ( fIsNestedGuest
9419 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
9420 && !CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
9421 {
9422 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
9423 if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
9424 return rcStrict;
9425 }
9426#endif
9427 uint8_t u8Interrupt;
9428 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
9429 if (RT_SUCCESS(rc))
9430 {
9431#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9432 if ( fIsNestedGuest
9433 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
9434 && CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
9435 {
9436 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
9437 if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
9438 return rcStrict;
9439 }
9440#endif
9441 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
9442 Log4Func(("Pending external interrupt vector %#x\n", u8Interrupt));
9443 }
9444 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
9445 {
9446 if ( !fIsNestedGuest
9447 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
9448 hmR0VmxApicSetTprThreshold(pVCpu, pVmcsInfo, u8Interrupt >> 4);
9449 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
9450
9451 /*
9452 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
9453 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
9454 * need to re-set this force-flag here.
9455 */
9456 }
9457 else
9458 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
9459 }
9460 else if (!fIsNestedGuest)
9461 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
9462 }
9463
9464 return VINF_SUCCESS;
9465}
9466
9467
9468/**
9469 * Injects any pending events into the guest if the guest is in a state to
9470 * receive them.
9471 *
9472 * @returns Strict VBox status code (i.e. informational status codes too).
9473 * @param pVCpu The cross context virtual CPU structure.
9474 * @param pVmxTransient The VMX-transient structure.
9475 * @param fIntrState The VT-x guest-interruptibility state.
9476 * @param fStepping Whether we are single-stepping the guest using the
9477 * hypervisor debugger and should return
9478 * VINF_EM_DBG_STEPPED if the event was dispatched
9479 * directly.
9480 */
9481static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
9482{
9483 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9484 Assert(VMMRZCallRing3IsEnabled(pVCpu));
9485
9486 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
9487 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
9488
9489 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
9490 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
9491 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
9492 Assert(!TRPMHasTrap(pVCpu));
9493
9494 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
9495 if (pVCpu->hm.s.Event.fPending)
9496 {
9497 /*
9498 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
9499 * pending even while injecting an event and in this case, we want a VM-exit as soon as
9500 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
9501 *
9502 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
9503 */
9504 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
9505#ifdef VBOX_STRICT
9506 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9507 {
9508 bool const fBlockInt = !(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
9509 Assert(!fBlockInt);
9510 Assert(!fBlockSti);
9511 Assert(!fBlockMovSS);
9512 }
9513 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
9514 {
9515 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
9516 Assert(!fBlockSti);
9517 Assert(!fBlockMovSS);
9518 Assert(!fBlockNmi);
9519 }
9520#endif
9521 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
9522 uIntType));
9523
9524 /*
9525 * Inject the event and get any changes to the guest-interruptibility state.
9526 *
9527 * The guest-interruptibility state may need to be updated if we inject the event
9528 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
9529 */
9530 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
9531 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
9532
9533 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9534 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
9535 else
9536 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
9537 }
9538
9539 /*
9540 * Update the guest-interruptibility state.
9541 *
9542 * This is required for the real-on-v86 software interrupt injection case above, as well as
9543 * updates to the guest state from ring-3 or IEM/REM.
9544 */
9545 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
9546 AssertRCReturn(rc, rc);
9547
9548 /*
9549 * There's no need to clear the VM-entry interruption-information field here if we're not
9550 * injecting anything. VT-x clears the valid bit on every VM-exit.
9551 *
9552 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
9553 */
9554
9555 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
9556 NOREF(fBlockMovSS); NOREF(fBlockSti);
9557 return rcStrict;
9558}
9559
9560
9561/**
9562 * Enters the VT-x session.
9563 *
9564 * @returns VBox status code.
9565 * @param pVCpu The cross context virtual CPU structure.
9566 */
9567VMMR0DECL(int) VMXR0Enter(PVMCPU pVCpu)
9568{
9569 AssertPtr(pVCpu);
9570 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
9571 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9572
9573 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9574 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9575 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9576
9577#ifdef VBOX_STRICT
9578 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
9579 RTCCUINTREG uHostCr4 = ASMGetCR4();
9580 if (!(uHostCr4 & X86_CR4_VMXE))
9581 {
9582 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
9583 return VERR_VMX_X86_CR4_VMXE_CLEARED;
9584 }
9585#endif
9586
9587 /*
9588 * Load the appropriate VMCS as the current and active one.
9589 */
9590 PVMXVMCSINFO pVmcsInfo;
9591 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
9592 if (!fInNestedGuestMode)
9593 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
9594 else
9595 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
9596 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
9597 if (RT_SUCCESS(rc))
9598 {
9599 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
9600 pVCpu->hm.s.fLeaveDone = false;
9601 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9602
9603 /*
9604 * Do the EMT scheduled L1D flush here if needed.
9605 */
9606 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9607 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9608 else if (pVCpu->CTX_SUFF(pVM)->hm.s.fMdsClearOnSched)
9609 hmR0MdsClear();
9610 }
9611 return rc;
9612}
9613
9614
9615/**
9616 * The thread-context callback (only on platforms which support it).
9617 *
9618 * @param enmEvent The thread-context event.
9619 * @param pVCpu The cross context virtual CPU structure.
9620 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
9621 * @thread EMT(pVCpu)
9622 */
9623VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPU pVCpu, bool fGlobalInit)
9624{
9625 AssertPtr(pVCpu);
9626 RT_NOREF1(fGlobalInit);
9627
9628 switch (enmEvent)
9629 {
9630 case RTTHREADCTXEVENT_OUT:
9631 {
9632 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9633 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9634 VMCPU_ASSERT_EMT(pVCpu);
9635
9636 /* No longjmps (logger flushes, locks) in this fragile context. */
9637 VMMRZCallRing3Disable(pVCpu);
9638 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
9639
9640 /* Restore host-state (FPU, debug etc.) */
9641 if (!pVCpu->hm.s.fLeaveDone)
9642 {
9643 /*
9644 * Do -not- import the guest-state here as we might already be in the middle of importing
9645 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
9646 */
9647 hmR0VmxLeave(pVCpu, false /* fImportState */);
9648 pVCpu->hm.s.fLeaveDone = true;
9649 }
9650
9651 /* Leave HM context, takes care of local init (term). */
9652 int rc = HMR0LeaveCpu(pVCpu);
9653 AssertRC(rc);
9654
9655 /* Restore longjmp state. */
9656 VMMRZCallRing3Enable(pVCpu);
9657 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
9658 break;
9659 }
9660
9661 case RTTHREADCTXEVENT_IN:
9662 {
9663 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9664 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9665 VMCPU_ASSERT_EMT(pVCpu);
9666
9667 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
9668 VMMRZCallRing3Disable(pVCpu);
9669 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
9670
9671 /* Initialize the bare minimum state required for HM. This takes care of
9672 initializing VT-x if necessary (onlined CPUs, local init etc.) */
9673 int rc = hmR0EnterCpu(pVCpu);
9674 AssertRC(rc);
9675 Assert( (pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9676 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9677
9678 /* Load the active VMCS as the current one. */
9679 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
9680 rc = hmR0VmxLoadVmcs(pVmcsInfo);
9681 AssertRC(rc);
9682 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9683 pVCpu->hm.s.fLeaveDone = false;
9684
9685 /* Do the EMT scheduled L1D flush if needed. */
9686 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9687 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9688
9689 /* Restore longjmp state. */
9690 VMMRZCallRing3Enable(pVCpu);
9691 break;
9692 }
9693
9694 default:
9695 break;
9696 }
9697}
9698
9699
9700/**
9701 * Exports the host state into the VMCS host-state area.
9702 * Sets up the VM-exit MSR-load area.
9703 *
9704 * The CPU state will be loaded from these fields on every successful VM-exit.
9705 *
9706 * @returns VBox status code.
9707 * @param pVCpu The cross context virtual CPU structure.
9708 *
9709 * @remarks No-long-jump zone!!!
9710 */
9711static int hmR0VmxExportHostState(PVMCPU pVCpu)
9712{
9713 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9714
9715 int rc = VINF_SUCCESS;
9716 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
9717 {
9718 rc = hmR0VmxExportHostControlRegs();
9719 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9720
9721 rc = hmR0VmxExportHostSegmentRegs(pVCpu);
9722 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9723
9724 rc = hmR0VmxExportHostMsrs(pVCpu);
9725 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9726
9727 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
9728 }
9729 return rc;
9730}
9731
9732
9733/**
9734 * Saves the host state in the VMCS host-state.
9735 *
9736 * @returns VBox status code.
9737 * @param pVCpu The cross context virtual CPU structure.
9738 *
9739 * @remarks No-long-jump zone!!!
9740 */
9741VMMR0DECL(int) VMXR0ExportHostState(PVMCPU pVCpu)
9742{
9743 AssertPtr(pVCpu);
9744 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9745
9746 /*
9747 * Export the host state here while entering HM context.
9748 * When thread-context hooks are used, we might get preempted and have to re-save the host
9749 * state but most of the time we won't be, so do it here before we disable interrupts.
9750 */
9751 return hmR0VmxExportHostState(pVCpu);
9752}
9753
9754
9755/**
9756 * Exports the guest state into the VMCS guest-state area.
9757 *
9758 * The will typically be done before VM-entry when the guest-CPU state and the
9759 * VMCS state may potentially be out of sync.
9760 *
9761 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
9762 * VM-entry controls.
9763 * Sets up the appropriate VMX non-root function to execute guest code based on
9764 * the guest CPU mode.
9765 *
9766 * @returns VBox strict status code.
9767 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9768 * without unrestricted guest execution and the VMMDev is not presently
9769 * mapped (e.g. EFI32).
9770 *
9771 * @param pVCpu The cross context virtual CPU structure.
9772 * @param pVmxTransient The VMX-transient structure.
9773 *
9774 * @remarks No-long-jump zone!!!
9775 */
9776static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9777{
9778 AssertPtr(pVCpu);
9779 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9780 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9781
9782 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9783
9784 /*
9785 * Determine real-on-v86 mode.
9786 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9787 */
9788 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9789 if ( pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
9790 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9791 pVmcsInfo->RealMode. fRealOnV86Active = false;
9792 else
9793 {
9794 Assert(!pVmxTransient->fIsNestedGuest);
9795 pVmcsInfo->RealMode.fRealOnV86Active = true;
9796 }
9797
9798 /*
9799 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9800 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9801 */
9802 /** @todo r=ramshankar: Move hmR0VmxSelectVMRunHandler inside
9803 * hmR0VmxExportGuestEntryExitCtls and do it conditionally. There shouldn't
9804 * be a need to evaluate this everytime since I'm pretty sure we intercept
9805 * all guest paging mode changes. */
9806 int rc = hmR0VmxSelectVMRunHandler(pVCpu, pVmxTransient);
9807 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9808
9809 rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9810 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9811
9812 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9813 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9814
9815 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9816 if (rcStrict == VINF_SUCCESS)
9817 { /* likely */ }
9818 else
9819 {
9820 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9821 return rcStrict;
9822 }
9823
9824 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9825 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9826
9827 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9828 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9829
9830 rc = hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9831 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9832
9833 rc = hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9834 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9835
9836 rc = hmR0VmxExportGuestRip(pVCpu);
9837 rc |= hmR0VmxExportGuestRsp(pVCpu);
9838 rc |= hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9839 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9840
9841 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9842 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9843
9844 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9845 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9846 | HM_CHANGED_GUEST_CR2
9847 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9848 | HM_CHANGED_GUEST_X87
9849 | HM_CHANGED_GUEST_SSE_AVX
9850 | HM_CHANGED_GUEST_OTHER_XSAVE
9851 | HM_CHANGED_GUEST_XCRx
9852 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9853 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9854 | HM_CHANGED_GUEST_TSC_AUX
9855 | HM_CHANGED_GUEST_OTHER_MSRS
9856 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9857
9858 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9859 return rc;
9860}
9861
9862
9863/**
9864 * Exports the state shared between the host and guest into the VMCS.
9865 *
9866 * @param pVCpu The cross context virtual CPU structure.
9867 * @param pVmxTransient The VMX-transient structure.
9868 *
9869 * @remarks No-long-jump zone!!!
9870 */
9871static void hmR0VmxExportSharedState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9872{
9873 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9874 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9875
9876 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9877 {
9878 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9879 AssertRC(rc);
9880 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9881
9882 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9883 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9884 {
9885 rc = hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9886 AssertRC(rc);
9887 }
9888 }
9889
9890 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9891 {
9892 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9893 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9894 }
9895
9896 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9897 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9898}
9899
9900
9901/**
9902 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9903 *
9904 * @returns Strict VBox status code (i.e. informational status codes too).
9905 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9906 * without unrestricted guest execution and the VMMDev is not presently
9907 * mapped (e.g. EFI32).
9908 *
9909 * @param pVCpu The cross context virtual CPU structure.
9910 * @param pVmxTransient The VMX-transient structure.
9911 *
9912 * @remarks No-long-jump zone!!!
9913 */
9914static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9915{
9916 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9917 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9918 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9919
9920#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9921 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9922#endif
9923
9924 /*
9925 * For many exits it's only RIP that changes and hence try to export it first
9926 * without going through a lot of change flag checks.
9927 */
9928 VBOXSTRICTRC rcStrict;
9929 uint64_t fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9930 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
9931 if ((fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)) == HM_CHANGED_GUEST_RIP)
9932 {
9933 rcStrict = hmR0VmxExportGuestRip(pVCpu);
9934 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9935 { /* likely */}
9936 else
9937 AssertMsgFailedReturn(("Failed to export guest RIP! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)), rcStrict);
9938 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9939 }
9940 else if (fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9941 {
9942 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9943 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9944 { /* likely */}
9945 else
9946 {
9947 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9948 VBOXSTRICTRC_VAL(rcStrict)));
9949 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9950 return rcStrict;
9951 }
9952 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9953 }
9954 else
9955 rcStrict = VINF_SUCCESS;
9956
9957#ifdef VBOX_STRICT
9958 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9959 fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9960 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
9961 AssertMsg(!(fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)),
9962 ("fCtxChanged=%#RX64\n", fCtxChanged));
9963#endif
9964 return rcStrict;
9965}
9966
9967
9968/**
9969 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9970 * and update error record fields accordingly.
9971 *
9972 * @returns VMX_IGS_* error codes.
9973 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9974 * wrong with the guest state.
9975 *
9976 * @param pVCpu The cross context virtual CPU structure.
9977 * @param pVmcsInfo The VMCS info. object.
9978 *
9979 * @remarks This function assumes our cache of the VMCS controls
9980 * are valid, i.e. hmR0VmxCheckVmcsCtls() succeeded.
9981 */
9982static uint32_t hmR0VmxCheckGuestState(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
9983{
9984#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9985#define HMVMX_CHECK_BREAK(expr, err) do { \
9986 if (!(expr)) { uError = (err); break; } \
9987 } while (0)
9988
9989 int rc;
9990 PVM pVM = pVCpu->CTX_SUFF(pVM);
9991 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9992 uint32_t uError = VMX_IGS_ERROR;
9993 uint32_t u32Val;
9994 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuest;
9995
9996 do
9997 {
9998 /*
9999 * CR0.
10000 */
10001 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
10002 uint32_t fSetCr0 = (uint32_t)(pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
10003 uint32_t const fZapCr0 = (uint32_t)(pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
10004 /* Exceptions for unrestricted guest execution for fixed CR0 bits (PE, PG).
10005 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
10006 if (fUnrestrictedGuest)
10007 fSetCr0 &= ~(X86_CR0_PE | X86_CR0_PG);
10008
10009 uint32_t u32GuestCr0;
10010 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32GuestCr0);
10011 AssertRCBreak(rc);
10012 HMVMX_CHECK_BREAK((u32GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
10013 HMVMX_CHECK_BREAK(!(u32GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
10014 if ( !fUnrestrictedGuest
10015 && (u32GuestCr0 & X86_CR0_PG)
10016 && !(u32GuestCr0 & X86_CR0_PE))
10017 {
10018 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
10019 }
10020
10021 /*
10022 * CR4.
10023 */
10024 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
10025 uint64_t const fSetCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
10026 uint64_t const fZapCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
10027
10028 uint32_t u32GuestCr4;
10029 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR4, &u32GuestCr4);
10030 AssertRCBreak(rc);
10031 HMVMX_CHECK_BREAK((u32GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
10032 HMVMX_CHECK_BREAK(!(u32GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
10033
10034 /*
10035 * IA32_DEBUGCTL MSR.
10036 */
10037 uint64_t u64Val;
10038 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
10039 AssertRCBreak(rc);
10040 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
10041 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
10042 {
10043 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
10044 }
10045 uint64_t u64DebugCtlMsr = u64Val;
10046
10047#ifdef VBOX_STRICT
10048 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
10049 AssertRCBreak(rc);
10050 Assert(u32Val == pVmcsInfo->u32EntryCtls);
10051#endif
10052 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
10053
10054 /*
10055 * RIP and RFLAGS.
10056 */
10057 uint32_t u32Eflags;
10058#if HC_ARCH_BITS == 64
10059 rc = VMXReadVmcs64(VMX_VMCS_GUEST_RIP, &u64Val);
10060 AssertRCBreak(rc);
10061 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
10062 if ( !fLongModeGuest
10063 || !pCtx->cs.Attr.n.u1Long)
10064 {
10065 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
10066 }
10067 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
10068 * must be identical if the "IA-32e mode guest" VM-entry
10069 * control is 1 and CS.L is 1. No check applies if the
10070 * CPU supports 64 linear-address bits. */
10071
10072 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
10073 rc = VMXReadVmcs64(VMX_VMCS_GUEST_RFLAGS, &u64Val);
10074 AssertRCBreak(rc);
10075 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
10076 VMX_IGS_RFLAGS_RESERVED);
10077 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
10078 u32Eflags = u64Val;
10079#else
10080 rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &u32Eflags);
10081 AssertRCBreak(rc);
10082 HMVMX_CHECK_BREAK(!(u32Eflags & 0xffc08028), VMX_IGS_RFLAGS_RESERVED); /* Bit 31:22, Bit 15, 5, 3 MBZ. */
10083 HMVMX_CHECK_BREAK((u32Eflags & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
10084#endif
10085
10086 if ( fLongModeGuest
10087 || ( fUnrestrictedGuest
10088 && !(u32GuestCr0 & X86_CR0_PE)))
10089 {
10090 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
10091 }
10092
10093 uint32_t u32EntryInfo;
10094 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
10095 AssertRCBreak(rc);
10096 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
10097 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
10098
10099 /*
10100 * 64-bit checks.
10101 */
10102#if HC_ARCH_BITS == 64
10103 if (fLongModeGuest)
10104 {
10105 HMVMX_CHECK_BREAK(u32GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
10106 HMVMX_CHECK_BREAK(u32GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
10107 }
10108
10109 if ( !fLongModeGuest
10110 && (u32GuestCr4 & X86_CR4_PCIDE))
10111 {
10112 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
10113 }
10114
10115 /** @todo CR3 field must be such that bits 63:52 and bits in the range
10116 * 51:32 beyond the processor's physical-address width are 0. */
10117
10118 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
10119 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
10120 {
10121 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
10122 }
10123
10124 rc = VMXReadVmcs64(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
10125 AssertRCBreak(rc);
10126 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
10127
10128 rc = VMXReadVmcs64(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
10129 AssertRCBreak(rc);
10130 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
10131#endif
10132
10133 /*
10134 * PERF_GLOBAL MSR.
10135 */
10136 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
10137 {
10138 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
10139 AssertRCBreak(rc);
10140 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
10141 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
10142 }
10143
10144 /*
10145 * PAT MSR.
10146 */
10147 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
10148 {
10149 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
10150 AssertRCBreak(rc);
10151 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
10152 for (unsigned i = 0; i < 8; i++)
10153 {
10154 uint8_t u8Val = (u64Val & 0xff);
10155 if ( u8Val != 0 /* UC */
10156 && u8Val != 1 /* WC */
10157 && u8Val != 4 /* WT */
10158 && u8Val != 5 /* WP */
10159 && u8Val != 6 /* WB */
10160 && u8Val != 7 /* UC- */)
10161 {
10162 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
10163 }
10164 u64Val >>= 8;
10165 }
10166 }
10167
10168 /*
10169 * EFER MSR.
10170 */
10171 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
10172 {
10173 Assert(pVM->hm.s.vmx.fSupportsVmcsEfer);
10174 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
10175 AssertRCBreak(rc);
10176 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
10177 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
10178 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
10179 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
10180 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
10181 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
10182 * iemVmxVmentryCheckGuestState(). */
10183 HMVMX_CHECK_BREAK( fUnrestrictedGuest
10184 || !(u32GuestCr0 & X86_CR0_PG)
10185 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
10186 VMX_IGS_EFER_LMA_LME_MISMATCH);
10187 }
10188
10189 /*
10190 * Segment registers.
10191 */
10192 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10193 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
10194 if (!(u32Eflags & X86_EFL_VM))
10195 {
10196 /* CS */
10197 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
10198 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
10199 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
10200 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
10201 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
10202 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
10203 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
10204 /* CS cannot be loaded with NULL in protected mode. */
10205 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
10206 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
10207 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
10208 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
10209 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
10210 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
10211 else if (pVM->hm.s.vmx.fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
10212 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
10213 else
10214 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
10215
10216 /* SS */
10217 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10218 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
10219 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
10220 if ( !(pCtx->cr0 & X86_CR0_PE)
10221 || pCtx->cs.Attr.n.u4Type == 3)
10222 {
10223 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
10224 }
10225 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
10226 {
10227 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
10228 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
10229 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
10230 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
10231 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
10232 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
10233 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
10234 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
10235 }
10236
10237 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
10238 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
10239 {
10240 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
10241 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
10242 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10243 || pCtx->ds.Attr.n.u4Type > 11
10244 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
10245 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
10246 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
10247 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
10248 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
10249 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
10250 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
10251 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10252 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
10253 }
10254 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
10255 {
10256 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
10257 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
10258 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10259 || pCtx->es.Attr.n.u4Type > 11
10260 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
10261 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
10262 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
10263 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
10264 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
10265 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
10266 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
10267 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10268 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
10269 }
10270 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
10271 {
10272 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
10273 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
10274 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10275 || pCtx->fs.Attr.n.u4Type > 11
10276 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
10277 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
10278 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
10279 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
10280 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
10281 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
10282 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
10283 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10284 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
10285 }
10286 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
10287 {
10288 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
10289 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
10290 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10291 || pCtx->gs.Attr.n.u4Type > 11
10292 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
10293 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
10294 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
10295 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
10296 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
10297 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
10298 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
10299 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10300 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
10301 }
10302 /* 64-bit capable CPUs. */
10303#if HC_ARCH_BITS == 64
10304 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
10305 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
10306 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10307 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
10308 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
10309 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
10310 VMX_IGS_LONGMODE_SS_BASE_INVALID);
10311 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
10312 VMX_IGS_LONGMODE_DS_BASE_INVALID);
10313 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
10314 VMX_IGS_LONGMODE_ES_BASE_INVALID);
10315#endif
10316 }
10317 else
10318 {
10319 /* V86 mode checks. */
10320 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
10321 if (pVmcsInfo->RealMode.fRealOnV86Active)
10322 {
10323 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
10324 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
10325 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
10326 }
10327 else
10328 {
10329 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
10330 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
10331 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
10332 }
10333
10334 /* CS */
10335 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
10336 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
10337 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
10338 /* SS */
10339 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
10340 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
10341 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
10342 /* DS */
10343 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
10344 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
10345 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
10346 /* ES */
10347 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
10348 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
10349 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
10350 /* FS */
10351 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
10352 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
10353 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
10354 /* GS */
10355 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
10356 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
10357 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
10358 /* 64-bit capable CPUs. */
10359#if HC_ARCH_BITS == 64
10360 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
10361 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
10362 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10363 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
10364 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
10365 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
10366 VMX_IGS_LONGMODE_SS_BASE_INVALID);
10367 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
10368 VMX_IGS_LONGMODE_DS_BASE_INVALID);
10369 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
10370 VMX_IGS_LONGMODE_ES_BASE_INVALID);
10371#endif
10372 }
10373
10374 /*
10375 * TR.
10376 */
10377 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
10378 /* 64-bit capable CPUs. */
10379#if HC_ARCH_BITS == 64
10380 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
10381#endif
10382 if (fLongModeGuest)
10383 {
10384 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
10385 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
10386 }
10387 else
10388 {
10389 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
10390 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
10391 VMX_IGS_TR_ATTR_TYPE_INVALID);
10392 }
10393 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
10394 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
10395 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
10396 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
10397 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10398 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
10399 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10400 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
10401
10402 /*
10403 * GDTR and IDTR.
10404 */
10405#if HC_ARCH_BITS == 64
10406 rc = VMXReadVmcs64(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
10407 AssertRCBreak(rc);
10408 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
10409
10410 rc = VMXReadVmcs64(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
10411 AssertRCBreak(rc);
10412 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
10413#endif
10414
10415 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
10416 AssertRCBreak(rc);
10417 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10418
10419 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
10420 AssertRCBreak(rc);
10421 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10422
10423 /*
10424 * Guest Non-Register State.
10425 */
10426 /* Activity State. */
10427 uint32_t u32ActivityState;
10428 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
10429 AssertRCBreak(rc);
10430 HMVMX_CHECK_BREAK( !u32ActivityState
10431 || (u32ActivityState & RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
10432 VMX_IGS_ACTIVITY_STATE_INVALID);
10433 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
10434 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
10435 uint32_t u32IntrState;
10436 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
10437 AssertRCBreak(rc);
10438 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
10439 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10440 {
10441 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
10442 }
10443
10444 /** @todo Activity state and injecting interrupts. Left as a todo since we
10445 * currently don't use activity states but ACTIVE. */
10446
10447 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10448 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
10449
10450 /* Guest interruptibility-state. */
10451 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
10452 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
10453 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10454 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
10455 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
10456 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10457 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
10458 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
10459 {
10460 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10461 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10462 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
10463 }
10464 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10465 {
10466 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10467 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
10468 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10469 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
10470 }
10471 /** @todo Assumes the processor is not in SMM. */
10472 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10473 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
10474 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10475 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10476 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
10477 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
10478 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10479 {
10480 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI),
10481 VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
10482 }
10483
10484 /* Pending debug exceptions. */
10485#if HC_ARCH_BITS == 64
10486 rc = VMXReadVmcs64(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
10487 AssertRCBreak(rc);
10488 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
10489 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
10490 u32Val = u64Val; /* For pending debug exceptions checks below. */
10491#else
10492 rc = VMXReadVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u32Val);
10493 AssertRCBreak(rc);
10494 /* Bits 31:15, Bit 13, Bits 11:4 MBZ. */
10495 HMVMX_CHECK_BREAK(!(u32Val & 0xffffaff0), VMX_IGS_PENDING_DEBUG_RESERVED);
10496#endif
10497
10498 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10499 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
10500 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
10501 {
10502 if ( (u32Eflags & X86_EFL_TF)
10503 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10504 {
10505 /* Bit 14 is PendingDebug.BS. */
10506 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
10507 }
10508 if ( !(u32Eflags & X86_EFL_TF)
10509 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10510 {
10511 /* Bit 14 is PendingDebug.BS. */
10512 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
10513 }
10514 }
10515
10516 /* VMCS link pointer. */
10517 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
10518 AssertRCBreak(rc);
10519 if (u64Val != UINT64_C(0xffffffffffffffff))
10520 {
10521 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
10522 /** @todo Bits beyond the processor's physical-address width MBZ. */
10523 /** @todo SMM checks. */
10524 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
10525 Assert(pVmcsInfo->pvShadowVmcs);
10526 VMXVMCSREVID VmcsRevId;
10527 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
10528 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID),
10529 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
10530 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
10531 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
10532 }
10533
10534 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
10535 * not using nested paging? */
10536 if ( pVM->hm.s.fNestedPaging
10537 && !fLongModeGuest
10538 && CPUMIsGuestInPAEModeEx(pCtx))
10539 {
10540 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
10541 AssertRCBreak(rc);
10542 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10543
10544 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
10545 AssertRCBreak(rc);
10546 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10547
10548 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
10549 AssertRCBreak(rc);
10550 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10551
10552 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
10553 AssertRCBreak(rc);
10554 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10555 }
10556
10557 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
10558 if (uError == VMX_IGS_ERROR)
10559 uError = VMX_IGS_REASON_NOT_FOUND;
10560 } while (0);
10561
10562 pVCpu->hm.s.u32HMError = uError;
10563 return uError;
10564
10565#undef HMVMX_ERROR_BREAK
10566#undef HMVMX_CHECK_BREAK
10567}
10568
10569
10570/**
10571 * Map the APIC-access page for virtualizing APIC accesses.
10572 *
10573 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
10574 * this not done as part of exporting guest state, see @bugref{8721}.
10575 *
10576 * @returns VBox status code.
10577 * @param pVCpu The cross context virtual CPU structure.
10578 */
10579static int hmR0VmxMapHCApicAccessPage(PVMCPU pVCpu)
10580{
10581 PVM pVM = pVCpu->CTX_SUFF(pVM);
10582 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
10583
10584 Assert(PDMHasApic(pVM));
10585 Assert(u64MsrApicBase);
10586
10587 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
10588 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
10589
10590 /* Unalias the existing mapping. */
10591 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
10592 AssertRCReturn(rc, rc);
10593
10594 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
10595 Assert(pVM->hm.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
10596 rc = IOMMMIOMapMMIOHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hm.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
10597 AssertRCReturn(rc, rc);
10598
10599 /* Update the per-VCPU cache of the APIC base MSR. */
10600 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
10601 return VINF_SUCCESS;
10602}
10603
10604
10605/**
10606 * Worker function passed to RTMpOnSpecific() that is to be called on the target
10607 * CPU.
10608 *
10609 * @param idCpu The ID for the CPU the function is called on.
10610 * @param pvUser1 Null, not used.
10611 * @param pvUser2 Null, not used.
10612 */
10613static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
10614{
10615 RT_NOREF3(idCpu, pvUser1, pvUser2);
10616 VMXDispatchHostNmi();
10617}
10618
10619
10620/**
10621 * Dispatching an NMI on the host CPU that received it.
10622 *
10623 * @returns VBox status code.
10624 * @param pVCpu The cross context virtual CPU structure.
10625 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
10626 * executing when receiving the host NMI in VMX non-root
10627 * operation.
10628 */
10629static int hmR0VmxExitHostNmi(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
10630{
10631 RTCPUID const idCpu = pVmcsInfo->idHostCpu;
10632
10633 /*
10634 * We don't want to delay dispatching the NMI any more than we have to. However,
10635 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
10636 * after executing guest or nested-guest code for the following reasons:
10637 *
10638 * - We would need to perform VMREADs with interrupts disabled and is orders of
10639 * magnitude worse when we run as a guest hypervisor without VMCS shadowing
10640 * supported by the host hypervisor.
10641 *
10642 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
10643 * longer period of time just for handling an edge case like host NMIs which do
10644 * not occur nearly as frequently as other VM-exits.
10645 *
10646 * Let's cover the most likely scenario first. Check if we are on the target CPU
10647 * and dispatch the NMI right away. This should be much faster than calling into
10648 * RTMpOnSpecific() machinery.
10649 */
10650 bool fDispatched = false;
10651 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
10652 if (idCpu == RTMpCpuId())
10653 {
10654 VMXDispatchHostNmi();
10655 fDispatched = true;
10656 }
10657 ASMSetFlags(fEFlags);
10658 if (fDispatched)
10659 {
10660 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
10661 return VINF_SUCCESS;
10662 }
10663
10664 /*
10665 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
10666 * there should be no race or recursion even if we are unlucky enough to be preempted
10667 * (to the target CPU) without dispatching the host NMI above.
10668 */
10669 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
10670 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
10671}
10672
10673
10674#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10675/**
10676 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
10677 * nested-guest using hardware-assisted VMX.
10678 *
10679 * @param pVCpu The cross context virtual CPU structure.
10680 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
10681 * @param pVmcsInfoGst The guest VMCS info. object.
10682 */
10683static void hmR0VmxMergeMsrBitmapNested(PCVMCPU pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
10684{
10685 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
10686 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
10687 Assert(pu64MsrBitmap);
10688
10689 /*
10690 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
10691 * MSR that is intercepted by the guest is also intercepted while executing the
10692 * nested-guest using hardware-assisted VMX.
10693 *
10694 * Note! If the nested-guest is not using an MSR bitmap, ever MSR must cause a
10695 * nested-guest VM-exit even if the outer guest is not intercepting some
10696 * MSRs. We cannot assume the caller has initialized the nested-guest
10697 * MSR bitmap in this case.
10698 *
10699 * The guest hypervisor may also switch whether it uses MSR bitmaps for
10700 * each VM-entry, hence initializing it once per-VM while setting up the
10701 * nested-guest VMCS is not sufficient.
10702 */
10703 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10704 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10705 {
10706 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
10707 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
10708 Assert(pu64MsrBitmapNstGst);
10709 Assert(pu64MsrBitmapGst);
10710
10711 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
10712 for (uint32_t i = 0; i < cFrags; i++)
10713 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
10714 }
10715 else
10716 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
10717}
10718
10719
10720/**
10721 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
10722 * hardware-assisted VMX execution of the nested-guest.
10723 *
10724 * For a guest, we don't modify these controls once we set up the VMCS and hence
10725 * this function is never called.
10726 *
10727 * For nested-guests since the guest hypervisor provides these controls on every
10728 * nested-guest VM-entry and could potentially change them everytime we need to
10729 * merge them before every nested-guest VM-entry.
10730 *
10731 * @returns VBox status code.
10732 * @param pVCpu The cross context virtual CPU structure.
10733 */
10734static int hmR0VmxMergeVmcsNested(PVMCPU pVCpu)
10735{
10736 PVM pVM = pVCpu->CTX_SUFF(pVM);
10737 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
10738 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10739 Assert(pVmcsNstGst);
10740
10741 /*
10742 * Merge the controls with the requirements of the guest VMCS.
10743 *
10744 * We do not need to validate the nested-guest VMX features specified in the nested-guest
10745 * VMCS with the features supported by the physical CPU as it's already done by the
10746 * VMLAUNCH/VMRESUME instruction emulation.
10747 *
10748 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
10749 * derived from the VMX features supported by the physical CPU.
10750 */
10751
10752 /* Pin-based VM-execution controls. */
10753 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
10754
10755 /* Processor-based VM-execution controls. */
10756 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
10757 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
10758 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
10759 | VMX_PROC_CTLS_USE_TPR_SHADOW
10760 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
10761
10762 /* Secondary processor-based VM-execution controls. */
10763 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
10764 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
10765 | VMX_PROC_CTLS2_INVPCID
10766 | VMX_PROC_CTLS2_VMCS_SHADOWING
10767 | VMX_PROC_CTLS2_RDTSCP
10768 | VMX_PROC_CTLS2_XSAVES_XRSTORS
10769 | VMX_PROC_CTLS2_APIC_REG_VIRT
10770 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
10771 | VMX_PROC_CTLS2_VMFUNC));
10772
10773 /*
10774 * VM-entry controls:
10775 * These controls contains state that depends on the nested-guest state (primarily
10776 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
10777 * VM-exit. Although the guest hypervisor cannot change it, we need to in order to
10778 * properly continue executing the nested-guest if the EFER MSR changes but does not
10779 * cause a nested-guest VM-exits.
10780 *
10781 * VM-exit controls:
10782 * These controls specify the host state on return. We cannot use the controls from
10783 * the guest hypervisor state as is as it would contain the guest state rather than
10784 * the host state. Since the host state is subject to change (e.g. preemption, trips
10785 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
10786 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
10787 *
10788 * VM-entry MSR-load:
10789 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
10790 * context by the VMLAUNCH/VMRESUME instruction emulation.
10791 *
10792 * VM-exit MSR-store:
10793 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
10794 * back into the VM-exit MSR-store area.
10795 *
10796 * VM-exit MSR-load areas:
10797 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
10798 * can entirely ignore what the guest hypervisor wants to load here.
10799 */
10800
10801 /*
10802 * Exception bitmap.
10803 *
10804 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
10805 * here (and avoid doing anything while exporting nested-guest state), but to keep the
10806 * code more flexible if intercepting exceptions become more dynamic in the future we do
10807 * it as part of exporting the nested-guest state.
10808 */
10809 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
10810
10811 /*
10812 * CR0/CR4 guest/host mask.
10813 *
10814 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
10815 * cause VM-exits, so we need to merge them here.
10816 */
10817 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
10818 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
10819
10820 /*
10821 * Page-fault error-code mask and match.
10822 *
10823 * Although we require unrestricted guest execution (and thereby nested-paging) for
10824 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
10825 * normally intercept #PFs, it might intercept them for debugging purposes.
10826 *
10827 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
10828 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
10829 */
10830 uint32_t u32XcptPFMask;
10831 uint32_t u32XcptPFMatch;
10832 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
10833 {
10834 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
10835 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
10836 }
10837 else
10838 {
10839 u32XcptPFMask = 0;
10840 u32XcptPFMatch = 0;
10841 }
10842
10843 /*
10844 * Pause-Loop exiting.
10845 */
10846 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10847 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10848
10849 /*
10850 * I/O Bitmap.
10851 *
10852 * We do not use the I/O bitmap that may be provided by the guest hypervisor as we always
10853 * intercept all I/O port accesses.
10854 */
10855 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10856
10857 /*
10858 * VMCS shadowing.
10859 *
10860 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10861 * enabled while executing the nested-guest.
10862 */
10863 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10864
10865 /*
10866 * APIC-access page.
10867 *
10868 * The APIC-access page address has already been initialized while setting up the
10869 * nested-guest VMCS. In theory, even if the guest-physical address is invalid, it should
10870 * not be of any consequence to the host or to the guest for that matter, but we only
10871 * accept valid addresses verified by the VMLAUNCH/VMRESUME instruction emulation to keep
10872 * it simple.
10873 */
10874
10875 /*
10876 * Virtual-APIC page and TPR threshold.
10877 *
10878 * The virtual-APIC page has already been allocated (by CPUM during VM startup) and cached
10879 * from guest memory as part of VMLAUNCH/VMRESUME instruction emulation. The host physical
10880 * address has also been updated in the nested-guest VMCS object during allocation.
10881 */
10882 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
10883 RTHCPHYS HCPhysVirtApic;
10884 uint32_t u32TprThreshold;
10885 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10886 {
10887 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW);
10888 HCPhysVirtApic = pVmcsInfoNstGst->HCPhysVirtApic;
10889 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10890 }
10891 else
10892 {
10893 HCPhysVirtApic = 0;
10894 u32TprThreshold = 0;
10895
10896 /*
10897 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10898 * used by the guest hypervisor. Preventing MMIO accesses to the physical APIC will
10899 * be taken care of by EPT/shadow paging.
10900 */
10901 if (pVM->hm.s.fAllow64BitGuests)
10902 {
10903 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10904 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10905 }
10906 }
10907
10908 /*
10909 * Validate basic assumptions.
10910 */
10911 Assert(pVM->hm.s.vmx.fAllowUnrestricted);
10912 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10913 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10914
10915 /*
10916 * Commit it to the nested-guest VMCS.
10917 */
10918 int rc = VINF_SUCCESS;
10919 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10920 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10921 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10922 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10923 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10924 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10925 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10926 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10927 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10928 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10929 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10930 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10931 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10932 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10933 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10934 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10935 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10936 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10937 {
10938 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10939 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10940 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10941 }
10942 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10943 {
10944 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10945 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, pVmcsInfoNstGst->HCPhysVirtApic);
10946 }
10947 AssertRCReturn(rc, rc);
10948
10949 /*
10950 * Update the nested-guest VMCS cache.
10951 */
10952 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10953 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10954 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10955 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10956 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10957 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10958 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10959 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10960 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10961
10962 /*
10963 * MSR bitmap.
10964 *
10965 * The MSR bitmap address has already been initialized while setting up the nested-guest
10966 * VMCS, here we need to merge the MSR bitmaps.
10967 */
10968 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10969 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10970
10971 return VINF_SUCCESS;
10972}
10973#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10974
10975
10976/**
10977 * Does the preparations before executing guest code in VT-x.
10978 *
10979 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10980 * recompiler/IEM. We must be cautious what we do here regarding committing
10981 * guest-state information into the VMCS assuming we assuredly execute the
10982 * guest in VT-x mode.
10983 *
10984 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10985 * the common-state (TRPM/forceflags), we must undo those changes so that the
10986 * recompiler/IEM can (and should) use them when it resumes guest execution.
10987 * Otherwise such operations must be done when we can no longer exit to ring-3.
10988 *
10989 * @returns Strict VBox status code (i.e. informational status codes too).
10990 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10991 * have been disabled.
10992 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10993 * pending events).
10994 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10995 * double-fault into the guest.
10996 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10997 * dispatched directly.
10998 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10999 *
11000 * @param pVCpu The cross context virtual CPU structure.
11001 * @param pVmxTransient The VMX-transient structure.
11002 * @param fStepping Whether we are single-stepping the guest in the
11003 * hypervisor debugger. Makes us ignore some of the reasons
11004 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
11005 * if event dispatching took place.
11006 */
11007static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
11008{
11009 Assert(VMMRZCallRing3IsEnabled(pVCpu));
11010
11011#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
11012 if (pVmxTransient->fIsNestedGuest)
11013 {
11014 RT_NOREF2(pVCpu, fStepping);
11015 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
11016 return VINF_EM_RESCHEDULE_REM;
11017 }
11018#endif
11019
11020#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
11021 PGMRZDynMapFlushAutoSet(pVCpu);
11022#endif
11023
11024 /*
11025 * Check and process force flag actions, some of which might require us to go back to ring-3.
11026 */
11027 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, fStepping);
11028 if (rcStrict == VINF_SUCCESS)
11029 { /* FFs don't get set all the time. */ }
11030 else
11031 return rcStrict;
11032
11033 /*
11034 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
11035 */
11036 /** @todo Doing this from ring-3 after VM setup phase causes a
11037 * VERR_IOM_MMIO_RANGE_NOT_FOUND guru while booting Visa 64 SMP VM. No
11038 * idea why atm. */
11039 PVM pVM = pVCpu->CTX_SUFF(pVM);
11040 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
11041 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
11042 && PDMHasApic(pVM))
11043 {
11044 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
11045 AssertRCReturn(rc, rc);
11046 }
11047
11048#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11049 /*
11050 * Merge guest VMCS controls with the nested-guest VMCS controls.
11051 *
11052 * Even if we have not executed the guest prior to this (e.g. when resuming from a
11053 * saved state), we should be okay with merging controls as we initialize the
11054 * guest VMCS controls as part of VM setup phase.
11055 */
11056 if ( pVmxTransient->fIsNestedGuest
11057 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
11058 {
11059 int rc = hmR0VmxMergeVmcsNested(pVCpu);
11060 AssertRCReturn(rc, rc);
11061 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
11062 }
11063#endif
11064
11065 /*
11066 * Evaluate events to be injected into the guest.
11067 *
11068 * Events in TRPM can be injected without inspecting the guest state.
11069 * If any new events (interrupts/NMI) are pending currently, we try to set up the
11070 * guest to cause a VM-exit the next time they are ready to receive the event.
11071 *
11072 * With nested-guests, evaluating pending events may cause VM-exits.
11073 */
11074 if (TRPMHasTrap(pVCpu))
11075 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
11076
11077 uint32_t fIntrState;
11078 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
11079
11080#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11081 /*
11082 * While evaluating pending events if something failed (unlikely) or if we were
11083 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
11084 */
11085 if (rcStrict != VINF_SUCCESS)
11086 return rcStrict;
11087 if ( pVmxTransient->fIsNestedGuest
11088 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11089 {
11090 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11091 return VINF_VMX_VMEXIT;
11092 }
11093#else
11094 Assert(rcStrict == VINF_SUCCESS);
11095#endif
11096
11097 /*
11098 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
11099 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
11100 * also result in triple-faulting the VM.
11101 *
11102 * With nested-guests, the above does not apply since unrestricted guest execution is a
11103 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
11104 */
11105 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
11106 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
11107 { /* likely */ }
11108 else
11109 {
11110 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
11111 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
11112 return rcStrict;
11113 }
11114
11115 /*
11116 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
11117 * import CR3 themselves. We will need to update them here, as even as late as the above
11118 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
11119 * the below force flags to be set.
11120 */
11121 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
11122 {
11123 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
11124 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
11125 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
11126 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
11127 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11128 }
11129 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
11130 {
11131 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
11132 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11133 }
11134
11135#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11136 /* Paranoia. */
11137 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11138#endif
11139
11140 /*
11141 * No longjmps to ring-3 from this point on!!!
11142 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
11143 * This also disables flushing of the R0-logger instance (if any).
11144 */
11145 VMMRZCallRing3Disable(pVCpu);
11146
11147 /*
11148 * Export the guest state bits.
11149 *
11150 * We cannot perform longjmps while loading the guest state because we do not preserve the
11151 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
11152 * CPU migration.
11153 *
11154 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
11155 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
11156 */
11157 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
11158 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
11159 { /* likely */ }
11160 else
11161 {
11162 VMMRZCallRing3Enable(pVCpu);
11163 return rcStrict;
11164 }
11165
11166 /*
11167 * We disable interrupts so that we don't miss any interrupts that would flag preemption
11168 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
11169 * preemption disabled for a while. Since this is purely to aid the
11170 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
11171 * disable interrupt on NT.
11172 *
11173 * We need to check for force-flags that could've possible been altered since we last
11174 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
11175 * see @bugref{6398}).
11176 *
11177 * We also check a couple of other force-flags as a last opportunity to get the EMT back
11178 * to ring-3 before executing guest code.
11179 */
11180 pVmxTransient->fEFlags = ASMIntDisableFlags();
11181
11182 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
11183 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
11184 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
11185 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
11186 {
11187 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
11188 {
11189#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11190 /*
11191 * If we are executing a nested-guest make sure that we should intercept subsequent
11192 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
11193 * the VM-exit instruction emulation happy.
11194 */
11195 if (pVmxTransient->fIsNestedGuest)
11196 pVCpu->cpum.GstCtx.hwvirt.vmx.fInterceptEvents = true;
11197#endif
11198
11199 /*
11200 * We've injected any pending events. This is really the point of no return (to ring-3).
11201 *
11202 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
11203 * returns from this function, so do -not- enable them here.
11204 */
11205 pVCpu->hm.s.Event.fPending = false;
11206 return VINF_SUCCESS;
11207 }
11208
11209 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
11210 rcStrict = VINF_EM_RAW_INTERRUPT;
11211 }
11212 else
11213 {
11214 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
11215 rcStrict = VINF_EM_RAW_TO_R3;
11216 }
11217
11218 ASMSetFlags(pVmxTransient->fEFlags);
11219 VMMRZCallRing3Enable(pVCpu);
11220
11221 return rcStrict;
11222}
11223
11224
11225/**
11226 * Final preparations before executing guest code using hardware-assisted VMX.
11227 *
11228 * We can no longer get preempted to a different host CPU and there are no returns
11229 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
11230 * failures), this function is not intended to fail sans unrecoverable hardware
11231 * errors.
11232 *
11233 * @param pVCpu The cross context virtual CPU structure.
11234 * @param pVmxTransient The VMX-transient structure.
11235 *
11236 * @remarks Called with preemption disabled.
11237 * @remarks No-long-jump zone!!!
11238 */
11239static void hmR0VmxPreRunGuestCommitted(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
11240{
11241 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11242 Assert(VMMR0IsLogFlushDisabled(pVCpu));
11243 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
11244 Assert(!pVCpu->hm.s.Event.fPending);
11245
11246 /*
11247 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
11248 */
11249 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11250 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
11251
11252 PVM pVM = pVCpu->CTX_SUFF(pVM);
11253 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11254 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
11255 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
11256
11257 if (!CPUMIsGuestFPUStateActive(pVCpu))
11258 {
11259 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
11260 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
11261 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
11262 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
11263 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
11264 }
11265
11266 /*
11267 * Re-export the host state bits as we may've been preempted (only happens when
11268 * thread-context hooks are used or when the VM start function changes) or if
11269 * the host CR0 is modified while loading the guest FPU state above.
11270 *
11271 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
11272 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
11273 * see @bugref{8432}.
11274 *
11275 * This may also happen when switching to/from a nested-guest VMCS without leaving
11276 * ring-0.
11277 */
11278 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
11279 {
11280 hmR0VmxExportHostState(pVCpu);
11281 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
11282 }
11283 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
11284
11285 /*
11286 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
11287 */
11288 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
11289 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
11290 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
11291
11292 /*
11293 * Store status of the shared guest/host debug state at the time of VM-entry.
11294 */
11295#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
11296 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
11297 {
11298 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActivePending(pVCpu);
11299 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActivePending(pVCpu);
11300 }
11301 else
11302#endif
11303 {
11304 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
11305 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
11306 }
11307
11308 /*
11309 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
11310 * more than one conditional check. The post-run side of our code shall determine
11311 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
11312 */
11313 if (pVmcsInfo->pbVirtApic)
11314 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
11315
11316 /*
11317 * Update the host MSRs values in the VM-exit MSR-load area.
11318 */
11319 if (!pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs)
11320 {
11321 if (pVmcsInfo->cExitMsrLoad > 0)
11322 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
11323 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = true;
11324 }
11325
11326 /*
11327 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
11328 * VMX-preemption timer based on the next virtual sync clock deadline.
11329 */
11330 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
11331 || idCurrentCpu != pVCpu->hm.s.idLastCpu)
11332 {
11333 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
11334 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
11335 }
11336
11337 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
11338 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
11339 if (!fIsRdtscIntercepted)
11340 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
11341 else
11342 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
11343
11344 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
11345 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
11346 Assert(idCurrentCpu == pVCpu->hm.s.idLastCpu);
11347 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Update the error reporting info. with the current host CPU. */
11348 pVmcsInfo->idHostCpu = idCurrentCpu; /* Update the CPU for which we updated host-state in this VMCS. */
11349
11350 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
11351
11352 TMNotifyStartOfExecution(pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
11353 as we're about to start executing the guest . */
11354
11355 /*
11356 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
11357 *
11358 * This is done this late as updating the TSC offsetting/preemption timer above
11359 * figures out if we can skip intercepting RDTSCP by calculating the number of
11360 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
11361 */
11362 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
11363 && !fIsRdtscIntercepted)
11364 {
11365 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
11366
11367 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
11368 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
11369 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
11370 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
11371 AssertRC(rc);
11372 Assert(!pVmxTransient->fRemoveTscAuxMsr);
11373 pVmxTransient->fRemoveTscAuxMsr = true;
11374 }
11375
11376#ifdef VBOX_STRICT
11377 Assert(pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs);
11378 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
11379 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo);
11380 AssertRC(hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
11381#endif
11382
11383#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
11384 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
11385 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
11386 * see @bugref{9180#c54}. */
11387 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
11388 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
11389 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
11390#endif
11391}
11392
11393
11394/**
11395 * First C routine invoked after running guest code using hardware-assisted VMX.
11396 *
11397 * @param pVCpu The cross context virtual CPU structure.
11398 * @param pVmxTransient The VMX-transient structure.
11399 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
11400 *
11401 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
11402 *
11403 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
11404 * unconditionally when it is safe to do so.
11405 */
11406static void hmR0VmxPostRunGuest(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
11407{
11408 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
11409
11410 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
11411 ASMAtomicIncU32(&pVCpu->hm.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
11412 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
11413 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
11414 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
11415 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
11416
11417 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11418 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
11419 {
11420 uint64_t uGstTsc;
11421 if (!pVmxTransient->fIsNestedGuest)
11422 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11423 else
11424 {
11425 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11426 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
11427 }
11428 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
11429 }
11430
11431 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
11432 TMNotifyEndOfExecution(pVCpu); /* Notify TM that the guest is no longer running. */
11433 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11434
11435#if HC_ARCH_BITS == 64
11436 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
11437#endif
11438#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
11439 /* The 64-on-32 switcher maintains VMCS-launch state on its own
11440 and we need to leave it alone here. */
11441 if (pVmcsInfo->pfnStartVM != VMXR0SwitcherStartVM64)
11442 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11443#else
11444 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11445#endif
11446#ifdef VBOX_STRICT
11447 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
11448#endif
11449 Assert(!ASMIntAreEnabled());
11450 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
11451 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11452
11453#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
11454 /*
11455 * Clean all the VMCS fields in the transient structure before reading
11456 * anything from the VMCS.
11457 */
11458 pVmxTransient->uExitReason = 0;
11459 pVmxTransient->uExitIntErrorCode = 0;
11460 pVmxTransient->uExitQual = 0;
11461 pVmxTransient->uGuestLinearAddr = 0;
11462 pVmxTransient->uExitIntInfo = 0;
11463 pVmxTransient->cbInstr = 0;
11464 pVmxTransient->ExitInstrInfo.u = 0;
11465 pVmxTransient->uEntryIntInfo = 0;
11466 pVmxTransient->uEntryXcptErrorCode = 0;
11467 pVmxTransient->cbEntryInstr = 0;
11468 pVmxTransient->uIdtVectoringInfo = 0;
11469 pVmxTransient->uIdtVectoringErrorCode = 0;
11470#endif
11471
11472 /*
11473 * Save the basic VM-exit reason and check if the VM-entry failed.
11474 * See Intel spec. 24.9.1 "Basic VM-exit Information".
11475 */
11476 uint32_t uExitReason;
11477 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
11478 AssertRC(rc);
11479 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
11480 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
11481
11482 /*
11483 * Log the VM-exit before logging anything else as otherwise it might be a
11484 * tad confusing what happens before and after the world-switch.
11485 */
11486 HMVMX_LOG_EXIT(pVCpu, uExitReason);
11487
11488 /*
11489 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
11490 * bitmap permissions, if it was added before VM-entry.
11491 */
11492 if (pVmxTransient->fRemoveTscAuxMsr)
11493 {
11494 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
11495 pVmxTransient->fRemoveTscAuxMsr = false;
11496 }
11497
11498 /*
11499 * Check if VMLAUNCH/VMRESUME succeeded.
11500 * If this failed, we cause a guru meditation and cease further execution.
11501 *
11502 * However, if we are executing a nested-guest we might fail if we use the
11503 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
11504 */
11505 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
11506 {
11507 /*
11508 * Update the VM-exit history array here even if the VM-entry failed due to:
11509 * - Invalid guest state.
11510 * - MSR loading.
11511 * - Machine-check event.
11512 *
11513 * In any of the above cases we will still have a "valid" VM-exit reason
11514 * despite @a fVMEntryFailed being false.
11515 *
11516 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
11517 *
11518 * Note! We don't have CS or RIP at this point. Will probably address that later
11519 * by amending the history entry added here.
11520 */
11521 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
11522 UINT64_MAX, uHostTsc);
11523
11524 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
11525 {
11526 VMMRZCallRing3Enable(pVCpu);
11527
11528 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11529 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11530
11531#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
11532 rc = hmR0VmxReadAllRoFieldsVmcs(pVCpu, pVmxTransient);
11533 AssertRC(rc);
11534#endif
11535#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
11536 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11537 AssertRC(rc);
11538#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
11539 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_RFLAGS);
11540 AssertRC(rc);
11541#else
11542 /*
11543 * Import the guest-interruptibility state always as we need it while evaluating
11544 * injecting events on re-entry.
11545 *
11546 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
11547 * checking for real-mode while exporting the state because all bits that cause
11548 * mode changes wrt CR0 are intercepted.
11549 */
11550 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_HM_VMX_INT_STATE);
11551 AssertRC(rc);
11552#endif
11553
11554 /*
11555 * Sync the TPR shadow with our APIC state.
11556 *
11557 * With nested-guests, mark the virtual-APIC page as dirty so it can be synced
11558 * when performing the nested-guest VM-exit.
11559 */
11560 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
11561 {
11562 if (!pVmxTransient->fIsNestedGuest)
11563 {
11564 Assert(pVmcsInfo->pbVirtApic);
11565 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
11566 {
11567 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
11568 AssertRC(rc);
11569 ASMAtomicOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
11570 }
11571 }
11572 else
11573 pVCpu->cpum.GstCtx.hwvirt.vmx.fVirtApicPageDirty = true;
11574 }
11575
11576 Assert(VMMRZCallRing3IsEnabled(pVCpu));
11577 return;
11578 }
11579 }
11580#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11581 else if (pVmxTransient->fIsNestedGuest)
11582 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
11583#endif
11584 else
11585 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
11586
11587 VMMRZCallRing3Enable(pVCpu);
11588}
11589
11590
11591/**
11592 * Runs the guest code using hardware-assisted VMX the normal way.
11593 *
11594 * @returns VBox status code.
11595 * @param pVCpu The cross context virtual CPU structure.
11596 * @param pcLoops Pointer to the number of executed loops.
11597 */
11598static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPU pVCpu, uint32_t *pcLoops)
11599{
11600 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11601 Assert(pcLoops);
11602 Assert(*pcLoops <= cMaxResumeLoops);
11603 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11604
11605#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11606 /*
11607 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
11608 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
11609 * guest VMCS while entering the VMX ring-0 session.
11610 */
11611 if (pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
11612 {
11613 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
11614 if (RT_SUCCESS(rc))
11615 { /* likely */ }
11616 else
11617 {
11618 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
11619 return rc;
11620 }
11621 }
11622#endif
11623
11624 VMXTRANSIENT VmxTransient;
11625 RT_ZERO(VmxTransient);
11626 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11627
11628 /* Paranoia. */
11629 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfo);
11630
11631 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11632 for (;;)
11633 {
11634 Assert(!HMR0SuspendPending());
11635 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11636 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11637
11638 /*
11639 * Preparatory work for running nested-guest code, this may force us to
11640 * return to ring-3.
11641 *
11642 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11643 */
11644 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11645 if (rcStrict != VINF_SUCCESS)
11646 break;
11647
11648 /* Interrupts are disabled at this point! */
11649 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11650 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11651 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11652 /* Interrupts are re-enabled at this point! */
11653
11654 /*
11655 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11656 */
11657 if (RT_SUCCESS(rcRun))
11658 { /* very likely */ }
11659 else
11660 {
11661 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11662 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11663 return rcRun;
11664 }
11665
11666 /*
11667 * Profile the VM-exit.
11668 */
11669 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11670 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11671 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11672 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11673 HMVMX_START_EXIT_DISPATCH_PROF();
11674
11675 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11676
11677 /*
11678 * Handle the VM-exit.
11679 */
11680#ifdef HMVMX_USE_FUNCTION_TABLE
11681 rcStrict = g_apfnVMExitHandlers[VmxTransient.uExitReason](pVCpu, &VmxTransient);
11682#else
11683 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
11684#endif
11685 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11686 if (rcStrict == VINF_SUCCESS)
11687 {
11688 if (++(*pcLoops) <= cMaxResumeLoops)
11689 continue;
11690 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11691 rcStrict = VINF_EM_RAW_INTERRUPT;
11692 }
11693 break;
11694 }
11695
11696 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11697 return rcStrict;
11698}
11699
11700
11701#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11702/**
11703 * Runs the nested-guest code using hardware-assisted VMX.
11704 *
11705 * @returns VBox status code.
11706 * @param pVCpu The cross context virtual CPU structure.
11707 * @param pcLoops Pointer to the number of executed loops.
11708 *
11709 * @sa hmR0VmxRunGuestCodeNormal.
11710 */
11711static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPU pVCpu, uint32_t *pcLoops)
11712{
11713 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11714 Assert(pcLoops);
11715 Assert(*pcLoops <= cMaxResumeLoops);
11716 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11717
11718 /*
11719 * Switch to the nested-guest VMCS as we may have transitioned from executing the
11720 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
11721 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
11722 */
11723 if (!pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
11724 {
11725 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
11726 if (RT_SUCCESS(rc))
11727 { /* likely */ }
11728 else
11729 {
11730 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
11731 return rc;
11732 }
11733 }
11734
11735 VMXTRANSIENT VmxTransient;
11736 RT_ZERO(VmxTransient);
11737 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11738 VmxTransient.fIsNestedGuest = true;
11739
11740 /* Paranoia. */
11741 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfoNstGst);
11742
11743 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11744 for (;;)
11745 {
11746 Assert(!HMR0SuspendPending());
11747 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11748 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11749
11750 /*
11751 * Preparatory work for running guest code, this may force us to
11752 * return to ring-3.
11753 *
11754 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11755 */
11756 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11757 if (rcStrict != VINF_SUCCESS)
11758 break;
11759
11760 /* Interrupts are disabled at this point! */
11761 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11762 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11763 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11764 /* Interrupts are re-enabled at this point! */
11765
11766 /*
11767 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11768 */
11769 if (RT_SUCCESS(rcRun))
11770 { /* very likely */ }
11771 else
11772 {
11773 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11774 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11775 return rcRun;
11776 }
11777
11778 /*
11779 * Profile the VM-exit.
11780 */
11781 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11782 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11783 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
11784 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11785 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11786 HMVMX_START_EXIT_DISPATCH_PROF();
11787
11788 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11789
11790 /*
11791 * Handle the VM-exit.
11792 */
11793 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
11794 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11795 if (rcStrict == VINF_SUCCESS)
11796 {
11797 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11798 {
11799 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11800 rcStrict = VINF_VMX_VMEXIT;
11801 }
11802 else
11803 {
11804 if (++(*pcLoops) <= cMaxResumeLoops)
11805 continue;
11806 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11807 rcStrict = VINF_EM_RAW_INTERRUPT;
11808 }
11809 }
11810 else
11811 Assert(rcStrict != VINF_VMX_VMEXIT);
11812 break;
11813 }
11814
11815 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11816 return rcStrict;
11817}
11818#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11819
11820
11821/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
11822 * probes.
11823 *
11824 * The following few functions and associated structure contains the bloat
11825 * necessary for providing detailed debug events and dtrace probes as well as
11826 * reliable host side single stepping. This works on the principle of
11827 * "subclassing" the normal execution loop and workers. We replace the loop
11828 * method completely and override selected helpers to add necessary adjustments
11829 * to their core operation.
11830 *
11831 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11832 * any performance for debug and analysis features.
11833 *
11834 * @{
11835 */
11836
11837/**
11838 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11839 * the debug run loop.
11840 */
11841typedef struct VMXRUNDBGSTATE
11842{
11843 /** The RIP we started executing at. This is for detecting that we stepped. */
11844 uint64_t uRipStart;
11845 /** The CS we started executing with. */
11846 uint16_t uCsStart;
11847
11848 /** Whether we've actually modified the 1st execution control field. */
11849 bool fModifiedProcCtls : 1;
11850 /** Whether we've actually modified the 2nd execution control field. */
11851 bool fModifiedProcCtls2 : 1;
11852 /** Whether we've actually modified the exception bitmap. */
11853 bool fModifiedXcptBitmap : 1;
11854
11855 /** We desire the modified the CR0 mask to be cleared. */
11856 bool fClearCr0Mask : 1;
11857 /** We desire the modified the CR4 mask to be cleared. */
11858 bool fClearCr4Mask : 1;
11859 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11860 uint32_t fCpe1Extra;
11861 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11862 uint32_t fCpe1Unwanted;
11863 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11864 uint32_t fCpe2Extra;
11865 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11866 uint32_t bmXcptExtra;
11867 /** The sequence number of the Dtrace provider settings the state was
11868 * configured against. */
11869 uint32_t uDtraceSettingsSeqNo;
11870 /** VM-exits to check (one bit per VM-exit). */
11871 uint32_t bmExitsToCheck[3];
11872
11873 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11874 uint32_t fProcCtlsInitial;
11875 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11876 uint32_t fProcCtls2Initial;
11877 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11878 uint32_t bmXcptInitial;
11879} VMXRUNDBGSTATE;
11880AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11881typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11882
11883
11884/**
11885 * Initializes the VMXRUNDBGSTATE structure.
11886 *
11887 * @param pVCpu The cross context virtual CPU structure of the
11888 * calling EMT.
11889 * @param pVmxTransient The VMX-transient structure.
11890 * @param pDbgState The debug state to initialize.
11891 */
11892static void hmR0VmxRunDebugStateInit(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11893{
11894 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11895 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11896
11897 pDbgState->fModifiedProcCtls = false;
11898 pDbgState->fModifiedProcCtls2 = false;
11899 pDbgState->fModifiedXcptBitmap = false;
11900 pDbgState->fClearCr0Mask = false;
11901 pDbgState->fClearCr4Mask = false;
11902 pDbgState->fCpe1Extra = 0;
11903 pDbgState->fCpe1Unwanted = 0;
11904 pDbgState->fCpe2Extra = 0;
11905 pDbgState->bmXcptExtra = 0;
11906 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11907 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11908 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11909}
11910
11911
11912/**
11913 * Updates the VMSC fields with changes requested by @a pDbgState.
11914 *
11915 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11916 * immediately before executing guest code, i.e. when interrupts are disabled.
11917 * We don't check status codes here as we cannot easily assert or return in the
11918 * latter case.
11919 *
11920 * @param pVCpu The cross context virtual CPU structure.
11921 * @param pVmxTransient The VMX-transient structure.
11922 * @param pDbgState The debug state.
11923 */
11924static void hmR0VmxPreRunGuestDebugStateApply(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11925{
11926 /*
11927 * Ensure desired flags in VMCS control fields are set.
11928 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11929 *
11930 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11931 * there should be no stale data in pCtx at this point.
11932 */
11933 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11934 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11935 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11936 {
11937 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11938 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11939 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11940 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11941 pDbgState->fModifiedProcCtls = true;
11942 }
11943
11944 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11945 {
11946 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11947 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11948 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11949 pDbgState->fModifiedProcCtls2 = true;
11950 }
11951
11952 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11953 {
11954 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11955 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11956 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11957 pDbgState->fModifiedXcptBitmap = true;
11958 }
11959
11960 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11961 {
11962 pVmcsInfo->u64Cr0Mask = 0;
11963 VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, 0);
11964 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11965 }
11966
11967 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11968 {
11969 pVmcsInfo->u64Cr4Mask = 0;
11970 VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, 0);
11971 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11972 }
11973
11974 NOREF(pVCpu);
11975}
11976
11977
11978/**
11979 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11980 * re-entry next time around.
11981 *
11982 * @returns Strict VBox status code (i.e. informational status codes too).
11983 * @param pVCpu The cross context virtual CPU structure.
11984 * @param pVmxTransient The VMX-transient structure.
11985 * @param pDbgState The debug state.
11986 * @param rcStrict The return code from executing the guest using single
11987 * stepping.
11988 */
11989static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11990 VBOXSTRICTRC rcStrict)
11991{
11992 /*
11993 * Restore VM-exit control settings as we may not reenter this function the
11994 * next time around.
11995 */
11996 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11997
11998 /* We reload the initial value, trigger what we can of recalculations the
11999 next time around. From the looks of things, that's all that's required atm. */
12000 if (pDbgState->fModifiedProcCtls)
12001 {
12002 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
12003 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
12004 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
12005 AssertRCReturn(rc2, rc2);
12006 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
12007 }
12008
12009 /* We're currently the only ones messing with this one, so just restore the
12010 cached value and reload the field. */
12011 if ( pDbgState->fModifiedProcCtls2
12012 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
12013 {
12014 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
12015 AssertRCReturn(rc2, rc2);
12016 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
12017 }
12018
12019 /* If we've modified the exception bitmap, we restore it and trigger
12020 reloading and partial recalculation the next time around. */
12021 if (pDbgState->fModifiedXcptBitmap)
12022 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
12023
12024 return rcStrict;
12025}
12026
12027
12028/**
12029 * Configures VM-exit controls for current DBGF and DTrace settings.
12030 *
12031 * This updates @a pDbgState and the VMCS execution control fields to reflect
12032 * the necessary VM-exits demanded by DBGF and DTrace.
12033 *
12034 * @param pVCpu The cross context virtual CPU structure.
12035 * @param pVmxTransient The VMX-transient structure. May update
12036 * fUpdatedTscOffsettingAndPreemptTimer.
12037 * @param pDbgState The debug state.
12038 */
12039static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
12040{
12041 /*
12042 * Take down the dtrace serial number so we can spot changes.
12043 */
12044 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
12045 ASMCompilerBarrier();
12046
12047 /*
12048 * We'll rebuild most of the middle block of data members (holding the
12049 * current settings) as we go along here, so start by clearing it all.
12050 */
12051 pDbgState->bmXcptExtra = 0;
12052 pDbgState->fCpe1Extra = 0;
12053 pDbgState->fCpe1Unwanted = 0;
12054 pDbgState->fCpe2Extra = 0;
12055 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
12056 pDbgState->bmExitsToCheck[i] = 0;
12057
12058 /*
12059 * Software interrupts (INT XXh) - no idea how to trigger these...
12060 */
12061 PVM pVM = pVCpu->CTX_SUFF(pVM);
12062 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
12063 || VBOXVMM_INT_SOFTWARE_ENABLED())
12064 {
12065 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
12066 }
12067
12068 /*
12069 * INT3 breakpoints - triggered by #BP exceptions.
12070 */
12071 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
12072 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
12073
12074 /*
12075 * Exception bitmap and XCPT events+probes.
12076 */
12077 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
12078 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
12079 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
12080
12081 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
12082 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
12083 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
12084 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
12085 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
12086 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
12087 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
12088 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
12089 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
12090 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
12091 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
12092 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
12093 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
12094 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
12095 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
12096 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
12097 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
12098 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
12099
12100 if (pDbgState->bmXcptExtra)
12101 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
12102
12103 /*
12104 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
12105 *
12106 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
12107 * So, when adding/changing/removing please don't forget to update it.
12108 *
12109 * Some of the macros are picking up local variables to save horizontal space,
12110 * (being able to see it in a table is the lesser evil here).
12111 */
12112#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
12113 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
12114 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
12115#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
12116 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12117 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12118 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12119 } else do { } while (0)
12120#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
12121 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12122 { \
12123 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
12124 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12125 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12126 } else do { } while (0)
12127#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
12128 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12129 { \
12130 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
12131 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12132 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12133 } else do { } while (0)
12134#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
12135 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12136 { \
12137 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
12138 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12139 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12140 } else do { } while (0)
12141
12142 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
12143 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
12144 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
12145 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
12146 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
12147
12148 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
12149 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
12150 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
12151 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
12152 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
12153 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
12154 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
12155 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
12156 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
12157 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
12158 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
12159 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
12160 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
12161 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
12162 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
12163 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
12164 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
12165 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
12166 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
12167 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
12168 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
12169 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
12170 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
12171 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
12172 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
12173 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
12174 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
12175 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
12176 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
12177 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
12178 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
12179 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
12180 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
12181 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
12182 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
12183 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
12184
12185 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
12186 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
12187 {
12188 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
12189 | CPUMCTX_EXTRN_APIC_TPR);
12190 AssertRC(rc);
12191
12192#if 0 /** @todo fix me */
12193 pDbgState->fClearCr0Mask = true;
12194 pDbgState->fClearCr4Mask = true;
12195#endif
12196 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
12197 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
12198 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
12199 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
12200 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
12201 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
12202 require clearing here and in the loop if we start using it. */
12203 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
12204 }
12205 else
12206 {
12207 if (pDbgState->fClearCr0Mask)
12208 {
12209 pDbgState->fClearCr0Mask = false;
12210 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
12211 }
12212 if (pDbgState->fClearCr4Mask)
12213 {
12214 pDbgState->fClearCr4Mask = false;
12215 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
12216 }
12217 }
12218 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
12219 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
12220
12221 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
12222 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
12223 {
12224 /** @todo later, need to fix handler as it assumes this won't usually happen. */
12225 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
12226 }
12227 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
12228 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
12229
12230 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
12231 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
12232 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
12233 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
12234 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
12235 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
12236 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
12237 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
12238#if 0 /** @todo too slow, fix handler. */
12239 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
12240#endif
12241 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
12242
12243 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
12244 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
12245 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
12246 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
12247 {
12248 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
12249 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
12250 }
12251 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12252 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12253 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12254 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12255
12256 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
12257 || IS_EITHER_ENABLED(pVM, INSTR_STR)
12258 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
12259 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
12260 {
12261 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
12262 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
12263 }
12264 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
12265 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
12266 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
12267 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
12268
12269 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
12270 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
12271 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
12272 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
12273 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
12274 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
12275 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
12276 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
12277 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
12278 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
12279 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
12280 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
12281 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
12282 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
12283 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
12284 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
12285 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
12286 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
12287 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
12288 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
12289 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
12290 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
12291
12292#undef IS_EITHER_ENABLED
12293#undef SET_ONLY_XBM_IF_EITHER_EN
12294#undef SET_CPE1_XBM_IF_EITHER_EN
12295#undef SET_CPEU_XBM_IF_EITHER_EN
12296#undef SET_CPE2_XBM_IF_EITHER_EN
12297
12298 /*
12299 * Sanitize the control stuff.
12300 */
12301 pDbgState->fCpe2Extra &= pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1;
12302 if (pDbgState->fCpe2Extra)
12303 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
12304 pDbgState->fCpe1Extra &= pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1;
12305 pDbgState->fCpe1Unwanted &= ~pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0;
12306 if (pVCpu->hm.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
12307 {
12308 pVCpu->hm.s.fDebugWantRdTscExit ^= true;
12309 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
12310 }
12311
12312 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
12313 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
12314 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
12315 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
12316}
12317
12318
12319/**
12320 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
12321 * appropriate.
12322 *
12323 * The caller has checked the VM-exit against the
12324 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
12325 * already, so we don't have to do that either.
12326 *
12327 * @returns Strict VBox status code (i.e. informational status codes too).
12328 * @param pVCpu The cross context virtual CPU structure.
12329 * @param pVmxTransient The VMX-transient structure.
12330 * @param uExitReason The VM-exit reason.
12331 *
12332 * @remarks The name of this function is displayed by dtrace, so keep it short
12333 * and to the point. No longer than 33 chars long, please.
12334 */
12335static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
12336{
12337 /*
12338 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
12339 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
12340 *
12341 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
12342 * does. Must add/change/remove both places. Same ordering, please.
12343 *
12344 * Added/removed events must also be reflected in the next section
12345 * where we dispatch dtrace events.
12346 */
12347 bool fDtrace1 = false;
12348 bool fDtrace2 = false;
12349 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
12350 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
12351 uint32_t uEventArg = 0;
12352#define SET_EXIT(a_EventSubName) \
12353 do { \
12354 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12355 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12356 } while (0)
12357#define SET_BOTH(a_EventSubName) \
12358 do { \
12359 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
12360 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12361 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
12362 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12363 } while (0)
12364 switch (uExitReason)
12365 {
12366 case VMX_EXIT_MTF:
12367 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12368
12369 case VMX_EXIT_XCPT_OR_NMI:
12370 {
12371 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
12372 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
12373 {
12374 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
12375 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
12376 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
12377 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
12378 {
12379 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
12380 {
12381 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
12382 uEventArg = pVmxTransient->uExitIntErrorCode;
12383 }
12384 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
12385 switch (enmEvent1)
12386 {
12387 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
12388 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
12389 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
12390 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
12391 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
12392 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
12393 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
12394 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
12395 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
12396 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
12397 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
12398 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
12399 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
12400 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
12401 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
12402 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
12403 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
12404 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
12405 default: break;
12406 }
12407 }
12408 else
12409 AssertFailed();
12410 break;
12411
12412 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
12413 uEventArg = idxVector;
12414 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
12415 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
12416 break;
12417 }
12418 break;
12419 }
12420
12421 case VMX_EXIT_TRIPLE_FAULT:
12422 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
12423 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
12424 break;
12425 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
12426 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
12427 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
12428 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
12429 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
12430
12431 /* Instruction specific VM-exits: */
12432 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
12433 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
12434 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
12435 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
12436 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
12437 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
12438 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
12439 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
12440 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
12441 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
12442 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
12443 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
12444 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
12445 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
12446 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
12447 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
12448 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
12449 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
12450 case VMX_EXIT_MOV_CRX:
12451 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12452 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
12453 SET_BOTH(CRX_READ);
12454 else
12455 SET_BOTH(CRX_WRITE);
12456 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
12457 break;
12458 case VMX_EXIT_MOV_DRX:
12459 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12460 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
12461 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
12462 SET_BOTH(DRX_READ);
12463 else
12464 SET_BOTH(DRX_WRITE);
12465 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
12466 break;
12467 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
12468 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
12469 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
12470 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
12471 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
12472 case VMX_EXIT_GDTR_IDTR_ACCESS:
12473 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12474 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
12475 {
12476 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
12477 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
12478 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
12479 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
12480 }
12481 break;
12482
12483 case VMX_EXIT_LDTR_TR_ACCESS:
12484 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12485 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
12486 {
12487 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
12488 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
12489 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
12490 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
12491 }
12492 break;
12493
12494 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
12495 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
12496 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
12497 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
12498 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
12499 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
12500 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
12501 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
12502 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
12503 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
12504 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
12505
12506 /* Events that aren't relevant at this point. */
12507 case VMX_EXIT_EXT_INT:
12508 case VMX_EXIT_INT_WINDOW:
12509 case VMX_EXIT_NMI_WINDOW:
12510 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12511 case VMX_EXIT_PREEMPT_TIMER:
12512 case VMX_EXIT_IO_INSTR:
12513 break;
12514
12515 /* Errors and unexpected events. */
12516 case VMX_EXIT_INIT_SIGNAL:
12517 case VMX_EXIT_SIPI:
12518 case VMX_EXIT_IO_SMI:
12519 case VMX_EXIT_SMI:
12520 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12521 case VMX_EXIT_ERR_MSR_LOAD:
12522 case VMX_EXIT_ERR_MACHINE_CHECK:
12523 case VMX_EXIT_PML_FULL:
12524 case VMX_EXIT_VIRTUALIZED_EOI:
12525 break;
12526
12527 default:
12528 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12529 break;
12530 }
12531#undef SET_BOTH
12532#undef SET_EXIT
12533
12534 /*
12535 * Dtrace tracepoints go first. We do them here at once so we don't
12536 * have to copy the guest state saving and stuff a few dozen times.
12537 * Down side is that we've got to repeat the switch, though this time
12538 * we use enmEvent since the probes are a subset of what DBGF does.
12539 */
12540 if (fDtrace1 || fDtrace2)
12541 {
12542 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12543 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12544 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12545 switch (enmEvent1)
12546 {
12547 /** @todo consider which extra parameters would be helpful for each probe. */
12548 case DBGFEVENT_END: break;
12549 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
12550 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
12551 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
12552 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
12553 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
12554 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
12555 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
12556 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
12557 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
12558 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
12559 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
12560 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
12561 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
12562 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
12563 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
12564 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
12565 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
12566 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
12567 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12568 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12569 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
12570 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
12571 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
12572 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
12573 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
12574 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
12575 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
12576 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12577 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12578 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12579 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12580 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12581 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
12582 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12583 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
12584 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
12585 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
12586 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
12587 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
12588 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
12589 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
12590 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
12591 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
12592 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
12593 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
12594 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
12595 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
12596 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
12597 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
12598 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
12599 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
12600 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
12601 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
12602 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
12603 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
12604 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
12605 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
12606 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
12607 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
12608 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
12609 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
12610 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
12611 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
12612 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
12613 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
12614 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
12615 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
12616 }
12617 switch (enmEvent2)
12618 {
12619 /** @todo consider which extra parameters would be helpful for each probe. */
12620 case DBGFEVENT_END: break;
12621 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
12622 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12623 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
12624 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
12625 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
12626 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
12627 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
12628 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
12629 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
12630 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12631 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12632 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12633 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12634 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12635 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
12636 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12637 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
12638 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
12639 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
12640 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
12641 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
12642 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
12643 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
12644 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
12645 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
12646 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
12647 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
12648 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
12649 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
12650 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
12651 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
12652 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
12653 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
12654 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
12655 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
12656 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
12657 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
12658 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
12659 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
12660 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
12661 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
12662 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
12663 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
12664 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
12665 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
12666 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
12667 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
12668 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
12669 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
12670 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
12671 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
12672 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
12673 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
12674 }
12675 }
12676
12677 /*
12678 * Fire of the DBGF event, if enabled (our check here is just a quick one,
12679 * the DBGF call will do a full check).
12680 *
12681 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
12682 * Note! If we have to events, we prioritize the first, i.e. the instruction
12683 * one, in order to avoid event nesting.
12684 */
12685 PVM pVM = pVCpu->CTX_SUFF(pVM);
12686 if ( enmEvent1 != DBGFEVENT_END
12687 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
12688 {
12689 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12690 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
12691 if (rcStrict != VINF_SUCCESS)
12692 return rcStrict;
12693 }
12694 else if ( enmEvent2 != DBGFEVENT_END
12695 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
12696 {
12697 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12698 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
12699 if (rcStrict != VINF_SUCCESS)
12700 return rcStrict;
12701 }
12702
12703 return VINF_SUCCESS;
12704}
12705
12706
12707/**
12708 * Single-stepping VM-exit filtering.
12709 *
12710 * This is preprocessing the VM-exits and deciding whether we've gotten far
12711 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
12712 * handling is performed.
12713 *
12714 * @returns Strict VBox status code (i.e. informational status codes too).
12715 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
12716 * @param pVmxTransient The VMX-transient structure.
12717 * @param pDbgState The debug state.
12718 */
12719DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
12720{
12721 /*
12722 * Expensive (saves context) generic dtrace VM-exit probe.
12723 */
12724 uint32_t const uExitReason = pVmxTransient->uExitReason;
12725 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
12726 { /* more likely */ }
12727 else
12728 {
12729 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12730 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12731 AssertRC(rc);
12732 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
12733 }
12734
12735 /*
12736 * Check for host NMI, just to get that out of the way.
12737 */
12738 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
12739 { /* normally likely */ }
12740 else
12741 {
12742 int rc2 = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
12743 AssertRCReturn(rc2, rc2);
12744 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
12745 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
12746 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
12747 }
12748
12749 /*
12750 * Check for single stepping event if we're stepping.
12751 */
12752 if (pVCpu->hm.s.fSingleInstruction)
12753 {
12754 switch (uExitReason)
12755 {
12756 case VMX_EXIT_MTF:
12757 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12758
12759 /* Various events: */
12760 case VMX_EXIT_XCPT_OR_NMI:
12761 case VMX_EXIT_EXT_INT:
12762 case VMX_EXIT_TRIPLE_FAULT:
12763 case VMX_EXIT_INT_WINDOW:
12764 case VMX_EXIT_NMI_WINDOW:
12765 case VMX_EXIT_TASK_SWITCH:
12766 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12767 case VMX_EXIT_APIC_ACCESS:
12768 case VMX_EXIT_EPT_VIOLATION:
12769 case VMX_EXIT_EPT_MISCONFIG:
12770 case VMX_EXIT_PREEMPT_TIMER:
12771
12772 /* Instruction specific VM-exits: */
12773 case VMX_EXIT_CPUID:
12774 case VMX_EXIT_GETSEC:
12775 case VMX_EXIT_HLT:
12776 case VMX_EXIT_INVD:
12777 case VMX_EXIT_INVLPG:
12778 case VMX_EXIT_RDPMC:
12779 case VMX_EXIT_RDTSC:
12780 case VMX_EXIT_RSM:
12781 case VMX_EXIT_VMCALL:
12782 case VMX_EXIT_VMCLEAR:
12783 case VMX_EXIT_VMLAUNCH:
12784 case VMX_EXIT_VMPTRLD:
12785 case VMX_EXIT_VMPTRST:
12786 case VMX_EXIT_VMREAD:
12787 case VMX_EXIT_VMRESUME:
12788 case VMX_EXIT_VMWRITE:
12789 case VMX_EXIT_VMXOFF:
12790 case VMX_EXIT_VMXON:
12791 case VMX_EXIT_MOV_CRX:
12792 case VMX_EXIT_MOV_DRX:
12793 case VMX_EXIT_IO_INSTR:
12794 case VMX_EXIT_RDMSR:
12795 case VMX_EXIT_WRMSR:
12796 case VMX_EXIT_MWAIT:
12797 case VMX_EXIT_MONITOR:
12798 case VMX_EXIT_PAUSE:
12799 case VMX_EXIT_GDTR_IDTR_ACCESS:
12800 case VMX_EXIT_LDTR_TR_ACCESS:
12801 case VMX_EXIT_INVEPT:
12802 case VMX_EXIT_RDTSCP:
12803 case VMX_EXIT_INVVPID:
12804 case VMX_EXIT_WBINVD:
12805 case VMX_EXIT_XSETBV:
12806 case VMX_EXIT_RDRAND:
12807 case VMX_EXIT_INVPCID:
12808 case VMX_EXIT_VMFUNC:
12809 case VMX_EXIT_RDSEED:
12810 case VMX_EXIT_XSAVES:
12811 case VMX_EXIT_XRSTORS:
12812 {
12813 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12814 AssertRCReturn(rc, rc);
12815 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
12816 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
12817 return VINF_EM_DBG_STEPPED;
12818 break;
12819 }
12820
12821 /* Errors and unexpected events: */
12822 case VMX_EXIT_INIT_SIGNAL:
12823 case VMX_EXIT_SIPI:
12824 case VMX_EXIT_IO_SMI:
12825 case VMX_EXIT_SMI:
12826 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12827 case VMX_EXIT_ERR_MSR_LOAD:
12828 case VMX_EXIT_ERR_MACHINE_CHECK:
12829 case VMX_EXIT_PML_FULL:
12830 case VMX_EXIT_VIRTUALIZED_EOI:
12831 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
12832 break;
12833
12834 default:
12835 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12836 break;
12837 }
12838 }
12839
12840 /*
12841 * Check for debugger event breakpoints and dtrace probes.
12842 */
12843 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12844 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12845 {
12846 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12847 if (rcStrict != VINF_SUCCESS)
12848 return rcStrict;
12849 }
12850
12851 /*
12852 * Normal processing.
12853 */
12854#ifdef HMVMX_USE_FUNCTION_TABLE
12855 return g_apfnVMExitHandlers[uExitReason](pVCpu, pVmxTransient);
12856#else
12857 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12858#endif
12859}
12860
12861
12862/**
12863 * Single steps guest code using hardware-assisted VMX.
12864 *
12865 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12866 * but single-stepping through the hypervisor debugger.
12867 *
12868 * @returns Strict VBox status code (i.e. informational status codes too).
12869 * @param pVCpu The cross context virtual CPU structure.
12870 * @param pcLoops Pointer to the number of executed loops.
12871 *
12872 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12873 */
12874static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPU pVCpu, uint32_t *pcLoops)
12875{
12876 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
12877 Assert(pcLoops);
12878 Assert(*pcLoops <= cMaxResumeLoops);
12879
12880 VMXTRANSIENT VmxTransient;
12881 RT_ZERO(VmxTransient);
12882 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12883
12884 /* Set HMCPU indicators. */
12885 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12886 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12887 pVCpu->hm.s.fDebugWantRdTscExit = false;
12888 pVCpu->hm.s.fUsingDebugLoop = true;
12889
12890 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12891 VMXRUNDBGSTATE DbgState;
12892 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12893 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12894
12895 /*
12896 * The loop.
12897 */
12898 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12899 for (;;)
12900 {
12901 Assert(!HMR0SuspendPending());
12902 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12903 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12904 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12905
12906 /* Set up VM-execution controls the next two can respond to. */
12907 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12908
12909 /*
12910 * Preparatory work for running guest code, this may force us to
12911 * return to ring-3.
12912 *
12913 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12914 */
12915 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12916 if (rcStrict != VINF_SUCCESS)
12917 break;
12918
12919 /* Interrupts are disabled at this point! */
12920 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12921
12922 /* Override any obnoxious code in the above two calls. */
12923 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12924
12925 /*
12926 * Finally execute the guest.
12927 */
12928 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12929
12930 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12931 /* Interrupts are re-enabled at this point! */
12932
12933 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12934 if (RT_SUCCESS(rcRun))
12935 { /* very likely */ }
12936 else
12937 {
12938 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12939 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12940 return rcRun;
12941 }
12942
12943 /* Profile the VM-exit. */
12944 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12945 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12946 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12947 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12948 HMVMX_START_EXIT_DISPATCH_PROF();
12949
12950 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12951
12952 /*
12953 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12954 */
12955 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12956 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12957 if (rcStrict != VINF_SUCCESS)
12958 break;
12959 if (++(*pcLoops) > cMaxResumeLoops)
12960 {
12961 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12962 rcStrict = VINF_EM_RAW_INTERRUPT;
12963 break;
12964 }
12965
12966 /*
12967 * Stepping: Did the RIP change, if so, consider it a single step.
12968 * Otherwise, make sure one of the TFs gets set.
12969 */
12970 if (fStepping)
12971 {
12972 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12973 AssertRC(rc);
12974 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12975 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12976 {
12977 rcStrict = VINF_EM_DBG_STEPPED;
12978 break;
12979 }
12980 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12981 }
12982
12983 /*
12984 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12985 */
12986 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12987 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12988 }
12989
12990 /*
12991 * Clear the X86_EFL_TF if necessary.
12992 */
12993 if (pVCpu->hm.s.fClearTrapFlag)
12994 {
12995 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12996 AssertRC(rc);
12997 pVCpu->hm.s.fClearTrapFlag = false;
12998 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12999 }
13000 /** @todo there seems to be issues with the resume flag when the monitor trap
13001 * flag is pending without being used. Seen early in bios init when
13002 * accessing APIC page in protected mode. */
13003
13004 /*
13005 * Restore VM-exit control settings as we may not re-enter this function the
13006 * next time around.
13007 */
13008 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
13009
13010 /* Restore HMCPU indicators. */
13011 pVCpu->hm.s.fUsingDebugLoop = false;
13012 pVCpu->hm.s.fDebugWantRdTscExit = false;
13013 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
13014
13015 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
13016 return rcStrict;
13017}
13018
13019
13020/** @} */
13021
13022
13023/**
13024 * Checks if any expensive dtrace probes are enabled and we should go to the
13025 * debug loop.
13026 *
13027 * @returns true if we should use debug loop, false if not.
13028 */
13029static bool hmR0VmxAnyExpensiveProbesEnabled(void)
13030{
13031 /* It's probably faster to OR the raw 32-bit counter variables together.
13032 Since the variables are in an array and the probes are next to one
13033 another (more or less), we have good locality. So, better read
13034 eight-nine cache lines ever time and only have one conditional, than
13035 128+ conditionals, right? */
13036 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
13037 | VBOXVMM_XCPT_DE_ENABLED_RAW()
13038 | VBOXVMM_XCPT_DB_ENABLED_RAW()
13039 | VBOXVMM_XCPT_BP_ENABLED_RAW()
13040 | VBOXVMM_XCPT_OF_ENABLED_RAW()
13041 | VBOXVMM_XCPT_BR_ENABLED_RAW()
13042 | VBOXVMM_XCPT_UD_ENABLED_RAW()
13043 | VBOXVMM_XCPT_NM_ENABLED_RAW()
13044 | VBOXVMM_XCPT_DF_ENABLED_RAW()
13045 | VBOXVMM_XCPT_TS_ENABLED_RAW()
13046 | VBOXVMM_XCPT_NP_ENABLED_RAW()
13047 | VBOXVMM_XCPT_SS_ENABLED_RAW()
13048 | VBOXVMM_XCPT_GP_ENABLED_RAW()
13049 | VBOXVMM_XCPT_PF_ENABLED_RAW()
13050 | VBOXVMM_XCPT_MF_ENABLED_RAW()
13051 | VBOXVMM_XCPT_AC_ENABLED_RAW()
13052 | VBOXVMM_XCPT_XF_ENABLED_RAW()
13053 | VBOXVMM_XCPT_VE_ENABLED_RAW()
13054 | VBOXVMM_XCPT_SX_ENABLED_RAW()
13055 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
13056 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
13057 ) != 0
13058 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
13059 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
13060 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
13061 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
13062 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
13063 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
13064 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
13065 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
13066 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
13067 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
13068 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
13069 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
13070 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
13071 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
13072 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
13073 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
13074 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
13075 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
13076 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
13077 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
13078 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
13079 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
13080 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
13081 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
13082 | VBOXVMM_INSTR_STR_ENABLED_RAW()
13083 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
13084 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
13085 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
13086 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
13087 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
13088 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
13089 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
13090 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
13091 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
13092 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
13093 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
13094 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
13095 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
13096 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
13097 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
13098 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
13099 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
13100 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
13101 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
13102 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
13103 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
13104 ) != 0
13105 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
13106 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
13107 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
13108 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
13109 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
13110 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
13111 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
13112 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
13113 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
13114 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
13115 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
13116 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
13117 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
13118 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
13119 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
13120 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
13121 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
13122 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
13123 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
13124 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
13125 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
13126 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
13127 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
13128 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
13129 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
13130 | VBOXVMM_EXIT_STR_ENABLED_RAW()
13131 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
13132 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
13133 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
13134 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
13135 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
13136 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
13137 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
13138 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
13139 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
13140 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
13141 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
13142 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
13143 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
13144 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
13145 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
13146 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
13147 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
13148 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
13149 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
13150 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
13151 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
13152 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
13153 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
13154 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
13155 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
13156 ) != 0;
13157}
13158
13159
13160/**
13161 * Runs the guest using hardware-assisted VMX.
13162 *
13163 * @returns Strict VBox status code (i.e. informational status codes too).
13164 * @param pVCpu The cross context virtual CPU structure.
13165 */
13166VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPU pVCpu)
13167{
13168 AssertPtr(pVCpu);
13169 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13170 Assert(VMMRZCallRing3IsEnabled(pVCpu));
13171 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
13172 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
13173
13174 VMMRZCallRing3SetNotification(pVCpu, hmR0VmxCallRing3Callback, pCtx);
13175
13176 VBOXSTRICTRC rcStrict;
13177 uint32_t cLoops = 0;
13178 for (;;)
13179 {
13180#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13181 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
13182#else
13183 bool const fInNestedGuestMode = false;
13184#endif
13185 if (!fInNestedGuestMode)
13186 {
13187 if ( !pVCpu->hm.s.fUseDebugLoop
13188 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
13189 && !DBGFIsStepping(pVCpu)
13190 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
13191 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
13192 else
13193 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
13194 }
13195#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13196 else
13197 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
13198
13199 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
13200 {
13201 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
13202 continue;
13203 }
13204 if (rcStrict == VINF_VMX_VMEXIT)
13205 {
13206 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
13207 continue;
13208 }
13209#endif
13210 break;
13211 }
13212
13213 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
13214 switch (rcLoop)
13215 {
13216 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
13217 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
13218 }
13219
13220 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
13221 if (RT_FAILURE(rc2))
13222 {
13223 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
13224 rcStrict = rc2;
13225 }
13226 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
13227 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
13228 return rcStrict;
13229}
13230
13231
13232#ifndef HMVMX_USE_FUNCTION_TABLE
13233/**
13234 * Handles a guest VM-exit from hardware-assisted VMX execution.
13235 *
13236 * @returns Strict VBox status code (i.e. informational status codes too).
13237 * @param pVCpu The cross context virtual CPU structure.
13238 * @param pVmxTransient The VMX-transient structure.
13239 */
13240DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13241{
13242#ifdef DEBUG_ramshankar
13243#define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
13244 do { \
13245 if (a_fSave != 0) \
13246 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
13247 VBOXSTRICTRC rcStrict = a_CallExpr; \
13248 if (a_fSave != 0) \
13249 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
13250 return rcStrict; \
13251 } while (0)
13252#else
13253# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
13254#endif
13255 uint32_t const uExitReason = pVmxTransient->uExitReason;
13256 switch (uExitReason)
13257 {
13258 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
13259 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
13260 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
13261 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
13262 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
13263 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
13264 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
13265 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
13266 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
13267 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
13268 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
13269 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
13270 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
13271 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
13272 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
13273 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
13274 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
13275 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
13276 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
13277 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
13278 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
13279 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
13280 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
13281 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
13282 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
13283 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
13284 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
13285 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
13286 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
13287 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
13288#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13289 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
13290 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
13291 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
13292 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
13293 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
13294 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
13295 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
13296 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
13297 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
13298 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
13299 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
13300#else
13301 case VMX_EXIT_VMCLEAR:
13302 case VMX_EXIT_VMLAUNCH:
13303 case VMX_EXIT_VMPTRLD:
13304 case VMX_EXIT_VMPTRST:
13305 case VMX_EXIT_VMREAD:
13306 case VMX_EXIT_VMRESUME:
13307 case VMX_EXIT_VMWRITE:
13308 case VMX_EXIT_VMXOFF:
13309 case VMX_EXIT_VMXON:
13310 case VMX_EXIT_INVVPID:
13311 case VMX_EXIT_INVEPT:
13312 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
13313#endif
13314
13315 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
13316 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
13317 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
13318
13319 case VMX_EXIT_INIT_SIGNAL:
13320 case VMX_EXIT_SIPI:
13321 case VMX_EXIT_IO_SMI:
13322 case VMX_EXIT_SMI:
13323 case VMX_EXIT_ERR_MSR_LOAD:
13324 case VMX_EXIT_ERR_MACHINE_CHECK:
13325 case VMX_EXIT_PML_FULL:
13326 case VMX_EXIT_VIRTUALIZED_EOI:
13327 case VMX_EXIT_GDTR_IDTR_ACCESS:
13328 case VMX_EXIT_LDTR_TR_ACCESS:
13329 case VMX_EXIT_APIC_WRITE:
13330 case VMX_EXIT_RDRAND:
13331 case VMX_EXIT_RSM:
13332 case VMX_EXIT_VMFUNC:
13333 case VMX_EXIT_ENCLS:
13334 case VMX_EXIT_RDSEED:
13335 case VMX_EXIT_XSAVES:
13336 case VMX_EXIT_XRSTORS:
13337 case VMX_EXIT_UMWAIT:
13338 case VMX_EXIT_TPAUSE:
13339 default:
13340 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13341 }
13342#undef VMEXIT_CALL_RET
13343}
13344#endif /* !HMVMX_USE_FUNCTION_TABLE */
13345
13346
13347#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13348/**
13349 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
13350 *
13351 * @returns Strict VBox status code (i.e. informational status codes too).
13352 * @param pVCpu The cross context virtual CPU structure.
13353 * @param pVmxTransient The VMX-transient structure.
13354 */
13355DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13356{
13357 uint32_t const uExitReason = pVmxTransient->uExitReason;
13358 switch (uExitReason)
13359 {
13360 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
13361 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
13362 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
13363 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
13364 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
13365
13366 /*
13367 * We shouldn't direct host physical interrupts to the nested-guest.
13368 */
13369 case VMX_EXIT_EXT_INT:
13370 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
13371
13372 /*
13373 * Instructions that cause VM-exits unconditionally or the condition is
13374 * always is taken solely from the guest hypervisor (meaning if the VM-exit
13375 * happens, it's guaranteed to be a nested-guest VM-exit).
13376 *
13377 * - Provides VM-exit instruction length ONLY.
13378 */
13379 case VMX_EXIT_CPUID: /* Unconditional. */
13380 case VMX_EXIT_VMCALL:
13381 case VMX_EXIT_GETSEC:
13382 case VMX_EXIT_INVD:
13383 case VMX_EXIT_XSETBV:
13384 case VMX_EXIT_VMLAUNCH:
13385 case VMX_EXIT_VMRESUME:
13386 case VMX_EXIT_VMXOFF:
13387 case VMX_EXIT_ENCLS: /* Condition specified solely by guest hypervisor. */
13388 case VMX_EXIT_VMFUNC:
13389 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
13390
13391 /*
13392 * Instructions that cause VM-exits unconditionally or the condition is
13393 * always is taken solely from the guest hypervisor (meaning if the VM-exit
13394 * happens, it's guaranteed to be a nested-guest VM-exit).
13395 *
13396 * - Provides VM-exit instruction length.
13397 * - Provides VM-exit information.
13398 * - Optionally provides Exit qualification.
13399 *
13400 * Since Exit qualification is 0 for all VM-exits where it is not
13401 * applicable, reading and passing it to the guest should produce
13402 * defined behavior.
13403 *
13404 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
13405 */
13406 case VMX_EXIT_INVEPT: /* Unconditional. */
13407 case VMX_EXIT_INVVPID:
13408 case VMX_EXIT_VMCLEAR:
13409 case VMX_EXIT_VMPTRLD:
13410 case VMX_EXIT_VMPTRST:
13411 case VMX_EXIT_VMXON:
13412 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by guest hypervisor. */
13413 case VMX_EXIT_LDTR_TR_ACCESS:
13414 case VMX_EXIT_RDRAND:
13415 case VMX_EXIT_RDSEED:
13416 case VMX_EXIT_XSAVES:
13417 case VMX_EXIT_XRSTORS:
13418 case VMX_EXIT_UMWAIT:
13419 case VMX_EXIT_TPAUSE:
13420 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
13421
13422 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
13423 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
13424 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
13425 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
13426 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
13427 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
13428 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
13429 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
13430 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
13431 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
13432 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
13433 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
13434 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
13435 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
13436 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
13437 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
13438 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
13439 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
13440 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
13441
13442 case VMX_EXIT_PREEMPT_TIMER:
13443 {
13444 /** @todo NSTVMX: Preempt timer. */
13445 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
13446 }
13447
13448 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
13449 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
13450
13451 case VMX_EXIT_VMREAD:
13452 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
13453
13454 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
13455 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
13456
13457 case VMX_EXIT_INIT_SIGNAL:
13458 case VMX_EXIT_SIPI:
13459 case VMX_EXIT_IO_SMI:
13460 case VMX_EXIT_SMI:
13461 case VMX_EXIT_ERR_MSR_LOAD:
13462 case VMX_EXIT_ERR_MACHINE_CHECK:
13463 case VMX_EXIT_PML_FULL:
13464 case VMX_EXIT_RSM:
13465 default:
13466 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13467 }
13468}
13469#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13470
13471
13472/** @name VM-exit helpers.
13473 * @{
13474 */
13475/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13476/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
13477/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13478
13479/** Macro for VM-exits called unexpectedly. */
13480#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
13481 do { \
13482 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
13483 return VERR_VMX_UNEXPECTED_EXIT; \
13484 } while (0)
13485
13486#ifdef VBOX_STRICT
13487/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
13488# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
13489 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
13490
13491# define HMVMX_ASSERT_PREEMPT_CPUID() \
13492 do { \
13493 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
13494 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
13495 } while (0)
13496
13497# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13498 do { \
13499 AssertPtr((a_pVCpu)); \
13500 AssertPtr((a_pVmxTransient)); \
13501 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
13502 Assert((a_pVmxTransient)->pVmcsInfo); \
13503 Assert(ASMIntAreEnabled()); \
13504 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13505 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
13506 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
13507 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13508 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
13509 HMVMX_ASSERT_PREEMPT_CPUID(); \
13510 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13511 } while (0)
13512
13513# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13514 do { \
13515 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
13516 Assert((a_pVmxTransient)->fIsNestedGuest); \
13517 } while (0)
13518
13519# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13520 do { \
13521 Log4Func(("\n")); \
13522 } while (0)
13523#else
13524# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13525 do { \
13526 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13527 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
13528 } while (0)
13529
13530# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13531 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
13532
13533# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
13534#endif
13535
13536#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13537/** Macro that does the necessary privilege checks and intercepted VM-exits for
13538 * guests that attempted to execute a VMX instruction. */
13539# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
13540 do \
13541 { \
13542 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
13543 if (rcStrictTmp == VINF_SUCCESS) \
13544 { /* likely */ } \
13545 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13546 { \
13547 Assert((a_pVCpu)->hm.s.Event.fPending); \
13548 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
13549 return VINF_SUCCESS; \
13550 } \
13551 else \
13552 { \
13553 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
13554 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
13555 } \
13556 } while (0)
13557
13558/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
13559# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
13560 do \
13561 { \
13562 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
13563 (a_pGCPtrEffAddr)); \
13564 if (rcStrictTmp == VINF_SUCCESS) \
13565 { /* likely */ } \
13566 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13567 { \
13568 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
13569 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
13570 NOREF(uXcptTmp); \
13571 return VINF_SUCCESS; \
13572 } \
13573 else \
13574 { \
13575 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
13576 return rcStrictTmp; \
13577 } \
13578 } while (0)
13579#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13580
13581
13582/**
13583 * Advances the guest RIP by the specified number of bytes.
13584 *
13585 * @param pVCpu The cross context virtual CPU structure.
13586 * @param cbInstr Number of bytes to advance the RIP by.
13587 *
13588 * @remarks No-long-jump zone!!!
13589 */
13590DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPU pVCpu, uint32_t cbInstr)
13591{
13592 /* Advance the RIP. */
13593 pVCpu->cpum.GstCtx.rip += cbInstr;
13594 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
13595
13596 /* Update interrupt inhibition. */
13597 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
13598 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
13599 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
13600}
13601
13602
13603/**
13604 * Advances the guest RIP after reading it from the VMCS.
13605 *
13606 * @returns VBox status code, no informational status codes.
13607 * @param pVCpu The cross context virtual CPU structure.
13608 * @param pVmxTransient The VMX-transient structure.
13609 *
13610 * @remarks No-long-jump zone!!!
13611 */
13612static int hmR0VmxAdvanceGuestRip(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13613{
13614 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13615 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
13616 AssertRCReturn(rc, rc);
13617
13618 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbInstr);
13619 return VINF_SUCCESS;
13620}
13621
13622
13623/**
13624 * Handle a condition that occurred while delivering an event through the guest or
13625 * nested-guest IDT.
13626 *
13627 * @returns Strict VBox status code (i.e. informational status codes too).
13628 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13629 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
13630 * to continue execution of the guest which will delivery the \#DF.
13631 * @retval VINF_EM_RESET if we detected a triple-fault condition.
13632 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
13633 *
13634 * @param pVCpu The cross context virtual CPU structure.
13635 * @param pVmxTransient The VMX-transient structure.
13636 *
13637 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13638 * Additionally, HMVMX_READ_EXIT_QUALIFICATION is required if the VM-exit
13639 * is due to an EPT violation, PML full or SPP-related event.
13640 *
13641 * @remarks No-long-jump zone!!!
13642 */
13643static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13644{
13645 Assert(!pVCpu->hm.s.Event.fPending);
13646 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
13647 if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13648 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13649 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13650 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_EXIT_QUALIFICATION);
13651
13652 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
13653 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13654 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
13655 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
13656 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
13657 {
13658 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
13659 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
13660
13661 /*
13662 * If the event was a software interrupt (generated with INT n) or a software exception
13663 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
13664 * can handle the VM-exit and continue guest execution which will re-execute the
13665 * instruction rather than re-injecting the exception, as that can cause premature
13666 * trips to ring-3 before injection and involve TRPM which currently has no way of
13667 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
13668 * the problem).
13669 */
13670 IEMXCPTRAISE enmRaise;
13671 IEMXCPTRAISEINFO fRaiseInfo;
13672 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
13673 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
13674 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
13675 {
13676 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
13677 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13678 }
13679 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
13680 {
13681 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
13682 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
13683 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
13684
13685 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
13686 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
13687
13688 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
13689
13690 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
13691 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
13692 {
13693 pVmxTransient->fVectoringPF = true;
13694 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13695 }
13696 }
13697 else
13698 {
13699 /*
13700 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
13701 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
13702 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
13703 */
13704 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
13705 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13706 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
13707 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13708 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13709 }
13710
13711 /*
13712 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
13713 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
13714 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
13715 * subsequent VM-entry would fail, see @bugref{7445}.
13716 *
13717 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
13718 */
13719 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13720 && enmRaise == IEMXCPTRAISE_PREV_EVENT
13721 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13722 && CPUMIsGuestNmiBlocking(pVCpu))
13723 {
13724 CPUMSetGuestNmiBlocking(pVCpu, false);
13725 }
13726
13727 switch (enmRaise)
13728 {
13729 case IEMXCPTRAISE_CURRENT_XCPT:
13730 {
13731 Log4Func(("IDT: Pending secondary Xcpt: idtinfo=%#RX64 exitinfo=%#RX64\n", uIdtVectorInfo, uExitIntInfo));
13732 Assert(rcStrict == VINF_SUCCESS);
13733 break;
13734 }
13735
13736 case IEMXCPTRAISE_PREV_EVENT:
13737 {
13738 uint32_t u32ErrCode;
13739 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
13740 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
13741 else
13742 u32ErrCode = 0;
13743
13744 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
13745 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
13746 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
13747 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
13748
13749 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
13750 pVCpu->hm.s.Event.u32ErrCode));
13751 Assert(rcStrict == VINF_SUCCESS);
13752 break;
13753 }
13754
13755 case IEMXCPTRAISE_REEXEC_INSTR:
13756 Assert(rcStrict == VINF_SUCCESS);
13757 break;
13758
13759 case IEMXCPTRAISE_DOUBLE_FAULT:
13760 {
13761 /*
13762 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
13763 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
13764 */
13765 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
13766 {
13767 pVmxTransient->fVectoringDoublePF = true;
13768 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
13769 pVCpu->cpum.GstCtx.cr2));
13770 rcStrict = VINF_SUCCESS;
13771 }
13772 else
13773 {
13774 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
13775 hmR0VmxSetPendingXcptDF(pVCpu);
13776 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
13777 uIdtVector, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13778 rcStrict = VINF_HM_DOUBLE_FAULT;
13779 }
13780 break;
13781 }
13782
13783 case IEMXCPTRAISE_TRIPLE_FAULT:
13784 {
13785 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector,
13786 VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13787 rcStrict = VINF_EM_RESET;
13788 break;
13789 }
13790
13791 case IEMXCPTRAISE_CPU_HANG:
13792 {
13793 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13794 rcStrict = VERR_EM_GUEST_CPU_HANG;
13795 break;
13796 }
13797
13798 default:
13799 {
13800 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
13801 rcStrict = VERR_VMX_IPE_2;
13802 break;
13803 }
13804 }
13805 }
13806 else if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13807 && !CPUMIsGuestNmiBlocking(pVCpu))
13808 {
13809 if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
13810 && VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo) != X86_XCPT_DF
13811 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo))
13812 {
13813 /*
13814 * Execution of IRET caused a fault when NMI blocking was in effect (i.e we're in
13815 * the guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13816 * that NMIs remain blocked until the IRET execution is completed.
13817 *
13818 * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
13819 */
13820 CPUMSetGuestNmiBlocking(pVCpu, true);
13821 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13822 }
13823 else if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13824 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13825 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13826 {
13827 /*
13828 * Execution of IRET caused an EPT violation, page-modification log-full event or
13829 * SPP-related event VM-exit when NMI blocking was in effect (i.e. we're in the
13830 * guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13831 * that NMIs remain blocked until the IRET execution is completed.
13832 *
13833 * See Intel spec. 27.2.3 "Information about NMI unblocking due to IRET"
13834 */
13835 if (VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitQual))
13836 {
13837 CPUMSetGuestNmiBlocking(pVCpu, true);
13838 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13839 }
13840 }
13841 }
13842
13843 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13844 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13845 return rcStrict;
13846}
13847
13848
13849#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13850/**
13851 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13852 * guest attempting to execute a VMX instruction.
13853 *
13854 * @returns Strict VBox status code (i.e. informational status codes too).
13855 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13856 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13857 *
13858 * @param pVCpu The cross context virtual CPU structure.
13859 * @param uExitReason The VM-exit reason.
13860 *
13861 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13862 * @remarks No-long-jump zone!!!
13863 */
13864static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPU pVCpu, uint32_t uExitReason)
13865{
13866 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13867 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13868
13869 /*
13870 * The physical CPU would have already checked the CPU mode/code segment.
13871 * We shall just assert here for paranoia.
13872 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13873 */
13874 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13875 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13876 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13877
13878 if (uExitReason == VMX_EXIT_VMXON)
13879 {
13880 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13881
13882 /*
13883 * We check CR4.VMXE because it is required to be always set while in VMX operation
13884 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13885 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13886 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13887 */
13888 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13889 {
13890 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13891 hmR0VmxSetPendingXcptUD(pVCpu);
13892 return VINF_HM_PENDING_XCPT;
13893 }
13894 }
13895 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13896 {
13897 /*
13898 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13899 * (other than VMXON), we need to raise a #UD.
13900 */
13901 Log4Func(("Not in VMX root mode -> #UD\n"));
13902 hmR0VmxSetPendingXcptUD(pVCpu);
13903 return VINF_HM_PENDING_XCPT;
13904 }
13905
13906 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13907 return VINF_SUCCESS;
13908}
13909
13910/**
13911 * Decodes the memory operand of an instruction that caused a VM-exit.
13912 *
13913 * The Exit qualification field provides the displacement field for memory
13914 * operand instructions, if any.
13915 *
13916 * @returns Strict VBox status code (i.e. informational status codes too).
13917 * @retval VINF_SUCCESS if the operand was successfully decoded.
13918 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
13919 * operand.
13920 * @param pVCpu The cross context virtual CPU structure.
13921 * @param uExitInstrInfo The VM-exit instruction information field.
13922 * @param enmMemAccess The memory operand's access type (read or write).
13923 * @param GCPtrDisp The instruction displacement field, if any. For
13924 * RIP-relative addressing pass RIP + displacement here.
13925 * @param pGCPtrMem Where to store the effective destination memory address.
13926 *
13927 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
13928 * virtual-8086 mode hence skips those checks while verifying if the
13929 * segment is valid.
13930 */
13931static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPU pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
13932 PRTGCPTR pGCPtrMem)
13933{
13934 Assert(pGCPtrMem);
13935 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
13936 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
13937 | CPUMCTX_EXTRN_CR0);
13938
13939 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
13940 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
13941 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
13942
13943 VMXEXITINSTRINFO ExitInstrInfo;
13944 ExitInstrInfo.u = uExitInstrInfo;
13945 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
13946 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
13947 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
13948 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
13949 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
13950 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
13951 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
13952 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
13953 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
13954
13955 /*
13956 * Validate instruction information.
13957 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
13958 */
13959 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
13960 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
13961 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
13962 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
13963 AssertLogRelMsgReturn(fIsMemOperand,
13964 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
13965
13966 /*
13967 * Compute the complete effective address.
13968 *
13969 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
13970 * See AMD spec. 4.5.2 "Segment Registers".
13971 */
13972 RTGCPTR GCPtrMem = GCPtrDisp;
13973 if (fBaseRegValid)
13974 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
13975 if (fIdxRegValid)
13976 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
13977
13978 RTGCPTR const GCPtrOff = GCPtrMem;
13979 if ( !fIsLongMode
13980 || iSegReg >= X86_SREG_FS)
13981 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
13982 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
13983
13984 /*
13985 * Validate effective address.
13986 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
13987 */
13988 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
13989 Assert(cbAccess > 0);
13990 if (fIsLongMode)
13991 {
13992 if (X86_IS_CANONICAL(GCPtrMem))
13993 {
13994 *pGCPtrMem = GCPtrMem;
13995 return VINF_SUCCESS;
13996 }
13997
13998 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
13999 * "Data Limit Checks in 64-bit Mode". */
14000 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
14001 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14002 return VINF_HM_PENDING_XCPT;
14003 }
14004
14005 /*
14006 * This is a watered down version of iemMemApplySegment().
14007 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
14008 * and segment CPL/DPL checks are skipped.
14009 */
14010 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
14011 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
14012 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
14013
14014 /* Check if the segment is present and usable. */
14015 if ( pSel->Attr.n.u1Present
14016 && !pSel->Attr.n.u1Unusable)
14017 {
14018 Assert(pSel->Attr.n.u1DescType);
14019 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
14020 {
14021 /* Check permissions for the data segment. */
14022 if ( enmMemAccess == VMXMEMACCESS_WRITE
14023 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
14024 {
14025 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
14026 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
14027 return VINF_HM_PENDING_XCPT;
14028 }
14029
14030 /* Check limits if it's a normal data segment. */
14031 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
14032 {
14033 if ( GCPtrFirst32 > pSel->u32Limit
14034 || GCPtrLast32 > pSel->u32Limit)
14035 {
14036 Log4Func(("Data segment limit exceeded. "
14037 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
14038 GCPtrLast32, pSel->u32Limit));
14039 if (iSegReg == X86_SREG_SS)
14040 hmR0VmxSetPendingXcptSS(pVCpu, 0);
14041 else
14042 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14043 return VINF_HM_PENDING_XCPT;
14044 }
14045 }
14046 else
14047 {
14048 /* Check limits if it's an expand-down data segment.
14049 Note! The upper boundary is defined by the B bit, not the G bit! */
14050 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
14051 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
14052 {
14053 Log4Func(("Expand-down data segment limit exceeded. "
14054 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
14055 GCPtrLast32, pSel->u32Limit));
14056 if (iSegReg == X86_SREG_SS)
14057 hmR0VmxSetPendingXcptSS(pVCpu, 0);
14058 else
14059 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14060 return VINF_HM_PENDING_XCPT;
14061 }
14062 }
14063 }
14064 else
14065 {
14066 /* Check permissions for the code segment. */
14067 if ( enmMemAccess == VMXMEMACCESS_WRITE
14068 || ( enmMemAccess == VMXMEMACCESS_READ
14069 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
14070 {
14071 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
14072 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
14073 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14074 return VINF_HM_PENDING_XCPT;
14075 }
14076
14077 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
14078 if ( GCPtrFirst32 > pSel->u32Limit
14079 || GCPtrLast32 > pSel->u32Limit)
14080 {
14081 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
14082 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
14083 if (iSegReg == X86_SREG_SS)
14084 hmR0VmxSetPendingXcptSS(pVCpu, 0);
14085 else
14086 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14087 return VINF_HM_PENDING_XCPT;
14088 }
14089 }
14090 }
14091 else
14092 {
14093 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
14094 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14095 return VINF_HM_PENDING_XCPT;
14096 }
14097
14098 *pGCPtrMem = GCPtrMem;
14099 return VINF_SUCCESS;
14100}
14101#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
14102
14103
14104/**
14105 * VM-exit helper for LMSW.
14106 */
14107static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
14108{
14109 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14110 AssertRCReturn(rc, rc);
14111
14112 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
14113 AssertMsg( rcStrict == VINF_SUCCESS
14114 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14115
14116 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
14117 if (rcStrict == VINF_IEM_RAISED_XCPT)
14118 {
14119 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14120 rcStrict = VINF_SUCCESS;
14121 }
14122
14123 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
14124 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14125 return rcStrict;
14126}
14127
14128
14129/**
14130 * VM-exit helper for CLTS.
14131 */
14132static VBOXSTRICTRC hmR0VmxExitClts(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
14133{
14134 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14135 AssertRCReturn(rc, rc);
14136
14137 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
14138 AssertMsg( rcStrict == VINF_SUCCESS
14139 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14140
14141 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
14142 if (rcStrict == VINF_IEM_RAISED_XCPT)
14143 {
14144 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14145 rcStrict = VINF_SUCCESS;
14146 }
14147
14148 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
14149 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14150 return rcStrict;
14151}
14152
14153
14154/**
14155 * VM-exit helper for MOV from CRx (CRx read).
14156 */
14157static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
14158{
14159 Assert(iCrReg < 16);
14160 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
14161
14162 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14163 AssertRCReturn(rc, rc);
14164
14165 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
14166 AssertMsg( rcStrict == VINF_SUCCESS
14167 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14168
14169 if (iGReg == X86_GREG_xSP)
14170 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
14171 else
14172 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14173#ifdef VBOX_WITH_STATISTICS
14174 switch (iCrReg)
14175 {
14176 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
14177 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
14178 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
14179 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
14180 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
14181 }
14182#endif
14183 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
14184 return rcStrict;
14185}
14186
14187
14188/**
14189 * VM-exit helper for MOV to CRx (CRx write).
14190 */
14191static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
14192{
14193 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14194 AssertRCReturn(rc, rc);
14195
14196 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
14197 AssertMsg( rcStrict == VINF_SUCCESS
14198 || rcStrict == VINF_IEM_RAISED_XCPT
14199 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14200
14201 switch (iCrReg)
14202 {
14203 case 0:
14204 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
14205 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
14206 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
14207 break;
14208
14209 case 2:
14210 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
14211 /* Nothing to do here, CR2 it's not part of the VMCS. */
14212 break;
14213
14214 case 3:
14215 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
14216 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
14217 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
14218 break;
14219
14220 case 4:
14221 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
14222 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
14223 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
14224 pVCpu->cpum.GstCtx.cr4, pVCpu->hm.s.fLoadSaveGuestXcr0));
14225 break;
14226
14227 case 8:
14228 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
14229 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
14230 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
14231 break;
14232
14233 default:
14234 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
14235 break;
14236 }
14237
14238 if (rcStrict == VINF_IEM_RAISED_XCPT)
14239 {
14240 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14241 rcStrict = VINF_SUCCESS;
14242 }
14243 return rcStrict;
14244}
14245
14246
14247/**
14248 * VM-exit exception handler for \#PF (Page-fault exception).
14249 *
14250 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14251 */
14252static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14253{
14254 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14255 PVM pVM = pVCpu->CTX_SUFF(pVM);
14256 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
14257 AssertRCReturn(rc, rc);
14258
14259 if (!pVM->hm.s.fNestedPaging)
14260 { /* likely */ }
14261 else
14262 {
14263#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
14264 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hm.s.fUsingDebugLoop);
14265#endif
14266 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
14267 if (!pVmxTransient->fVectoringDoublePF)
14268 {
14269 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
14270 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
14271 }
14272 else
14273 {
14274 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
14275 Assert(!pVmxTransient->fIsNestedGuest);
14276 hmR0VmxSetPendingXcptDF(pVCpu);
14277 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
14278 }
14279 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
14280 return rc;
14281 }
14282
14283 Assert(!pVmxTransient->fIsNestedGuest);
14284
14285 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
14286 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
14287 if (pVmxTransient->fVectoringPF)
14288 {
14289 Assert(pVCpu->hm.s.Event.fPending);
14290 return VINF_EM_RAW_INJECT_TRPM_EVENT;
14291 }
14292
14293 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14294 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14295 AssertRCReturn(rc, rc);
14296
14297 Log4Func(("#PF: cr2=%#RX64 cs:rip=%#04x:%#RX64 uErrCode %#RX32 cr3=%#RX64\n", pVmxTransient->uExitQual, pCtx->cs.Sel,
14298 pCtx->rip, pVmxTransient->uExitIntErrorCode, pCtx->cr3));
14299
14300 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
14301 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
14302
14303 Log4Func(("#PF: rc=%Rrc\n", rc));
14304 if (rc == VINF_SUCCESS)
14305 {
14306 /*
14307 * This is typically a shadow page table sync or a MMIO instruction. But we may have
14308 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
14309 */
14310 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14311 TRPMResetTrap(pVCpu);
14312 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
14313 return rc;
14314 }
14315
14316 if (rc == VINF_EM_RAW_GUEST_TRAP)
14317 {
14318 if (!pVmxTransient->fVectoringDoublePF)
14319 {
14320 /* It's a guest page fault and needs to be reflected to the guest. */
14321 uint32_t uGstErrorCode = TRPMGetErrorCode(pVCpu);
14322 TRPMResetTrap(pVCpu);
14323 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
14324 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
14325 uGstErrorCode, pVmxTransient->uExitQual);
14326 }
14327 else
14328 {
14329 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
14330 TRPMResetTrap(pVCpu);
14331 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
14332 hmR0VmxSetPendingXcptDF(pVCpu);
14333 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
14334 }
14335
14336 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
14337 return VINF_SUCCESS;
14338 }
14339
14340 TRPMResetTrap(pVCpu);
14341 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
14342 return rc;
14343}
14344
14345
14346/**
14347 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
14348 *
14349 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14350 */
14351static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14352{
14353 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14354 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
14355
14356 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
14357 AssertRCReturn(rc, rc);
14358
14359 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
14360 {
14361 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
14362 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
14363
14364 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
14365 * provides VM-exit instruction length. If this causes problem later,
14366 * disassemble the instruction like it's done on AMD-V. */
14367 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14368 AssertRCReturn(rc2, rc2);
14369 return rc;
14370 }
14371
14372 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14373 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14374 return VINF_SUCCESS;
14375}
14376
14377
14378/**
14379 * VM-exit exception handler for \#BP (Breakpoint exception).
14380 *
14381 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14382 */
14383static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14384{
14385 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14386 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
14387
14388 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14389 AssertRCReturn(rc, rc);
14390
14391 if (!pVmxTransient->fIsNestedGuest)
14392 rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
14393 else
14394 rc = VINF_EM_RAW_GUEST_TRAP;
14395 if (rc == VINF_EM_RAW_GUEST_TRAP)
14396 {
14397 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14398 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14399 }
14400
14401 Assert(rc == VINF_SUCCESS || rc == VINF_EM_RAW_GUEST_TRAP || rc == VINF_EM_DBG_BREAKPOINT);
14402 return rc;
14403}
14404
14405
14406/**
14407 * VM-exit exception handler for \#AC (Alignment-check exception).
14408 *
14409 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14410 */
14411static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14412{
14413 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14414 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
14415
14416 /* Re-inject it. We'll detect any nesting before getting here. */
14417 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14418 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14419 return VINF_SUCCESS;
14420}
14421
14422
14423/**
14424 * VM-exit exception handler for \#DB (Debug exception).
14425 *
14426 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14427 */
14428static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14429{
14430 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14431 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
14432
14433 /*
14434 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
14435 */
14436 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
14437 AssertRCReturn(rc, rc);
14438
14439 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
14440 uint64_t const uDR6 = X86_DR6_INIT_VAL
14441 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
14442 | X86_DR6_BD | X86_DR6_BS));
14443
14444 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14445 if (!pVmxTransient->fIsNestedGuest)
14446 rc = DBGFRZTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
14447 else
14448 rc = VINF_EM_RAW_GUEST_TRAP;
14449 Log6Func(("rc=%Rrc\n", rc));
14450 if (rc == VINF_EM_RAW_GUEST_TRAP)
14451 {
14452 /*
14453 * The exception was for the guest. Update DR6, DR7.GD and
14454 * IA32_DEBUGCTL.LBR before forwarding it.
14455 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
14456 */
14457 VMMRZCallRing3Disable(pVCpu);
14458 HM_DISABLE_PREEMPT(pVCpu);
14459
14460 pCtx->dr[6] &= ~X86_DR6_B_MASK;
14461 pCtx->dr[6] |= uDR6;
14462 if (CPUMIsGuestDebugStateActive(pVCpu))
14463 ASMSetDR6(pCtx->dr[6]);
14464
14465 HM_RESTORE_PREEMPT();
14466 VMMRZCallRing3Enable(pVCpu);
14467
14468 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
14469 AssertRCReturn(rc, rc);
14470
14471 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
14472 pCtx->dr[7] &= ~X86_DR7_GD;
14473
14474 /* Paranoia. */
14475 pCtx->dr[7] &= ~X86_DR7_RAZ_MASK;
14476 pCtx->dr[7] |= X86_DR7_RA1_MASK;
14477
14478 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_DR7, (uint32_t)pCtx->dr[7]);
14479 AssertRCReturn(rc, rc);
14480
14481 /*
14482 * Raise #DB in the guest.
14483 *
14484 * It is important to reflect exactly what the VM-exit gave us (preserving the
14485 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
14486 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
14487 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
14488 *
14489 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
14490 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
14491 */
14492 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14493 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14494 return VINF_SUCCESS;
14495 }
14496
14497 /*
14498 * Not a guest trap, must be a hypervisor related debug event then.
14499 * Update DR6 in case someone is interested in it.
14500 */
14501 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
14502 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
14503 CPUMSetHyperDR6(pVCpu, uDR6);
14504
14505 return rc;
14506}
14507
14508
14509/**
14510 * Hacks its way around the lovely mesa driver's backdoor accesses.
14511 *
14512 * @sa hmR0SvmHandleMesaDrvGp.
14513 */
14514static int hmR0VmxHandleMesaDrvGp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14515{
14516 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
14517 RT_NOREF(pCtx);
14518
14519 /* For now we'll just skip the instruction. */
14520 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14521}
14522
14523
14524/**
14525 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
14526 * backdoor logging w/o checking what it is running inside.
14527 *
14528 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
14529 * backdoor port and magic numbers loaded in registers.
14530 *
14531 * @returns true if it is, false if it isn't.
14532 * @sa hmR0SvmIsMesaDrvGp.
14533 */
14534DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14535{
14536 /* 0xed: IN eAX,dx */
14537 uint8_t abInstr[1];
14538 if (pVmxTransient->cbInstr != sizeof(abInstr))
14539 return false;
14540
14541 /* Check that it is #GP(0). */
14542 if (pVmxTransient->uExitIntErrorCode != 0)
14543 return false;
14544
14545 /* Check magic and port. */
14546 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
14547 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
14548 if (pCtx->rax != UINT32_C(0x564d5868))
14549 return false;
14550 if (pCtx->dx != UINT32_C(0x5658))
14551 return false;
14552
14553 /* Flat ring-3 CS. */
14554 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
14555 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
14556 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
14557 if (pCtx->cs.Attr.n.u2Dpl != 3)
14558 return false;
14559 if (pCtx->cs.u64Base != 0)
14560 return false;
14561
14562 /* Check opcode. */
14563 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
14564 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
14565 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
14566 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
14567 if (RT_FAILURE(rc))
14568 return false;
14569 if (abInstr[0] != 0xed)
14570 return false;
14571
14572 return true;
14573}
14574
14575
14576/**
14577 * VM-exit exception handler for \#GP (General-protection exception).
14578 *
14579 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14580 */
14581static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14582{
14583 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14584 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
14585
14586 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14587 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14588 if (pVmcsInfo->RealMode.fRealOnV86Active)
14589 { /* likely */ }
14590 else
14591 {
14592#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14593 Assert(pVCpu->hm.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
14594#endif
14595 /*
14596 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
14597 * executing a nested-guest, reflect #GP to the guest or nested-guest.
14598 */
14599 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14600 AssertRCReturn(rc, rc);
14601 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
14602 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
14603
14604 if ( pVmxTransient->fIsNestedGuest
14605 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
14606 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
14607 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14608 pVmxTransient->cbInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14609 else
14610 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
14611 return rc;
14612 }
14613
14614 Assert(CPUMIsGuestInRealModeEx(pCtx));
14615 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest);
14616 Assert(!pVmxTransient->fIsNestedGuest);
14617
14618 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14619 AssertRCReturn(rc, rc);
14620
14621 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
14622 if (rcStrict == VINF_SUCCESS)
14623 {
14624 if (!CPUMIsGuestInRealModeEx(pCtx))
14625 {
14626 /*
14627 * The guest is no longer in real-mode, check if we can continue executing the
14628 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
14629 */
14630 pVmcsInfo->RealMode.fRealOnV86Active = false;
14631 if (HMCanExecuteVmxGuest(pVCpu, pCtx))
14632 {
14633 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
14634 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14635 }
14636 else
14637 {
14638 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
14639 rcStrict = VINF_EM_RESCHEDULE;
14640 }
14641 }
14642 else
14643 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14644 }
14645 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14646 {
14647 rcStrict = VINF_SUCCESS;
14648 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14649 }
14650 return VBOXSTRICTRC_VAL(rcStrict);
14651}
14652
14653
14654/**
14655 * VM-exit exception handler wrapper for all other exceptions that are not handled
14656 * by a specific handler.
14657 *
14658 * This simply re-injects the exception back into the VM without any special
14659 * processing.
14660 *
14661 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14662 */
14663static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14664{
14665 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14666
14667#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14668 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14669 AssertMsg(pVCpu->hm.s.fUsingDebugLoop || pVmcsInfo->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
14670 ("uVector=%#x u32XcptBitmap=%#X32\n",
14671 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
14672 NOREF(pVmcsInfo);
14673#endif
14674
14675 /*
14676 * Re-inject the exception into the guest. This cannot be a double-fault condition which
14677 * would have been handled while checking exits due to event delivery.
14678 */
14679 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14680
14681#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14682 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
14683 AssertRCReturn(rc, rc);
14684 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
14685#endif
14686
14687#ifdef VBOX_WITH_STATISTICS
14688 switch (uVector)
14689 {
14690 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
14691 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
14692 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
14693 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14694 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
14695 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
14696 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14697 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
14698 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
14699 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
14700 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
14701 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
14702 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
14703 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
14704 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
14705 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
14706 default:
14707 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
14708 break;
14709 }
14710#endif
14711
14712 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
14713 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
14714 NOREF(uVector);
14715
14716 /* Re-inject the original exception into the guest. */
14717 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14718 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14719 return VINF_SUCCESS;
14720}
14721
14722
14723/**
14724 * VM-exit exception handler for all exceptions (except NMIs!).
14725 *
14726 * @remarks This may be called for both guests and nested-guests. Take care to not
14727 * make assumptions and avoid doing anything that is not relevant when
14728 * executing a nested-guest (e.g., Mesa driver hacks).
14729 */
14730static VBOXSTRICTRC hmR0VmxExitXcpt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14731{
14732 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
14733
14734 /*
14735 * If this VM-exit occurred while delivering an event through the guest IDT, take
14736 * action based on the return code and additional hints (e.g. for page-faults)
14737 * that will be updated in the VMX transient structure.
14738 */
14739 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14740 if (rcStrict == VINF_SUCCESS)
14741 {
14742 /*
14743 * If an exception caused a VM-exit due to delivery of an event, the original
14744 * event may have to be re-injected into the guest. We shall reinject it and
14745 * continue guest execution. However, page-fault is a complicated case and
14746 * needs additional processing done in hmR0VmxExitXcptPF().
14747 */
14748 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14749 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14750 if ( !pVCpu->hm.s.Event.fPending
14751 || uVector == X86_XCPT_PF)
14752 {
14753 switch (uVector)
14754 {
14755 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
14756 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
14757 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
14758 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
14759 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
14760 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
14761 default:
14762 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
14763 }
14764 }
14765 /* else: inject pending event before resuming guest execution. */
14766 }
14767 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
14768 {
14769 Assert(pVCpu->hm.s.Event.fPending);
14770 rcStrict = VINF_SUCCESS;
14771 }
14772
14773 return rcStrict;
14774}
14775/** @} */
14776
14777
14778/** @name VM-exit handlers.
14779 * @{
14780 */
14781/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14782/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14783/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14784
14785/**
14786 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
14787 */
14788HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14789{
14790 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14791 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
14792 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
14793 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
14794 return VINF_SUCCESS;
14795 return VINF_EM_RAW_INTERRUPT;
14796}
14797
14798
14799/**
14800 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
14801 * VM-exit.
14802 */
14803HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14804{
14805 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14806 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
14807
14808 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14809 AssertRCReturn(rc, rc);
14810
14811 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
14812 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14813 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14814
14815 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14816 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
14817 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
14818 NOREF(pVmcsInfo);
14819
14820 VBOXSTRICTRC rcStrict;
14821 switch (uExitIntType)
14822 {
14823 /*
14824 * Host physical NMIs:
14825 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
14826 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14827 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14828 *
14829 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14830 * See Intel spec. 27.5.5 "Updating Non-Register State".
14831 */
14832 case VMX_EXIT_INT_INFO_TYPE_NMI:
14833 {
14834 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14835 break;
14836 }
14837
14838 /*
14839 * Privileged software exceptions (#DB from ICEBP),
14840 * Software exceptions (#BP and #OF),
14841 * Hardware exceptions:
14842 * Process the required exceptions and resume guest execution if possible.
14843 */
14844 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14845 Assert(uVector == X86_XCPT_DB);
14846 RT_FALL_THRU();
14847 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14848 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14849 RT_FALL_THRU();
14850 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14851 {
14852 NOREF(uVector);
14853 rc = hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14854 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14855 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14856 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14857 AssertRCReturn(rc, rc);
14858
14859 rcStrict = hmR0VmxExitXcpt(pVCpu, pVmxTransient);
14860 break;
14861 }
14862
14863 default:
14864 {
14865 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14866 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14867 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14868 break;
14869 }
14870 }
14871
14872 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14873 return rcStrict;
14874}
14875
14876
14877/**
14878 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14879 */
14880HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14881{
14882 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14883
14884 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14885 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14886 int rc = hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14887 AssertRCReturn(rc, rc);
14888
14889 /* Evaluate and deliver pending events and resume guest execution. */
14890 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14891 return VINF_SUCCESS;
14892}
14893
14894
14895/**
14896 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14897 */
14898HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14899{
14900 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14901
14902 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14903 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14904 {
14905 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14906 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14907 }
14908
14909 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14910
14911 /*
14912 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14913 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14914 */
14915 uint32_t fIntrState;
14916 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
14917 AssertRCReturn(rc, rc);
14918 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
14919 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
14920 {
14921 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
14922 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
14923
14924 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
14925 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
14926 AssertRCReturn(rc, rc);
14927 }
14928
14929 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
14930 rc = hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
14931 AssertRCReturn(rc, rc);
14932
14933 /* Evaluate and deliver pending events and resume guest execution. */
14934 return VINF_SUCCESS;
14935}
14936
14937
14938/**
14939 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
14940 */
14941HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14942{
14943 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14944 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14945}
14946
14947
14948/**
14949 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
14950 */
14951HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14952{
14953 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14954 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14955}
14956
14957
14958/**
14959 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
14960 */
14961HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14962{
14963 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14964
14965 /*
14966 * Get the state we need and update the exit history entry.
14967 */
14968 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14969 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14970 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14971 AssertRCReturn(rc, rc);
14972
14973 VBOXSTRICTRC rcStrict;
14974 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14975 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
14976 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14977 if (!pExitRec)
14978 {
14979 /*
14980 * Regular CPUID instruction execution.
14981 */
14982 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbInstr);
14983 if (rcStrict == VINF_SUCCESS)
14984 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14985 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14986 {
14987 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14988 rcStrict = VINF_SUCCESS;
14989 }
14990 }
14991 else
14992 {
14993 /*
14994 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14995 */
14996 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14997 AssertRCReturn(rc2, rc2);
14998
14999 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
15000 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
15001
15002 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15003 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15004
15005 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15006 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15007 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15008 }
15009 return rcStrict;
15010}
15011
15012
15013/**
15014 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
15015 */
15016HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15017{
15018 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15019
15020 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15021 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
15022 AssertRCReturn(rc, rc);
15023
15024 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
15025 return VINF_EM_RAW_EMULATE_INSTR;
15026
15027 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
15028 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15029}
15030
15031
15032/**
15033 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
15034 */
15035HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15036{
15037 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15038
15039 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15040 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15041 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15042 AssertRCReturn(rc, rc);
15043
15044 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbInstr);
15045 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15046 {
15047 /* If we get a spurious VM-exit when TSC offsetting is enabled,
15048 we must reset offsetting on VM-entry. See @bugref{6634}. */
15049 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
15050 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15051 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15052 }
15053 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15054 {
15055 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15056 rcStrict = VINF_SUCCESS;
15057 }
15058 return rcStrict;
15059}
15060
15061
15062/**
15063 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
15064 */
15065HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15066{
15067 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15068
15069 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15070 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
15071 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15072 AssertRCReturn(rc, rc);
15073
15074 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbInstr);
15075 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15076 {
15077 /* If we get a spurious VM-exit when TSC offsetting is enabled,
15078 we must reset offsetting on VM-reentry. See @bugref{6634}. */
15079 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
15080 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15081 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15082 }
15083 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15084 {
15085 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15086 rcStrict = VINF_SUCCESS;
15087 }
15088 return rcStrict;
15089}
15090
15091
15092/**
15093 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
15094 */
15095HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15096{
15097 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15098
15099 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15100 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
15101 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
15102 AssertRCReturn(rc, rc);
15103
15104 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15105 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
15106 if (RT_LIKELY(rc == VINF_SUCCESS))
15107 {
15108 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15109 Assert(pVmxTransient->cbInstr == 2);
15110 }
15111 else
15112 {
15113 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
15114 rc = VERR_EM_INTERPRETER;
15115 }
15116 return rc;
15117}
15118
15119
15120/**
15121 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
15122 */
15123HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15124{
15125 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15126
15127 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
15128 if (EMAreHypercallInstructionsEnabled(pVCpu))
15129 {
15130 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15131 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
15132 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
15133 AssertRCReturn(rc, rc);
15134
15135 /* Perform the hypercall. */
15136 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
15137 if (rcStrict == VINF_SUCCESS)
15138 {
15139 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15140 AssertRCReturn(rc, rc);
15141 }
15142 else
15143 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
15144 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
15145 || RT_FAILURE(rcStrict));
15146
15147 /* If the hypercall changes anything other than guest's general-purpose registers,
15148 we would need to reload the guest changed bits here before VM-entry. */
15149 }
15150 else
15151 Log4Func(("Hypercalls not enabled\n"));
15152
15153 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
15154 if (RT_FAILURE(rcStrict))
15155 {
15156 hmR0VmxSetPendingXcptUD(pVCpu);
15157 rcStrict = VINF_SUCCESS;
15158 }
15159
15160 return rcStrict;
15161}
15162
15163
15164/**
15165 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
15166 */
15167HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15168{
15169 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15170 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || pVCpu->hm.s.fUsingDebugLoop);
15171
15172 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15173 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15174 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15175 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15176 AssertRCReturn(rc, rc);
15177
15178 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbInstr, pVmxTransient->uExitQual);
15179
15180 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
15181 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15182 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15183 {
15184 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15185 rcStrict = VINF_SUCCESS;
15186 }
15187 else
15188 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
15189 VBOXSTRICTRC_VAL(rcStrict)));
15190 return rcStrict;
15191}
15192
15193
15194/**
15195 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
15196 */
15197HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15198{
15199 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15200
15201 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15202 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
15203 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15204 AssertRCReturn(rc, rc);
15205
15206 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbInstr);
15207 if (rcStrict == VINF_SUCCESS)
15208 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15209 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15210 {
15211 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15212 rcStrict = VINF_SUCCESS;
15213 }
15214
15215 return rcStrict;
15216}
15217
15218
15219/**
15220 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
15221 */
15222HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15223{
15224 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15225
15226 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15227 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
15228 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15229 AssertRCReturn(rc, rc);
15230
15231 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbInstr);
15232 if (RT_SUCCESS(rcStrict))
15233 {
15234 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15235 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
15236 rcStrict = VINF_SUCCESS;
15237 }
15238
15239 return rcStrict;
15240}
15241
15242
15243/**
15244 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
15245 * VM-exit.
15246 */
15247HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15248{
15249 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15250 return VINF_EM_RESET;
15251}
15252
15253
15254/**
15255 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
15256 */
15257HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15258{
15259 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15260
15261 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15262 AssertRCReturn(rc, rc);
15263
15264 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
15265 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
15266 rc = VINF_SUCCESS;
15267 else
15268 rc = VINF_EM_HALT;
15269
15270 if (rc != VINF_SUCCESS)
15271 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
15272 return rc;
15273}
15274
15275
15276/**
15277 * VM-exit handler for instructions that result in a \#UD exception delivered to
15278 * the guest.
15279 */
15280HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15281{
15282 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15283 hmR0VmxSetPendingXcptUD(pVCpu);
15284 return VINF_SUCCESS;
15285}
15286
15287
15288/**
15289 * VM-exit handler for expiry of the VMX-preemption timer.
15290 */
15291HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15292{
15293 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15294
15295 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
15296 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15297
15298 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
15299 PVM pVM = pVCpu->CTX_SUFF(pVM);
15300 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
15301 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
15302 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
15303}
15304
15305
15306/**
15307 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
15308 */
15309HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15310{
15311 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15312
15313 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15314 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15315 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
15316 AssertRCReturn(rc, rc);
15317
15318 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbInstr);
15319 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
15320 : HM_CHANGED_RAISED_XCPT_MASK);
15321
15322 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15323 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
15324
15325 return rcStrict;
15326}
15327
15328
15329/**
15330 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
15331 */
15332HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15333{
15334 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15335 /** @todo Use VM-exit instruction information. */
15336 return VERR_EM_INTERPRETER;
15337}
15338
15339
15340/**
15341 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
15342 * VM-exit.
15343 */
15344HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15345{
15346 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15347 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15348 AssertRCReturn(rc, rc);
15349
15350 rc = hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
15351 if (RT_FAILURE(rc))
15352 return rc;
15353
15354 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
15355 NOREF(uInvalidReason);
15356
15357#ifdef VBOX_STRICT
15358 uint32_t fIntrState;
15359 RTHCUINTREG uHCReg;
15360 uint64_t u64Val;
15361 uint32_t u32Val;
15362 rc = hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
15363 rc |= hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
15364 rc |= hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
15365 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
15366 AssertRCReturn(rc, rc);
15367
15368 Log4(("uInvalidReason %u\n", uInvalidReason));
15369 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
15370 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
15371 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
15372 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
15373
15374 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32Val); AssertRC(rc);
15375 Log4(("VMX_VMCS_GUEST_CR0 %#RX32\n", u32Val));
15376 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, &uHCReg); AssertRC(rc);
15377 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RHr\n", uHCReg));
15378 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, &uHCReg); AssertRC(rc);
15379 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
15380 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, &uHCReg); AssertRC(rc);
15381 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RHr\n", uHCReg));
15382 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_READ_SHADOW, &uHCReg); AssertRC(rc);
15383 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
15384 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
15385 {
15386 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
15387 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
15388 }
15389
15390 hmR0DumpRegs(pVCpu);
15391#endif
15392
15393 return VERR_VMX_INVALID_GUEST_STATE;
15394}
15395
15396/**
15397 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
15398 */
15399HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15400{
15401 /*
15402 * Cummulative notes of all recognized but unexpected VM-exits.
15403 *
15404 * 1. This does -not- cover scenarios like like a page-fault VM-exit occurring when
15405 * nested-paging is used.
15406 *
15407 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
15408 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
15409 * this function (and thereby stop VM execution) for handling such instructions.
15410 *
15411 *
15412 * VMX_EXIT_INIT_SIGNAL:
15413 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
15414 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
15415 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
15416 *
15417 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
15418 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
15419 * See Intel spec. "23.8 Restrictions on VMX operation".
15420 *
15421 * VMX_EXIT_SIPI:
15422 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
15423 * activity state is used. We don't make use of it as our guests don't have direct
15424 * access to the host local APIC.
15425 *
15426 * See Intel spec. 25.3 "Other Causes of VM-exits".
15427 *
15428 * VMX_EXIT_IO_SMI:
15429 * VMX_EXIT_SMI:
15430 * This can only happen if we support dual-monitor treatment of SMI, which can be
15431 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
15432 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
15433 * VMX root mode or receive an SMI. If we get here, something funny is going on.
15434 *
15435 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
15436 * See Intel spec. 25.3 "Other Causes of VM-Exits"
15437 *
15438 * VMX_EXIT_ERR_MSR_LOAD:
15439 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
15440 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
15441 * execution.
15442 *
15443 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
15444 *
15445 * VMX_EXIT_ERR_MACHINE_CHECK:
15446 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
15447 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
15448 * #MC exception abort class exception is raised. We thus cannot assume a
15449 * reasonable chance of continuing any sort of execution and we bail.
15450 *
15451 * See Intel spec. 15.1 "Machine-check Architecture".
15452 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
15453 *
15454 * VMX_EXIT_PML_FULL:
15455 * VMX_EXIT_VIRTUALIZED_EOI:
15456 * VMX_EXIT_APIC_WRITE:
15457 * We do not currently support any of these features and thus they are all unexpected
15458 * VM-exits.
15459 *
15460 * VMX_EXIT_GDTR_IDTR_ACCESS:
15461 * VMX_EXIT_LDTR_TR_ACCESS:
15462 * VMX_EXIT_RDRAND:
15463 * VMX_EXIT_RSM:
15464 * VMX_EXIT_VMFUNC:
15465 * VMX_EXIT_ENCLS:
15466 * VMX_EXIT_RDSEED:
15467 * VMX_EXIT_XSAVES:
15468 * VMX_EXIT_XRSTORS:
15469 * VMX_EXIT_UMWAIT:
15470 * VMX_EXIT_TPAUSE:
15471 * These VM-exits are -not- caused unconditionally by execution of the corresponding
15472 * instruction. Any VM-exit for these instructions indicate a hardware problem,
15473 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
15474 *
15475 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
15476 */
15477 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15478 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
15479 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15480}
15481
15482
15483/**
15484 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
15485 */
15486HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15487{
15488 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15489
15490 /** @todo Optimize this: We currently drag in in the whole MSR state
15491 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15492 * MSRs required. That would require changes to IEM and possibly CPUM too.
15493 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15494 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15495 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15496 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15497 switch (idMsr)
15498 {
15499 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15500 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15501 }
15502
15503 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15504 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15505 AssertRCReturn(rc, rc);
15506
15507 Log4Func(("ecx=%#RX32\n", idMsr));
15508
15509#ifdef VBOX_STRICT
15510 Assert(!pVmxTransient->fIsNestedGuest);
15511 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
15512 {
15513 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
15514 && idMsr != MSR_K6_EFER)
15515 {
15516 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
15517 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15518 }
15519 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15520 {
15521 Assert(pVmcsInfo->pvMsrBitmap);
15522 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15523 if (fMsrpm & VMXMSRPM_ALLOW_RD)
15524 {
15525 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
15526 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15527 }
15528 }
15529 }
15530#endif
15531
15532 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbInstr);
15533 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
15534 if (rcStrict == VINF_SUCCESS)
15535 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
15536 | HM_CHANGED_GUEST_RAX | HM_CHANGED_GUEST_RDX);
15537 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15538 {
15539 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15540 rcStrict = VINF_SUCCESS;
15541 }
15542 else
15543 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ, ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15544
15545 return rcStrict;
15546}
15547
15548
15549/**
15550 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
15551 */
15552HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15553{
15554 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15555
15556 /** @todo Optimize this: We currently drag in in the whole MSR state
15557 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15558 * MSRs required. That would require changes to IEM and possibly CPUM too.
15559 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15560 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15561 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15562
15563 /*
15564 * The FS and GS base MSRs are not part of the above all-MSRs mask.
15565 * Although we don't need to fetch the base as it will be overwritten shortly, while
15566 * loading guest-state we would also load the entire segment register including limit
15567 * and attributes and thus we need to load them here.
15568 */
15569 switch (idMsr)
15570 {
15571 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15572 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15573 }
15574
15575 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15576 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15577 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15578 AssertRCReturn(rc, rc);
15579
15580 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
15581
15582 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbInstr);
15583 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
15584
15585 if (rcStrict == VINF_SUCCESS)
15586 {
15587 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15588
15589 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
15590 if ( idMsr == MSR_IA32_APICBASE
15591 || ( idMsr >= MSR_IA32_X2APIC_START
15592 && idMsr <= MSR_IA32_X2APIC_END))
15593 {
15594 /*
15595 * We've already saved the APIC related guest-state (TPR) in post-run phase.
15596 * When full APIC register virtualization is implemented we'll have to make
15597 * sure APIC state is saved from the VMCS before IEM changes it.
15598 */
15599 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
15600 }
15601 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
15602 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15603 else if (idMsr == MSR_K6_EFER)
15604 {
15605 /*
15606 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
15607 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
15608 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
15609 */
15610 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
15611 }
15612
15613 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
15614 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
15615 {
15616 switch (idMsr)
15617 {
15618 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
15619 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
15620 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
15621 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
15622 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
15623 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
15624 default:
15625 {
15626 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15627 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
15628 else if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15629 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
15630 break;
15631 }
15632 }
15633 }
15634#ifdef VBOX_STRICT
15635 else
15636 {
15637 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
15638 switch (idMsr)
15639 {
15640 case MSR_IA32_SYSENTER_CS:
15641 case MSR_IA32_SYSENTER_EIP:
15642 case MSR_IA32_SYSENTER_ESP:
15643 case MSR_K8_FS_BASE:
15644 case MSR_K8_GS_BASE:
15645 {
15646 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
15647 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15648 }
15649
15650 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
15651 default:
15652 {
15653 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15654 {
15655 /* EFER MSR writes are always intercepted. */
15656 if (idMsr != MSR_K6_EFER)
15657 {
15658 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
15659 idMsr));
15660 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15661 }
15662 }
15663
15664 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15665 {
15666 Assert(pVmcsInfo->pvMsrBitmap);
15667 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15668 if (fMsrpm & VMXMSRPM_ALLOW_WR)
15669 {
15670 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
15671 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15672 }
15673 }
15674 break;
15675 }
15676 }
15677 }
15678#endif /* VBOX_STRICT */
15679 }
15680 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15681 {
15682 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15683 rcStrict = VINF_SUCCESS;
15684 }
15685 else
15686 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE, ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15687
15688 return rcStrict;
15689}
15690
15691
15692/**
15693 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
15694 */
15695HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15696{
15697 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15698
15699 /** @todo The guest has likely hit a contended spinlock. We might want to
15700 * poke a schedule different guest VCPU. */
15701 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15702 if (RT_SUCCESS(rc))
15703 return VINF_EM_RAW_INTERRUPT;
15704
15705 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
15706 return rc;
15707}
15708
15709
15710/**
15711 * VM-exit handler for when the TPR value is lowered below the specified
15712 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
15713 */
15714HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15715{
15716 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15717 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
15718
15719 /*
15720 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
15721 * We'll re-evaluate pending interrupts and inject them before the next VM
15722 * entry so we can just continue execution here.
15723 */
15724 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
15725 return VINF_SUCCESS;
15726}
15727
15728
15729/**
15730 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
15731 * VM-exit.
15732 *
15733 * @retval VINF_SUCCESS when guest execution can continue.
15734 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
15735 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
15736 * incompatible guest state for VMX execution (real-on-v86 case).
15737 */
15738HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15739{
15740 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15741 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
15742
15743 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15744 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15745 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15746 AssertRCReturn(rc, rc);
15747
15748 VBOXSTRICTRC rcStrict;
15749 PVM pVM = pVCpu->CTX_SUFF(pVM);
15750 uint64_t const uExitQual = pVmxTransient->uExitQual;
15751 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
15752 switch (uAccessType)
15753 {
15754 /*
15755 * MOV to CRx.
15756 */
15757 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
15758 {
15759 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15760 AssertRCReturn(rc, rc);
15761
15762 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
15763 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
15764 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15765 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15766
15767 /*
15768 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
15769 * - When nested paging isn't used.
15770 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
15771 * - We are executing in the VM debug loop.
15772 */
15773 Assert( iCrReg != 3
15774 || !pVM->hm.s.fNestedPaging
15775 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15776 || pVCpu->hm.s.fUsingDebugLoop);
15777
15778 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
15779 Assert( iCrReg != 8
15780 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15781
15782 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
15783 AssertMsg( rcStrict == VINF_SUCCESS
15784 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15785
15786 /*
15787 * This is a kludge for handling switches back to real mode when we try to use
15788 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
15789 * deal with special selector values, so we have to return to ring-3 and run
15790 * there till the selector values are V86 mode compatible.
15791 *
15792 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
15793 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
15794 * this function.
15795 */
15796 if ( iCrReg == 0
15797 && rcStrict == VINF_SUCCESS
15798 && !pVM->hm.s.vmx.fUnrestrictedGuest
15799 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
15800 && (uOldCr0 & X86_CR0_PE)
15801 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
15802 {
15803 /** @todo Check selectors rather than returning all the time. */
15804 Assert(!pVmxTransient->fIsNestedGuest);
15805 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
15806 rcStrict = VINF_EM_RESCHEDULE_REM;
15807 }
15808 break;
15809 }
15810
15811 /*
15812 * MOV from CRx.
15813 */
15814 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
15815 {
15816 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15817 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15818
15819 /*
15820 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
15821 * - When nested paging isn't used.
15822 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
15823 * - We are executing in the VM debug loop.
15824 */
15825 Assert( iCrReg != 3
15826 || !pVM->hm.s.fNestedPaging
15827 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15828 || pVCpu->hm.s.fUsingDebugLoop);
15829
15830 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
15831 Assert( iCrReg != 8
15832 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15833
15834 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
15835 break;
15836 }
15837
15838 /*
15839 * CLTS (Clear Task-Switch Flag in CR0).
15840 */
15841 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15842 {
15843 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbInstr);
15844 break;
15845 }
15846
15847 /*
15848 * LMSW (Load Machine-Status Word into CR0).
15849 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15850 */
15851 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15852 {
15853 RTGCPTR GCPtrEffDst;
15854 uint8_t const cbInstr = pVmxTransient->cbInstr;
15855 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15856 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15857 if (fMemOperand)
15858 {
15859 rc = hmR0VmxReadGuestLinearAddrVmcs(pVCpu, pVmxTransient);
15860 AssertRCReturn(rc, rc);
15861 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15862 }
15863 else
15864 GCPtrEffDst = NIL_RTGCPTR;
15865 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15866 break;
15867 }
15868
15869 default:
15870 {
15871 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15872 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15873 }
15874 }
15875
15876 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15877 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15878 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15879
15880 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15881 NOREF(pVM);
15882 return rcStrict;
15883}
15884
15885
15886/**
15887 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15888 * VM-exit.
15889 */
15890HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15891{
15892 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15893 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15894
15895 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15896 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15897 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15898 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15899 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15900 | CPUMCTX_EXTRN_EFER);
15901 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15902 AssertRCReturn(rc, rc);
15903
15904 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15905 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15906 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15907 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15908 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15909 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15910 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15911 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15912
15913 /*
15914 * Update exit history to see if this exit can be optimized.
15915 */
15916 VBOXSTRICTRC rcStrict;
15917 PCEMEXITREC pExitRec = NULL;
15918 if ( !fGstStepping
15919 && !fDbgStepping)
15920 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15921 !fIOString
15922 ? !fIOWrite
15923 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
15924 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
15925 : !fIOWrite
15926 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
15927 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
15928 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15929 if (!pExitRec)
15930 {
15931 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
15932 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
15933
15934 uint32_t const cbValue = s_aIOSizes[uIOSize];
15935 uint32_t const cbInstr = pVmxTransient->cbInstr;
15936 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
15937 PVM pVM = pVCpu->CTX_SUFF(pVM);
15938 if (fIOString)
15939 {
15940 /*
15941 * INS/OUTS - I/O String instruction.
15942 *
15943 * Use instruction-information if available, otherwise fall back on
15944 * interpreting the instruction.
15945 */
15946 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15947 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
15948 bool const fInsOutsInfo = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
15949 if (fInsOutsInfo)
15950 {
15951 int rc2 = hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15952 AssertRCReturn(rc2, rc2);
15953 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
15954 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
15955 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
15956 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
15957 if (fIOWrite)
15958 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
15959 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
15960 else
15961 {
15962 /*
15963 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
15964 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
15965 * See Intel Instruction spec. for "INS".
15966 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
15967 */
15968 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
15969 }
15970 }
15971 else
15972 rcStrict = IEMExecOne(pVCpu);
15973
15974 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15975 fUpdateRipAlready = true;
15976 }
15977 else
15978 {
15979 /*
15980 * IN/OUT - I/O instruction.
15981 */
15982 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15983 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
15984 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
15985 if (fIOWrite)
15986 {
15987 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
15988 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
15989 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15990 && !pCtx->eflags.Bits.u1TF)
15991 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
15992 }
15993 else
15994 {
15995 uint32_t u32Result = 0;
15996 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
15997 if (IOM_SUCCESS(rcStrict))
15998 {
15999 /* Save result of I/O IN instr. in AL/AX/EAX. */
16000 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
16001 }
16002 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
16003 && !pCtx->eflags.Bits.u1TF)
16004 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
16005 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
16006 }
16007 }
16008
16009 if (IOM_SUCCESS(rcStrict))
16010 {
16011 if (!fUpdateRipAlready)
16012 {
16013 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
16014 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
16015 }
16016
16017 /*
16018 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
16019 * while booting Fedora 17 64-bit guest.
16020 *
16021 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
16022 */
16023 if (fIOString)
16024 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
16025
16026 /*
16027 * If any I/O breakpoints are armed, we need to check if one triggered
16028 * and take appropriate action.
16029 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
16030 */
16031 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
16032 AssertRCReturn(rc, rc);
16033
16034 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
16035 * execution engines about whether hyper BPs and such are pending. */
16036 uint32_t const uDr7 = pCtx->dr[7];
16037 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
16038 && X86_DR7_ANY_RW_IO(uDr7)
16039 && (pCtx->cr4 & X86_CR4_DE))
16040 || DBGFBpIsHwIoArmed(pVM)))
16041 {
16042 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
16043
16044 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
16045 VMMRZCallRing3Disable(pVCpu);
16046 HM_DISABLE_PREEMPT(pVCpu);
16047
16048 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
16049
16050 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
16051 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
16052 {
16053 /* Raise #DB. */
16054 if (fIsGuestDbgActive)
16055 ASMSetDR6(pCtx->dr[6]);
16056 if (pCtx->dr[7] != uDr7)
16057 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
16058
16059 hmR0VmxSetPendingXcptDB(pVCpu);
16060 }
16061 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
16062 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
16063 else if ( rcStrict2 != VINF_SUCCESS
16064 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
16065 rcStrict = rcStrict2;
16066 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
16067
16068 HM_RESTORE_PREEMPT();
16069 VMMRZCallRing3Enable(pVCpu);
16070 }
16071 }
16072
16073#ifdef VBOX_STRICT
16074 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
16075 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
16076 Assert(!fIOWrite);
16077 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
16078 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
16079 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
16080 Assert(fIOWrite);
16081 else
16082 {
16083# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
16084 * statuses, that the VMM device and some others may return. See
16085 * IOM_SUCCESS() for guidance. */
16086 AssertMsg( RT_FAILURE(rcStrict)
16087 || rcStrict == VINF_SUCCESS
16088 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
16089 || rcStrict == VINF_EM_DBG_BREAKPOINT
16090 || rcStrict == VINF_EM_RAW_GUEST_TRAP
16091 || rcStrict == VINF_EM_RAW_TO_R3
16092 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16093# endif
16094 }
16095#endif
16096 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
16097 }
16098 else
16099 {
16100 /*
16101 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
16102 */
16103 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16104 AssertRCReturn(rc2, rc2);
16105 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
16106 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
16107 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
16108 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16109 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
16110 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
16111
16112 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
16113 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16114
16115 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
16116 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16117 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
16118 }
16119 return rcStrict;
16120}
16121
16122
16123/**
16124 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
16125 * VM-exit.
16126 */
16127HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16128{
16129 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16130
16131 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
16132 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16133 AssertRCReturn(rc, rc);
16134 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
16135 {
16136 rc = hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16137 AssertRCReturn(rc, rc);
16138 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16139 {
16140 uint32_t uErrCode;
16141 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
16142 {
16143 rc = hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16144 AssertRCReturn(rc, rc);
16145 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
16146 }
16147 else
16148 uErrCode = 0;
16149
16150 RTGCUINTPTR GCPtrFaultAddress;
16151 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
16152 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
16153 else
16154 GCPtrFaultAddress = 0;
16155
16156 rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16157 AssertRCReturn(rc, rc);
16158
16159 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
16160 pVmxTransient->cbInstr, uErrCode, GCPtrFaultAddress);
16161
16162 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
16163 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
16164 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
16165 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16166 }
16167 }
16168
16169 /* Fall back to the interpreter to emulate the task-switch. */
16170 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
16171 return VERR_EM_INTERPRETER;
16172}
16173
16174
16175/**
16176 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
16177 */
16178HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16179{
16180 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16181
16182 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16183 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
16184 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
16185 AssertRCReturn(rc, rc);
16186 return VINF_EM_DBG_STEPPED;
16187}
16188
16189
16190/**
16191 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
16192 */
16193HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16194{
16195 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16196 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
16197
16198 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16199 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16200 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16201 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16202 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16203 AssertRCReturn(rc, rc);
16204
16205 /*
16206 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16207 */
16208 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16209 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16210 {
16211 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
16212 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
16213 {
16214 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
16215 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16216 }
16217 }
16218 else
16219 {
16220 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16221 return rcStrict;
16222 }
16223
16224 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
16225 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16226 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16227 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16228 AssertRCReturn(rc, rc);
16229
16230 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
16231 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
16232 switch (uAccessType)
16233 {
16234 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
16235 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
16236 {
16237 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
16238 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
16239 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
16240
16241 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
16242 GCPhys &= PAGE_BASE_GC_MASK;
16243 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
16244 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
16245 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
16246
16247 PVM pVM = pVCpu->CTX_SUFF(pVM);
16248 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16249 rcStrict = IOMMMIOPhysHandler(pVM, pVCpu,
16250 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW,
16251 CPUMCTX2CORE(pCtx), GCPhys);
16252 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16253 if ( rcStrict == VINF_SUCCESS
16254 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16255 || rcStrict == VERR_PAGE_NOT_PRESENT)
16256 {
16257 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16258 | HM_CHANGED_GUEST_APIC_TPR);
16259 rcStrict = VINF_SUCCESS;
16260 }
16261 break;
16262 }
16263
16264 default:
16265 {
16266 Log4Func(("uAccessType=%#x\n", uAccessType));
16267 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
16268 break;
16269 }
16270 }
16271
16272 if (rcStrict != VINF_SUCCESS)
16273 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
16274 return rcStrict;
16275}
16276
16277
16278/**
16279 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
16280 * VM-exit.
16281 */
16282HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16283{
16284 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16285
16286 /* We should -not- get this VM-exit if the guest's debug registers were active. */
16287 if (pVmxTransient->fWasGuestDebugStateActive)
16288 {
16289 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
16290 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
16291 }
16292
16293 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16294 if ( !pVCpu->hm.s.fSingleInstruction
16295 && !pVmxTransient->fWasHyperDebugStateActive)
16296 {
16297 Assert(!DBGFIsStepping(pVCpu));
16298 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
16299
16300 /* Don't intercept MOV DRx any more. */
16301 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
16302 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
16303 AssertRCReturn(rc, rc);
16304
16305 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
16306 VMMRZCallRing3Disable(pVCpu);
16307 HM_DISABLE_PREEMPT(pVCpu);
16308
16309 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
16310 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
16311 Assert(CPUMIsGuestDebugStateActive(pVCpu) || HC_ARCH_BITS == 32);
16312
16313 HM_RESTORE_PREEMPT();
16314 VMMRZCallRing3Enable(pVCpu);
16315
16316#ifdef VBOX_WITH_STATISTICS
16317 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16318 AssertRCReturn(rc, rc);
16319 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16320 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16321 else
16322 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16323#endif
16324 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
16325 return VINF_SUCCESS;
16326 }
16327
16328 /*
16329 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
16330 * The EFER MSR is always up-to-date.
16331 * Update the segment registers and DR7 from the CPU.
16332 */
16333 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16334 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16335 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
16336 AssertRCReturn(rc, rc);
16337 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
16338
16339 PVM pVM = pVCpu->CTX_SUFF(pVM);
16340 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16341 {
16342 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16343 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
16344 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
16345 if (RT_SUCCESS(rc))
16346 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
16347 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16348 }
16349 else
16350 {
16351 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16352 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
16353 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
16354 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16355 }
16356
16357 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
16358 if (RT_SUCCESS(rc))
16359 {
16360 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
16361 AssertRCReturn(rc2, rc2);
16362 return VINF_SUCCESS;
16363 }
16364 return rc;
16365}
16366
16367
16368/**
16369 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
16370 * Conditional VM-exit.
16371 */
16372HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16373{
16374 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16375 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16376
16377 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16378 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16379 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16380 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16381 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16382 AssertRCReturn(rc, rc);
16383
16384 /*
16385 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16386 */
16387 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16388 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16389 {
16390 /*
16391 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
16392 * instruction emulation to inject the original event. Otherwise, injecting the original event
16393 * using hardware-assisted VMX would would trigger the same EPT misconfig VM-exit again.
16394 */
16395 if (!pVCpu->hm.s.Event.fPending)
16396 { /* likely */ }
16397 else
16398 {
16399 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
16400#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16401 /** @todo NSTVMX: Think about how this should be handled. */
16402 if (pVmxTransient->fIsNestedGuest)
16403 return VERR_VMX_IPE_3;
16404#endif
16405 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16406 }
16407 }
16408 else
16409 {
16410 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16411 return rcStrict;
16412 }
16413
16414 /*
16415 * Get sufficent state and update the exit history entry.
16416 */
16417 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16418 rc = hmR0VmxReadGuestPhysicalAddrVmcs(pVCpu, pVmxTransient);
16419 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16420 AssertRCReturn(rc, rc);
16421
16422 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
16423 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
16424 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
16425 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
16426 if (!pExitRec)
16427 {
16428 /*
16429 * If we succeed, resume guest execution.
16430 * If we fail in interpreting the instruction because we couldn't get the guest physical address
16431 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
16432 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
16433 * weird case. See @bugref{6043}.
16434 */
16435 PVM pVM = pVCpu->CTX_SUFF(pVM);
16436 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16437 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
16438 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
16439 if ( rcStrict == VINF_SUCCESS
16440 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16441 || rcStrict == VERR_PAGE_NOT_PRESENT)
16442 {
16443 /* Successfully handled MMIO operation. */
16444 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16445 | HM_CHANGED_GUEST_APIC_TPR);
16446 rcStrict = VINF_SUCCESS;
16447 }
16448 }
16449 else
16450 {
16451 /*
16452 * Frequent exit or something needing probing. Call EMHistoryExec.
16453 */
16454 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
16455 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
16456
16457 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
16458 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16459
16460 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
16461 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16462 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
16463 }
16464 return rcStrict;
16465}
16466
16467
16468/**
16469 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
16470 * VM-exit.
16471 */
16472HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16473{
16474 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16475 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16476
16477 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16478 rc |= hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16479 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16480 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16481 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16482 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16483 AssertRCReturn(rc, rc);
16484
16485 /*
16486 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16487 */
16488 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16489 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16490 {
16491 /*
16492 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
16493 * we shall resolve the nested #PF and re-inject the original event.
16494 */
16495 if (pVCpu->hm.s.Event.fPending)
16496 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
16497 }
16498 else
16499 {
16500 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16501 return rcStrict;
16502 }
16503
16504 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16505 rc = hmR0VmxReadGuestPhysicalAddrVmcs(pVCpu, pVmxTransient);
16506 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16507 AssertRCReturn(rc, rc);
16508
16509 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
16510 uint64_t const uExitQual = pVmxTransient->uExitQual;
16511 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", uExitQual));
16512
16513 RTGCUINT uErrorCode = 0;
16514 if (uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
16515 uErrorCode |= X86_TRAP_PF_ID;
16516 if (uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
16517 uErrorCode |= X86_TRAP_PF_RW;
16518 if (uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
16519 uErrorCode |= X86_TRAP_PF_P;
16520
16521 PVM pVM = pVCpu->CTX_SUFF(pVM);
16522 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16523 Log4Func(("at %#RX64 (%#RX64 errcode=%#x) cs:rip=%#04x:%#RX64\n", GCPhys, uExitQual, uErrorCode, pCtx->cs.Sel, pCtx->rip));
16524
16525 /*
16526 * Handle the pagefault trap for the nested shadow table.
16527 */
16528 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
16529 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
16530 TRPMResetTrap(pVCpu);
16531
16532 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
16533 if ( rcStrict == VINF_SUCCESS
16534 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16535 || rcStrict == VERR_PAGE_NOT_PRESENT)
16536 {
16537 /* Successfully synced our nested page tables. */
16538 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
16539 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
16540 return VINF_SUCCESS;
16541 }
16542
16543 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16544 return rcStrict;
16545}
16546
16547
16548#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16549/**
16550 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
16551 */
16552HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16553{
16554 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16555
16556 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16557 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16558 | CPUMCTX_EXTRN_HWVIRT
16559 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16560 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16561 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16562 AssertRCReturn(rc, rc);
16563
16564 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16565
16566 VMXVEXITINFO ExitInfo;
16567 RT_ZERO(ExitInfo);
16568 ExitInfo.uReason = pVmxTransient->uExitReason;
16569 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16570 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16571 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16572 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16573
16574 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
16575 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16576 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16577 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16578 {
16579 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16580 rcStrict = VINF_SUCCESS;
16581 }
16582 return rcStrict;
16583}
16584
16585
16586/**
16587 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
16588 */
16589HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16590{
16591 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16592
16593 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
16594 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16595 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16596 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16597 AssertRCReturn(rc, rc);
16598
16599 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16600
16601 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16602 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbInstr, VMXINSTRID_VMLAUNCH);
16603 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16604 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16605 {
16606 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16607 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16608 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16609 }
16610 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16611 return rcStrict;
16612}
16613
16614
16615/**
16616 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
16617 */
16618HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16619{
16620 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16621
16622 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16623 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16624 | CPUMCTX_EXTRN_HWVIRT
16625 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16626 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16627 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16628 AssertRCReturn(rc, rc);
16629
16630 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16631
16632 VMXVEXITINFO ExitInfo;
16633 RT_ZERO(ExitInfo);
16634 ExitInfo.uReason = pVmxTransient->uExitReason;
16635 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16636 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16637 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16638 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16639
16640 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
16641 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16642 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16643 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16644 {
16645 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16646 rcStrict = VINF_SUCCESS;
16647 }
16648 return rcStrict;
16649}
16650
16651
16652/**
16653 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
16654 */
16655HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16656{
16657 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16658
16659 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16660 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16661 | CPUMCTX_EXTRN_HWVIRT
16662 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16663 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16664 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16665 AssertRCReturn(rc, rc);
16666
16667 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16668
16669 VMXVEXITINFO ExitInfo;
16670 RT_ZERO(ExitInfo);
16671 ExitInfo.uReason = pVmxTransient->uExitReason;
16672 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16673 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16674 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16675 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16676
16677 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
16678 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16679 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16680 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16681 {
16682 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16683 rcStrict = VINF_SUCCESS;
16684 }
16685 return rcStrict;
16686}
16687
16688
16689/**
16690 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
16691 */
16692HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16693{
16694 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16695
16696 /*
16697 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
16698 * thus might not need to import the shadow VMCS state, it's safer just in case
16699 * code elsewhere dares look at unsynced VMCS fields.
16700 */
16701 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16702 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16703 | CPUMCTX_EXTRN_HWVIRT
16704 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16705 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16706 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16707 AssertRCReturn(rc, rc);
16708
16709 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16710
16711 VMXVEXITINFO ExitInfo;
16712 RT_ZERO(ExitInfo);
16713 ExitInfo.uReason = pVmxTransient->uExitReason;
16714 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16715 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16716 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16717 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16718 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16719
16720 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
16721 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16722 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16723 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16724 {
16725 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16726 rcStrict = VINF_SUCCESS;
16727 }
16728 return rcStrict;
16729}
16730
16731
16732/**
16733 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
16734 */
16735HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16736{
16737 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16738
16739 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
16740 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16741 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16742 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16743 AssertRCReturn(rc, rc);
16744
16745 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16746
16747 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16748 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbInstr, VMXINSTRID_VMRESUME);
16749 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16750 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16751 {
16752 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16753 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16754 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16755 }
16756 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16757 return rcStrict;
16758}
16759
16760
16761/**
16762 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
16763 */
16764HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16765{
16766 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16767
16768 /*
16769 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
16770 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
16771 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
16772 */
16773 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16774 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16775 | CPUMCTX_EXTRN_HWVIRT
16776 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16777 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16778 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16779 AssertRCReturn(rc, rc);
16780
16781 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16782
16783 VMXVEXITINFO ExitInfo;
16784 RT_ZERO(ExitInfo);
16785 ExitInfo.uReason = pVmxTransient->uExitReason;
16786 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16787 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16788 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16789 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16790 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16791
16792 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
16793 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16794 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16795 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16796 {
16797 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16798 rcStrict = VINF_SUCCESS;
16799 }
16800 return rcStrict;
16801}
16802
16803
16804/**
16805 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
16806 */
16807HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16808{
16809 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16810
16811 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16812 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
16813 | CPUMCTX_EXTRN_HWVIRT
16814 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
16815 AssertRCReturn(rc, rc);
16816
16817 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16818
16819 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbInstr);
16820 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16821 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
16822 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16823 {
16824 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16825 rcStrict = VINF_SUCCESS;
16826 }
16827 return rcStrict;
16828}
16829
16830
16831/**
16832 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
16833 */
16834HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16835{
16836 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16837
16838 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16839 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16840 | CPUMCTX_EXTRN_HWVIRT
16841 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16842 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16843 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16844 AssertRCReturn(rc, rc);
16845
16846 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16847
16848 VMXVEXITINFO ExitInfo;
16849 RT_ZERO(ExitInfo);
16850 ExitInfo.uReason = pVmxTransient->uExitReason;
16851 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16852 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16853 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16854 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16855
16856 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16857 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16858 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16859 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16860 {
16861 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16862 rcStrict = VINF_SUCCESS;
16863 }
16864 return rcStrict;
16865}
16866
16867
16868/**
16869 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16870 */
16871HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16872{
16873 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16874
16875 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16876 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16877 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16878 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16879 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16880 AssertRCReturn(rc, rc);
16881
16882 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16883
16884 VMXVEXITINFO ExitInfo;
16885 RT_ZERO(ExitInfo);
16886 ExitInfo.uReason = pVmxTransient->uExitReason;
16887 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16888 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16889 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16890 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16891
16892 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16893 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16894 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16895 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16896 {
16897 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16898 rcStrict = VINF_SUCCESS;
16899 }
16900 return rcStrict;
16901}
16902#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16903/** @} */
16904
16905
16906#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16907/** @name Nested-guest VM-exit handlers.
16908 * @{
16909 */
16910/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16911/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16912/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16913
16914/**
16915 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
16916 * Conditional VM-exit.
16917 */
16918HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16919{
16920 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16921
16922 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16923 AssertRCReturn(rc, rc);
16924
16925 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
16926 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
16927 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
16928
16929 switch (uExitIntType)
16930 {
16931 /*
16932 * Physical NMIs:
16933 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
16934 */
16935 case VMX_EXIT_INT_INFO_TYPE_NMI:
16936 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
16937
16938 /*
16939 * Hardware exceptions,
16940 * Software exceptions,
16941 * Privileged software exceptions:
16942 * Figure out if the exception must be delivered to the guest or the nested-guest.
16943 */
16944 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
16945 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
16946 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
16947 {
16948 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16949 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16950 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16951 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16952 AssertRCReturn(rc, rc);
16953
16954 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16955 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pVCpu, pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
16956 pVmxTransient->uExitIntErrorCode);
16957 if (fIntercept)
16958 {
16959 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16960 AssertRCReturn(rc, rc);
16961
16962 /*
16963 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
16964 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
16965 * length. However, if delivery of a software interrupt, software exception or privileged
16966 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
16967 */
16968 VMXVEXITINFO ExitInfo;
16969 RT_ZERO(ExitInfo);
16970 ExitInfo.uReason = pVmxTransient->uExitReason;
16971 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16972 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16973
16974 VMXVEXITEVENTINFO ExitEventInfo;
16975 RT_ZERO(ExitEventInfo);
16976 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
16977 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
16978 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16979 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16980
16981#ifdef DEBUG_ramshankar
16982 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
16983 Log4Func(("cs:rip=%#04x:%#RX64 %s err_code=%#x exit_qual=%#RX64\n", pCtx->cs.Sel, pCtx->rip,
16984 VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo) ? "#PF" : "Unk",
16985 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual));
16986 Log4Func(("idt_info=%#RX64 (%s) idt_errcode=%#RX32\n", pVmxTransient->uIdtVectoringInfo,
16987 VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo) ? "Valid" : "Invalid",
16988 pVmxTransient->uIdtVectoringErrorCode));
16989#endif
16990 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
16991 }
16992
16993 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs in hmR0VmxExitXcptPF. */
16994 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16995 return hmR0VmxExitXcpt(pVCpu, pVmxTransient);
16996 }
16997
16998 /*
16999 * Software interrupts:
17000 * VM-exits cannot be caused by software interrupts.
17001 *
17002 * External interrupts:
17003 * This should only happen when "acknowledge external interrupts on VM-exit"
17004 * control is set. However, we never set this when executing a guest or
17005 * nested-guest. For nested-guests it is emulated while injecting interrupts into
17006 * the guest.
17007 */
17008 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
17009 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
17010 default:
17011 {
17012 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
17013 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
17014 }
17015 }
17016}
17017
17018
17019/**
17020 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
17021 * Unconditional VM-exit.
17022 */
17023HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17024{
17025 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17026 return IEMExecVmxVmexitTripleFault(pVCpu);
17027}
17028
17029
17030/**
17031 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
17032 */
17033HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17034{
17035 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17036
17037 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
17038 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
17039 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
17040}
17041
17042
17043/**
17044 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
17045 */
17046HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17047{
17048 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17049
17050 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
17051 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
17052 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
17053}
17054
17055
17056/**
17057 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
17058 * Unconditional VM-exit.
17059 */
17060HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17061{
17062 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17063
17064 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17065 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17066 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17067 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17068 AssertRCReturn(rc, rc);
17069
17070 VMXVEXITINFO ExitInfo;
17071 RT_ZERO(ExitInfo);
17072 ExitInfo.uReason = pVmxTransient->uExitReason;
17073 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17074 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17075
17076 VMXVEXITEVENTINFO ExitEventInfo;
17077 RT_ZERO(ExitEventInfo);
17078 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17079 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17080 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
17081}
17082
17083
17084/**
17085 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
17086 */
17087HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17088{
17089 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17090
17091 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
17092 {
17093 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17094 AssertRCReturn(rc, rc);
17095 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17096 }
17097 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
17098}
17099
17100
17101/**
17102 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
17103 */
17104HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17105{
17106 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17107
17108 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17109 {
17110 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17111 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17112 AssertRCReturn(rc, rc);
17113
17114 VMXVEXITINFO ExitInfo;
17115 RT_ZERO(ExitInfo);
17116 ExitInfo.uReason = pVmxTransient->uExitReason;
17117 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17118 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17119 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17120 }
17121 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
17122}
17123
17124
17125/**
17126 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
17127 */
17128HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17129{
17130 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17131
17132 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
17133 {
17134 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17135 AssertRCReturn(rc, rc);
17136 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17137 }
17138 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
17139}
17140
17141
17142/**
17143 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
17144 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
17145 */
17146HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17147{
17148 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17149
17150 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
17151 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
17152
17153 int rc = hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17154 AssertRCReturn(rc, rc);
17155
17156 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
17157 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
17158 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
17159
17160 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
17161 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
17162 u64VmcsField &= UINT64_C(0xffffffff);
17163
17164 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
17165 {
17166 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17167 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17168 AssertRCReturn(rc, rc);
17169
17170 VMXVEXITINFO ExitInfo;
17171 RT_ZERO(ExitInfo);
17172 ExitInfo.uReason = pVmxTransient->uExitReason;
17173 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17174 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17175 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17176 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17177 }
17178
17179 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
17180 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
17181 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
17182}
17183
17184
17185/**
17186 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
17187 */
17188HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17189{
17190 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17191
17192 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17193 {
17194 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17195 AssertRCReturn(rc, rc);
17196 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17197 }
17198
17199 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
17200}
17201
17202
17203/**
17204 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
17205 * Conditional VM-exit.
17206 */
17207HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17208{
17209 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17210
17211 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17212 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17213 AssertRCReturn(rc, rc);
17214
17215 VBOXSTRICTRC rcStrict;
17216 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
17217 switch (uAccessType)
17218 {
17219 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
17220 {
17221 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
17222 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
17223 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
17224 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
17225
17226 bool fIntercept;
17227 switch (iCrReg)
17228 {
17229 case 0:
17230 case 4:
17231 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(pVCpu, &pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
17232 break;
17233
17234 case 3:
17235 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
17236 break;
17237
17238 case 8:
17239 fIntercept = CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
17240 break;
17241
17242 default:
17243 fIntercept = false;
17244 break;
17245 }
17246 if (fIntercept)
17247 {
17248 VMXVEXITINFO ExitInfo;
17249 RT_ZERO(ExitInfo);
17250 ExitInfo.uReason = pVmxTransient->uExitReason;
17251 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17252 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17253 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17254 }
17255 else
17256 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
17257 break;
17258 }
17259
17260 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
17261 {
17262 /*
17263 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
17264 * CR2 reads do not cause a VM-exit.
17265 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
17266 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
17267 */
17268 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
17269 if ( iCrReg == 3
17270 || iCrReg == 8)
17271 {
17272 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
17273 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
17274 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
17275 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uIntercept))
17276 {
17277 VMXVEXITINFO ExitInfo;
17278 RT_ZERO(ExitInfo);
17279 ExitInfo.uReason = pVmxTransient->uExitReason;
17280 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17281 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17282 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17283 }
17284 else
17285 {
17286 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
17287 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
17288 }
17289 }
17290 else
17291 {
17292 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
17293 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
17294 }
17295 break;
17296 }
17297
17298 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
17299 {
17300 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
17301 Assert(pVmcsNstGst);
17302 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
17303 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
17304 if ( (uGstHostMask & X86_CR0_TS)
17305 && (uReadShadow & X86_CR0_TS))
17306 {
17307 VMXVEXITINFO ExitInfo;
17308 RT_ZERO(ExitInfo);
17309 ExitInfo.uReason = pVmxTransient->uExitReason;
17310 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17311 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17312 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17313 }
17314 else
17315 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr);
17316 break;
17317 }
17318
17319 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
17320 {
17321 RTGCPTR GCPtrEffDst;
17322 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
17323 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
17324 if (fMemOperand)
17325 {
17326 rc = hmR0VmxReadGuestLinearAddrVmcs(pVCpu, pVmxTransient);
17327 AssertRCReturn(rc, rc);
17328 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
17329 }
17330 else
17331 GCPtrEffDst = NIL_RTGCPTR;
17332
17333 if (CPUMIsGuestVmxLmswInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, uNewMsw))
17334 {
17335 VMXVEXITINFO ExitInfo;
17336 RT_ZERO(ExitInfo);
17337 ExitInfo.uReason = pVmxTransient->uExitReason;
17338 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17339 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
17340 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17341 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17342 }
17343 else
17344 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, uNewMsw, GCPtrEffDst);
17345 break;
17346 }
17347
17348 default:
17349 {
17350 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
17351 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
17352 }
17353 }
17354
17355 if (rcStrict == VINF_IEM_RAISED_XCPT)
17356 {
17357 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
17358 rcStrict = VINF_SUCCESS;
17359 }
17360 return rcStrict;
17361}
17362
17363
17364/**
17365 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
17366 * Conditional VM-exit.
17367 */
17368HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17369{
17370 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17371
17372 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
17373 {
17374 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17375 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17376 AssertRCReturn(rc, rc);
17377
17378 VMXVEXITINFO ExitInfo;
17379 RT_ZERO(ExitInfo);
17380 ExitInfo.uReason = pVmxTransient->uExitReason;
17381 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17382 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17383 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17384 }
17385 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
17386}
17387
17388
17389/**
17390 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
17391 * Conditional VM-exit.
17392 */
17393HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17394{
17395 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17396
17397 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17398 AssertRCReturn(rc, rc);
17399
17400 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
17401 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
17402 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
17403
17404 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
17405 uint8_t const cbAccess = s_aIOSizes[uIOSize];
17406 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
17407 {
17408 /*
17409 * IN/OUT instruction:
17410 * - Provides VM-exit instruction length.
17411 *
17412 * INS/OUTS instruction:
17413 * - Provides VM-exit instruction length.
17414 * - Provides Guest-linear address.
17415 * - Optionally provides VM-exit instruction info (depends on CPU feature).
17416 */
17417 PVM pVM = pVCpu->CTX_SUFF(pVM);
17418 rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17419 AssertRCReturn(rc, rc);
17420
17421 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
17422 pVmxTransient->ExitInstrInfo.u = 0;
17423 pVmxTransient->uGuestLinearAddr = 0;
17424
17425 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
17426 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
17427 if (fIOString)
17428 {
17429 rc |= hmR0VmxReadGuestLinearAddrVmcs(pVCpu, pVmxTransient);
17430 if (fVmxInsOutsInfo)
17431 {
17432 Assert(RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
17433 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17434 }
17435 }
17436 AssertRCReturn(rc, rc);
17437
17438 VMXVEXITINFO ExitInfo;
17439 RT_ZERO(ExitInfo);
17440 ExitInfo.uReason = pVmxTransient->uExitReason;
17441 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17442 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17443 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17444 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
17445 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17446 }
17447 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
17448}
17449
17450
17451/**
17452 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
17453 */
17454HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17455{
17456 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17457
17458 uint32_t fMsrpm;
17459 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17460 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17461 else
17462 fMsrpm = VMXMSRPM_EXIT_RD;
17463
17464 if (fMsrpm & VMXMSRPM_EXIT_RD)
17465 {
17466 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17467 AssertRCReturn(rc, rc);
17468 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17469 }
17470 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
17471}
17472
17473
17474/**
17475 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
17476 */
17477HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17478{
17479 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17480
17481 uint32_t fMsrpm;
17482 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17483 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17484 else
17485 fMsrpm = VMXMSRPM_EXIT_WR;
17486
17487 if (fMsrpm & VMXMSRPM_EXIT_WR)
17488 {
17489 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17490 AssertRCReturn(rc, rc);
17491 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17492 }
17493 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
17494}
17495
17496
17497/**
17498 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
17499 */
17500HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(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_MWAIT_EXIT))
17505 {
17506 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17507 AssertRCReturn(rc, rc);
17508 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17509 }
17510 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
17511}
17512
17513
17514/**
17515 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
17516 * VM-exit.
17517 */
17518HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17519{
17520 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17521
17522 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
17523 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
17524}
17525
17526
17527/**
17528 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
17529 */
17530HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17531{
17532 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17533
17534 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
17535 {
17536 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17537 AssertRCReturn(rc, rc);
17538 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17539 }
17540 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
17541}
17542
17543
17544/**
17545 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
17546 */
17547HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17548{
17549 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17550
17551 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
17552 * PAUSE when executing a nested-guest? If it does not, we would not need
17553 * to check for the intercepts here. Just call VM-exit... */
17554
17555 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
17556 if ( CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
17557 || CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
17558 {
17559 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17560 AssertRCReturn(rc, rc);
17561 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17562 }
17563 return hmR0VmxExitPause(pVCpu, pVmxTransient);
17564}
17565
17566
17567/**
17568 * Nested-guest VM-exit handler for when the TPR value is lowered below the
17569 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
17570 */
17571HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17572{
17573 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17574
17575 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
17576 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
17577 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
17578}
17579
17580
17581/**
17582 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
17583 * VM-exit.
17584 */
17585HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17586{
17587 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17588
17589 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17590 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17591 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17592 AssertRCReturn(rc, rc);
17593
17594 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
17595 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17596 AssertRCReturn(rc, rc);
17597
17598 VMXVEXITINFO ExitInfo;
17599 RT_ZERO(ExitInfo);
17600 ExitInfo.uReason = pVmxTransient->uExitReason;
17601 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17602 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17603
17604 VMXVEXITEVENTINFO ExitEventInfo;
17605 RT_ZERO(ExitEventInfo);
17606 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17607 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17608 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
17609}
17610
17611
17612/**
17613 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
17614 * Conditional VM-exit.
17615 */
17616HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17617{
17618 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17619
17620 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
17621 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17622 AssertRCReturn(rc, rc);
17623
17624 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17625}
17626
17627
17628/**
17629 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
17630 * Conditional VM-exit.
17631 */
17632HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17633{
17634 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17635
17636 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
17637 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17638 AssertRCReturn(rc, rc);
17639
17640 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17641}
17642
17643
17644/**
17645 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
17646 */
17647HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17648{
17649 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17650
17651 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17652 {
17653 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
17654 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17655 AssertRCReturn(rc, rc);
17656 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17657 }
17658 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
17659}
17660
17661
17662/**
17663 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
17664 */
17665HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17666{
17667 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17668
17669 if (CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
17670 {
17671 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17672 AssertRCReturn(rc, rc);
17673 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17674 }
17675 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
17676}
17677
17678
17679/**
17680 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
17681 */
17682HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17683{
17684 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17685
17686 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17687 {
17688 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
17689 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17690 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17691 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17692 AssertRCReturn(rc, rc);
17693
17694 VMXVEXITINFO ExitInfo;
17695 RT_ZERO(ExitInfo);
17696 ExitInfo.uReason = pVmxTransient->uExitReason;
17697 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17698 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17699 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17700 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17701 }
17702 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
17703}
17704
17705
17706/**
17707 * Nested-guest VM-exit handler for invalid-guest state
17708 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
17709 */
17710HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17711{
17712 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17713
17714 /*
17715 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
17716 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
17717 * Handle it like it's in an invalid guest state of the outer guest.
17718 *
17719 * When the fast path is implemented, this should be changed to cause the corresponding
17720 * nested-guest VM-exit.
17721 */
17722 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
17723}
17724
17725
17726/**
17727 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
17728 * and only provide the instruction length.
17729 *
17730 * Unconditional VM-exit.
17731 */
17732HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17733{
17734 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17735
17736#ifdef VBOX_STRICT
17737 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17738 switch (pVmxTransient->uExitReason)
17739 {
17740 case VMX_EXIT_ENCLS:
17741 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
17742 break;
17743
17744 case VMX_EXIT_VMFUNC:
17745 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_VMFUNC));
17746 break;
17747 }
17748#endif
17749
17750 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17751 AssertRCReturn(rc, rc);
17752 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17753}
17754
17755
17756/**
17757 * Nested-guest VM-exit handler for instructions that provide instruction length as
17758 * well as more information.
17759 *
17760 * Unconditional VM-exit.
17761 */
17762HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17763{
17764 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17765
17766#ifdef VBOX_STRICT
17767 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17768 switch (pVmxTransient->uExitReason)
17769 {
17770 case VMX_EXIT_GDTR_IDTR_ACCESS:
17771 case VMX_EXIT_LDTR_TR_ACCESS:
17772 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
17773 break;
17774
17775 case VMX_EXIT_RDRAND:
17776 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
17777 break;
17778
17779 case VMX_EXIT_RDSEED:
17780 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
17781 break;
17782
17783 case VMX_EXIT_XSAVES:
17784 case VMX_EXIT_XRSTORS:
17785 /** @todo NSTVMX: Verify XSS-bitmap. */
17786 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
17787 break;
17788
17789 case VMX_EXIT_UMWAIT:
17790 case VMX_EXIT_TPAUSE:
17791 Assert(CPUMIsGuestVmxProcCtlsSet(pVCpu, pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
17792 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
17793 break;
17794 }
17795#endif
17796
17797 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17798 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17799 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17800 AssertRCReturn(rc, rc);
17801
17802 VMXVEXITINFO ExitInfo;
17803 RT_ZERO(ExitInfo);
17804 ExitInfo.uReason = pVmxTransient->uExitReason;
17805 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17806 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17807 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17808 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17809}
17810
17811/** @} */
17812#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17813
Note: See TracBrowser for help on using the repository browser.

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