VirtualBox

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

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

VMM/HMVMXR0: Nested VMX: bugref:9180 Remove full guest-state sync debug option.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 641.9 KB
Line 
1/* $Id: HMVMXR0.cpp 78306 2019-04-26 05:41:02Z 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
28#include <VBox/vmm/pdmapi.h>
29#include <VBox/vmm/dbgf.h>
30#include <VBox/vmm/iem.h>
31#include <VBox/vmm/iom.h>
32#include <VBox/vmm/selm.h>
33#include <VBox/vmm/tm.h>
34#include <VBox/vmm/em.h>
35#include <VBox/vmm/gim.h>
36#include <VBox/vmm/apic.h>
37#ifdef VBOX_WITH_REM
38# include <VBox/vmm/rem.h>
39#endif
40#include "HMInternal.h"
41#include <VBox/vmm/vm.h>
42#include <VBox/vmm/hmvmxinline.h>
43#include "HMVMXR0.h"
44#include "dtrace/VBoxVMM.h"
45
46#ifdef DEBUG_ramshankar
47# define HMVMX_ALWAYS_SAVE_GUEST_RFLAGS
48# define HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE
49# define HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
50# define HMVMX_ALWAYS_CHECK_GUEST_STATE
51# define HMVMX_ALWAYS_TRAP_ALL_XCPTS
52# define HMVMX_ALWAYS_TRAP_PF
53# define HMVMX_ALWAYS_FLUSH_TLB
54# define HMVMX_ALWAYS_SWAP_EFER
55#endif
56
57
58/*********************************************************************************************************************************
59* Defined Constants And Macros *
60*********************************************************************************************************************************/
61/** Use the function table. */
62#define HMVMX_USE_FUNCTION_TABLE
63
64/** Determine which tagged-TLB flush handler to use. */
65#define HMVMX_FLUSH_TAGGED_TLB_EPT_VPID 0
66#define HMVMX_FLUSH_TAGGED_TLB_EPT 1
67#define HMVMX_FLUSH_TAGGED_TLB_VPID 2
68#define HMVMX_FLUSH_TAGGED_TLB_NONE 3
69
70/** @name HMVMX_READ_XXX
71 * Flags to skip redundant reads of some common VMCS fields that are not part of
72 * the guest-CPU or VCPU state but are needed while handling VM-exits.
73 */
74#define HMVMX_READ_IDT_VECTORING_INFO RT_BIT_32(0)
75#define HMVMX_READ_IDT_VECTORING_ERROR_CODE RT_BIT_32(1)
76#define HMVMX_READ_EXIT_QUALIFICATION RT_BIT_32(2)
77#define HMVMX_READ_EXIT_INSTR_LEN RT_BIT_32(3)
78#define HMVMX_READ_EXIT_INTERRUPTION_INFO RT_BIT_32(4)
79#define HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE RT_BIT_32(5)
80#define HMVMX_READ_EXIT_INSTR_INFO RT_BIT_32(6)
81#define HMVMX_READ_GUEST_LINEAR_ADDR RT_BIT_32(7)
82/** @} */
83
84/**
85 * Subset of the guest-CPU state that is kept by VMX R0 code while executing the
86 * guest using hardware-assisted VMX.
87 *
88 * This excludes state like GPRs (other than RSP) which are always are
89 * swapped and restored across the world-switch and also registers like EFER,
90 * MSR which cannot be modified by the guest without causing a VM-exit.
91 */
92#define HMVMX_CPUMCTX_EXTRN_ALL ( CPUMCTX_EXTRN_RIP \
93 | CPUMCTX_EXTRN_RFLAGS \
94 | CPUMCTX_EXTRN_RSP \
95 | CPUMCTX_EXTRN_SREG_MASK \
96 | CPUMCTX_EXTRN_TABLE_MASK \
97 | CPUMCTX_EXTRN_KERNEL_GS_BASE \
98 | CPUMCTX_EXTRN_SYSCALL_MSRS \
99 | CPUMCTX_EXTRN_SYSENTER_MSRS \
100 | CPUMCTX_EXTRN_TSC_AUX \
101 | CPUMCTX_EXTRN_OTHER_MSRS \
102 | CPUMCTX_EXTRN_CR0 \
103 | CPUMCTX_EXTRN_CR3 \
104 | CPUMCTX_EXTRN_CR4 \
105 | CPUMCTX_EXTRN_DR7 \
106 | CPUMCTX_EXTRN_HM_VMX_MASK)
107
108/**
109 * Exception bitmap mask for real-mode guests (real-on-v86).
110 *
111 * We need to intercept all exceptions manually except:
112 * - \#AC and \#DB are always intercepted to prevent the CPU from deadlocking
113 * due to bugs in Intel CPUs.
114 * - \#PF need not be intercepted even in real-mode if we have nested paging
115 * support.
116 */
117#define HMVMX_REAL_MODE_XCPT_MASK ( RT_BIT(X86_XCPT_DE) /* always: | RT_BIT(X86_XCPT_DB) */ | RT_BIT(X86_XCPT_NMI) \
118 | RT_BIT(X86_XCPT_BP) | RT_BIT(X86_XCPT_OF) | RT_BIT(X86_XCPT_BR) \
119 | RT_BIT(X86_XCPT_UD) | RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_DF) \
120 | RT_BIT(X86_XCPT_CO_SEG_OVERRUN) | RT_BIT(X86_XCPT_TS) | RT_BIT(X86_XCPT_NP) \
121 | RT_BIT(X86_XCPT_SS) | RT_BIT(X86_XCPT_GP) /* RT_BIT(X86_XCPT_PF) */ \
122 | RT_BIT(X86_XCPT_MF) /* always: | RT_BIT(X86_XCPT_AC) */ | RT_BIT(X86_XCPT_MC) \
123 | RT_BIT(X86_XCPT_XF))
124
125/** Maximum VM-instruction error number. */
126#define HMVMX_INSTR_ERROR_MAX 28
127
128/** Profiling macro. */
129#ifdef HM_PROFILE_EXIT_DISPATCH
130# define HMVMX_START_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitDispatch, ed)
131# define HMVMX_STOP_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitDispatch, ed)
132#else
133# define HMVMX_START_EXIT_DISPATCH_PROF() do { } while (0)
134# define HMVMX_STOP_EXIT_DISPATCH_PROF() do { } while (0)
135#endif
136
137/** Assert that preemption is disabled or covered by thread-context hooks. */
138#define HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu) Assert( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
139 || !RTThreadPreemptIsEnabled(NIL_RTTHREAD))
140
141/** Assert that we haven't migrated CPUs when thread-context hooks are not
142 * used. */
143#define HMVMX_ASSERT_CPU_SAFE(a_pVCpu) AssertMsg( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
144 || (a_pVCpu)->hm.s.idEnteredCpu == RTMpCpuId(), \
145 ("Illegal migration! Entered on CPU %u Current %u\n", \
146 (a_pVCpu)->hm.s.idEnteredCpu, RTMpCpuId()))
147
148/** Asserts that the given CPUMCTX_EXTRN_XXX bits are present in the guest-CPU
149 * context. */
150#define HMVMX_CPUMCTX_ASSERT(a_pVCpu, a_fExtrnMbz) AssertMsg(!((a_pVCpu)->cpum.GstCtx.fExtrn & (a_fExtrnMbz)), \
151 ("fExtrn=%#RX64 fExtrnMbz=%#RX64\n", \
152 (a_pVCpu)->cpum.GstCtx.fExtrn, (a_fExtrnMbz)))
153
154/** Helper macro for VM-exit handlers called unexpectedly. */
155#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_pVmxTransient) \
156 do { \
157 (a_pVCpu)->hm.s.u32HMError = (a_pVmxTransient)->uExitReason; \
158 return VERR_VMX_UNEXPECTED_EXIT; \
159 } while (0)
160
161#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
162/** Macro that does the necessary privilege checks and intercepted VM-exits for
163 * guests that attempted to execute a VMX instruction. */
164# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
165 do \
166 { \
167 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
168 if (rcStrictTmp == VINF_SUCCESS) \
169 { /* likely */ } \
170 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
171 { \
172 Assert((a_pVCpu)->hm.s.Event.fPending); \
173 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
174 return VINF_SUCCESS; \
175 } \
176 else \
177 { \
178 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
179 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
180 } \
181 } while (0)
182
183/** Macro that decodes a memory operand for an instruction VM-exit. */
184# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
185 do \
186 { \
187 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
188 (a_pGCPtrEffAddr)); \
189 if (rcStrictTmp == VINF_SUCCESS) \
190 { /* likely */ } \
191 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
192 { \
193 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
194 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
195 NOREF(uXcptTmp); \
196 return VINF_SUCCESS; \
197 } \
198 else \
199 { \
200 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
201 return rcStrictTmp; \
202 } \
203 } while (0)
204
205#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
206
207
208/*********************************************************************************************************************************
209* Structures and Typedefs *
210*********************************************************************************************************************************/
211/**
212 * VMX transient state.
213 *
214 * A state structure for holding miscellaneous information across
215 * VMX non-root operation and restored after the transition.
216 */
217typedef struct VMXTRANSIENT
218{
219 /** The host's rflags/eflags. */
220 RTCCUINTREG fEFlags;
221#if HC_ARCH_BITS == 32
222 uint32_t u32Alignment0;
223#endif
224 /** The guest's TPR value used for TPR shadowing. */
225 uint8_t u8GuestTpr;
226 /** Alignment. */
227 uint8_t abAlignment0[7];
228
229 /** The basic VM-exit reason. */
230 uint16_t uExitReason;
231 /** Alignment. */
232 uint16_t u16Alignment0;
233 /** The VM-exit interruption error code. */
234 uint32_t uExitIntErrorCode;
235 /** The VM-exit exit code qualification. */
236 uint64_t uExitQual;
237 /** The Guest-linear address. */
238 uint64_t uGuestLinearAddr;
239
240 /** The VM-exit interruption-information field. */
241 uint32_t uExitIntInfo;
242 /** The VM-exit instruction-length field. */
243 uint32_t cbInstr;
244 /** The VM-exit instruction-information field. */
245 VMXEXITINSTRINFO ExitInstrInfo;
246 /** Whether the VM-entry failed or not. */
247 bool fVMEntryFailed;
248 /** Whether we are currently executing a nested-guest. */
249 bool fIsNestedGuest;
250 /** Alignment. */
251 uint8_t abAlignment1[2];
252
253 /** The VM-entry interruption-information field. */
254 uint32_t uEntryIntInfo;
255 /** The VM-entry exception error code field. */
256 uint32_t uEntryXcptErrorCode;
257 /** The VM-entry instruction length field. */
258 uint32_t cbEntryInstr;
259
260 /** IDT-vectoring information field. */
261 uint32_t uIdtVectoringInfo;
262 /** IDT-vectoring error code. */
263 uint32_t uIdtVectoringErrorCode;
264
265 /** Mask of currently read VMCS fields; HMVMX_READ_XXX. */
266 uint32_t fVmcsFieldsRead;
267
268 /** Whether the guest debug state was active at the time of VM-exit. */
269 bool fWasGuestDebugStateActive;
270 /** Whether the hyper debug state was active at the time of VM-exit. */
271 bool fWasHyperDebugStateActive;
272 /** Whether TSC-offsetting and VMX-preemption timer was updated before VM-entry. */
273 bool fUpdatedTscOffsettingAndPreemptTimer;
274 /** Whether the VM-exit was caused by a page-fault during delivery of a
275 * contributory exception or a page-fault. */
276 bool fVectoringDoublePF;
277 /** Whether the VM-exit was caused by a page-fault during delivery of an
278 * external interrupt or NMI. */
279 bool fVectoringPF;
280 bool afAlignment0[3];
281
282 /** The VMCS info. object. */
283 PVMXVMCSINFO pVmcsInfo;
284} VMXTRANSIENT;
285AssertCompileMemberAlignment(VMXTRANSIENT, uExitReason, sizeof(uint64_t));
286AssertCompileMemberAlignment(VMXTRANSIENT, uExitIntInfo, sizeof(uint64_t));
287AssertCompileMemberAlignment(VMXTRANSIENT, uEntryIntInfo, sizeof(uint64_t));
288AssertCompileMemberAlignment(VMXTRANSIENT, fWasGuestDebugStateActive, sizeof(uint64_t));
289AssertCompileMemberAlignment(VMXTRANSIENT, pVmcsInfo, sizeof(uint64_t));
290AssertCompileMemberSize(VMXTRANSIENT, ExitInstrInfo, sizeof(uint32_t));
291/** Pointer to VMX transient state. */
292typedef VMXTRANSIENT *PVMXTRANSIENT;
293
294/**
295 * Memory operand read or write access.
296 */
297typedef enum VMXMEMACCESS
298{
299 VMXMEMACCESS_READ = 0,
300 VMXMEMACCESS_WRITE = 1
301} VMXMEMACCESS;
302
303/**
304 * VMX VM-exit handler.
305 *
306 * @returns Strict VBox status code (i.e. informational status codes too).
307 * @param pVCpu The cross context virtual CPU structure.
308 * @param pVmxTransient The VMX-transient structure.
309 */
310#ifndef HMVMX_USE_FUNCTION_TABLE
311typedef VBOXSTRICTRC FNVMXEXITHANDLER(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
312#else
313typedef DECLCALLBACK(VBOXSTRICTRC) FNVMXEXITHANDLER(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
314/** Pointer to VM-exit handler. */
315typedef FNVMXEXITHANDLER *PFNVMXEXITHANDLER;
316#endif
317
318/**
319 * VMX VM-exit handler, non-strict status code.
320 *
321 * This is generally the same as FNVMXEXITHANDLER, the NSRC bit is just FYI.
322 *
323 * @returns VBox status code, no informational status code returned.
324 * @param pVCpu The cross context virtual CPU structure.
325 * @param pVmxTransient The VMX-transient structure.
326 *
327 * @remarks This is not used on anything returning VERR_EM_INTERPRETER as the
328 * use of that status code will be replaced with VINF_EM_SOMETHING
329 * later when switching over to IEM.
330 */
331#ifndef HMVMX_USE_FUNCTION_TABLE
332typedef int FNVMXEXITHANDLERNSRC(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
333#else
334typedef FNVMXEXITHANDLER FNVMXEXITHANDLERNSRC;
335#endif
336
337
338/*********************************************************************************************************************************
339* Internal Functions *
340*********************************************************************************************************************************/
341#ifndef HMVMX_USE_FUNCTION_TABLE
342DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
343# define HMVMX_EXIT_DECL DECLINLINE(VBOXSTRICTRC)
344# define HMVMX_EXIT_NSRC_DECL DECLINLINE(int)
345#else
346# define HMVMX_EXIT_DECL static DECLCALLBACK(VBOXSTRICTRC)
347# define HMVMX_EXIT_NSRC_DECL HMVMX_EXIT_DECL
348#endif
349#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
350DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
351#endif
352
353static int hmR0VmxImportGuestState(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, uint64_t fWhat);
354#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
355static void hmR0VmxInitVmcsReadCache(PVMCPU pVCpu);
356#endif
357
358/** @name VM-exit handlers.
359 * @{
360 */
361static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmi;
362static FNVMXEXITHANDLER hmR0VmxExitExtInt;
363static FNVMXEXITHANDLER hmR0VmxExitTripleFault;
364static FNVMXEXITHANDLERNSRC hmR0VmxExitInitSignal;
365static FNVMXEXITHANDLERNSRC hmR0VmxExitSipi;
366static FNVMXEXITHANDLERNSRC hmR0VmxExitIoSmi;
367static FNVMXEXITHANDLERNSRC hmR0VmxExitSmi;
368static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindow;
369static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindow;
370static FNVMXEXITHANDLER hmR0VmxExitTaskSwitch;
371static FNVMXEXITHANDLER hmR0VmxExitCpuid;
372static FNVMXEXITHANDLER hmR0VmxExitGetsec;
373static FNVMXEXITHANDLER hmR0VmxExitHlt;
374static FNVMXEXITHANDLERNSRC hmR0VmxExitInvd;
375static FNVMXEXITHANDLER hmR0VmxExitInvlpg;
376static FNVMXEXITHANDLER hmR0VmxExitRdpmc;
377static FNVMXEXITHANDLER hmR0VmxExitVmcall;
378#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
379static FNVMXEXITHANDLER hmR0VmxExitVmclear;
380static FNVMXEXITHANDLER hmR0VmxExitVmlaunch;
381static FNVMXEXITHANDLER hmR0VmxExitVmptrld;
382static FNVMXEXITHANDLER hmR0VmxExitVmptrst;
383static FNVMXEXITHANDLER hmR0VmxExitVmread;
384static FNVMXEXITHANDLER hmR0VmxExitVmresume;
385static FNVMXEXITHANDLER hmR0VmxExitVmwrite;
386static FNVMXEXITHANDLER hmR0VmxExitVmxoff;
387static FNVMXEXITHANDLER hmR0VmxExitVmxon;
388#endif
389static FNVMXEXITHANDLER hmR0VmxExitRdtsc;
390static FNVMXEXITHANDLERNSRC hmR0VmxExitRsm;
391static FNVMXEXITHANDLERNSRC hmR0VmxExitSetPendingXcptUD;
392static FNVMXEXITHANDLER hmR0VmxExitMovCRx;
393static FNVMXEXITHANDLER hmR0VmxExitMovDRx;
394static FNVMXEXITHANDLER hmR0VmxExitIoInstr;
395static FNVMXEXITHANDLER hmR0VmxExitRdmsr;
396static FNVMXEXITHANDLER hmR0VmxExitWrmsr;
397static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestState;
398static FNVMXEXITHANDLERNSRC hmR0VmxExitErrMsrLoad;
399static FNVMXEXITHANDLERNSRC hmR0VmxExitErrUndefined;
400static FNVMXEXITHANDLER hmR0VmxExitMwait;
401static FNVMXEXITHANDLER hmR0VmxExitMtf;
402static FNVMXEXITHANDLER hmR0VmxExitMonitor;
403static FNVMXEXITHANDLER hmR0VmxExitPause;
404static FNVMXEXITHANDLERNSRC hmR0VmxExitErrMachineCheck;
405static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThreshold;
406static FNVMXEXITHANDLER hmR0VmxExitApicAccess;
407static FNVMXEXITHANDLER hmR0VmxExitXdtrAccess;
408static FNVMXEXITHANDLER hmR0VmxExitEptViolation;
409static FNVMXEXITHANDLER hmR0VmxExitEptMisconfig;
410static FNVMXEXITHANDLER hmR0VmxExitRdtscp;
411static FNVMXEXITHANDLER hmR0VmxExitPreemptTimer;
412static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvd;
413static FNVMXEXITHANDLER hmR0VmxExitXsetbv;
414static FNVMXEXITHANDLER hmR0VmxExitRdrand;
415static FNVMXEXITHANDLER hmR0VmxExitInvpcid;
416/** @} */
417
418/** @name Helpers for hardware exceptions VM-exit handlers.
419 * @{
420 */
421static int hmR0VmxExitXcptPF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
422static int hmR0VmxExitXcptMF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
423static int hmR0VmxExitXcptDB(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
424static int hmR0VmxExitXcptBP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
425static int hmR0VmxExitXcptGP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
426static int hmR0VmxExitXcptAC(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
427static int hmR0VmxExitXcptGeneric(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
428/** @} */
429
430
431/*********************************************************************************************************************************
432* Global Variables *
433*********************************************************************************************************************************/
434#ifdef VMX_USE_CACHED_VMCS_ACCESSES
435static const uint32_t g_aVmcsCacheSegBase[] =
436{
437 VMX_VMCS_GUEST_ES_BASE_CACHE_IDX,
438 VMX_VMCS_GUEST_CS_BASE_CACHE_IDX,
439 VMX_VMCS_GUEST_SS_BASE_CACHE_IDX,
440 VMX_VMCS_GUEST_DS_BASE_CACHE_IDX,
441 VMX_VMCS_GUEST_FS_BASE_CACHE_IDX,
442 VMX_VMCS_GUEST_GS_BASE_CACHE_IDX
443};
444AssertCompile(RT_ELEMENTS(g_aVmcsCacheSegBase) == X86_SREG_COUNT);
445#endif
446static const uint32_t g_aVmcsSegBase[] =
447{
448 VMX_VMCS_GUEST_ES_BASE,
449 VMX_VMCS_GUEST_CS_BASE,
450 VMX_VMCS_GUEST_SS_BASE,
451 VMX_VMCS_GUEST_DS_BASE,
452 VMX_VMCS_GUEST_FS_BASE,
453 VMX_VMCS_GUEST_GS_BASE
454};
455static const uint32_t g_aVmcsSegSel[] =
456{
457 VMX_VMCS16_GUEST_ES_SEL,
458 VMX_VMCS16_GUEST_CS_SEL,
459 VMX_VMCS16_GUEST_SS_SEL,
460 VMX_VMCS16_GUEST_DS_SEL,
461 VMX_VMCS16_GUEST_FS_SEL,
462 VMX_VMCS16_GUEST_GS_SEL
463};
464static const uint32_t g_aVmcsSegLimit[] =
465{
466 VMX_VMCS32_GUEST_ES_LIMIT,
467 VMX_VMCS32_GUEST_CS_LIMIT,
468 VMX_VMCS32_GUEST_SS_LIMIT,
469 VMX_VMCS32_GUEST_DS_LIMIT,
470 VMX_VMCS32_GUEST_FS_LIMIT,
471 VMX_VMCS32_GUEST_GS_LIMIT
472};
473static const uint32_t g_aVmcsSegAttr[] =
474{
475 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
476 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
477 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
478 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
479 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
480 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS
481};
482AssertCompile(RT_ELEMENTS(g_aVmcsSegSel) == X86_SREG_COUNT);
483AssertCompile(RT_ELEMENTS(g_aVmcsSegLimit) == X86_SREG_COUNT);
484AssertCompile(RT_ELEMENTS(g_aVmcsSegBase) == X86_SREG_COUNT);
485AssertCompile(RT_ELEMENTS(g_aVmcsSegAttr) == X86_SREG_COUNT);
486
487#ifdef HMVMX_USE_FUNCTION_TABLE
488/**
489 * VMX_EXIT dispatch table.
490 */
491static const PFNVMXEXITHANDLER g_apfnVMExitHandlers[VMX_EXIT_MAX + 1] =
492{
493 /* 00 VMX_EXIT_XCPT_OR_NMI */ hmR0VmxExitXcptOrNmi,
494 /* 01 VMX_EXIT_EXT_INT */ hmR0VmxExitExtInt,
495 /* 02 VMX_EXIT_TRIPLE_FAULT */ hmR0VmxExitTripleFault,
496 /* 03 VMX_EXIT_INIT_SIGNAL */ hmR0VmxExitInitSignal,
497 /* 04 VMX_EXIT_SIPI */ hmR0VmxExitSipi,
498 /* 05 VMX_EXIT_IO_SMI */ hmR0VmxExitIoSmi,
499 /* 06 VMX_EXIT_SMI */ hmR0VmxExitSmi,
500 /* 07 VMX_EXIT_INT_WINDOW */ hmR0VmxExitIntWindow,
501 /* 08 VMX_EXIT_NMI_WINDOW */ hmR0VmxExitNmiWindow,
502 /* 09 VMX_EXIT_TASK_SWITCH */ hmR0VmxExitTaskSwitch,
503 /* 10 VMX_EXIT_CPUID */ hmR0VmxExitCpuid,
504 /* 11 VMX_EXIT_GETSEC */ hmR0VmxExitGetsec,
505 /* 12 VMX_EXIT_HLT */ hmR0VmxExitHlt,
506 /* 13 VMX_EXIT_INVD */ hmR0VmxExitInvd,
507 /* 14 VMX_EXIT_INVLPG */ hmR0VmxExitInvlpg,
508 /* 15 VMX_EXIT_RDPMC */ hmR0VmxExitRdpmc,
509 /* 16 VMX_EXIT_RDTSC */ hmR0VmxExitRdtsc,
510 /* 17 VMX_EXIT_RSM */ hmR0VmxExitRsm,
511 /* 18 VMX_EXIT_VMCALL */ hmR0VmxExitVmcall,
512#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
513 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitVmclear,
514 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitVmlaunch,
515 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitVmptrld,
516 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitVmptrst,
517 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitVmread,
518 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitVmresume,
519 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitVmwrite,
520 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitVmxoff,
521 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitVmxon,
522#else
523 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitSetPendingXcptUD,
524 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitSetPendingXcptUD,
525 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitSetPendingXcptUD,
526 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitSetPendingXcptUD,
527 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitSetPendingXcptUD,
528 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitSetPendingXcptUD,
529 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitSetPendingXcptUD,
530 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitSetPendingXcptUD,
531 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitSetPendingXcptUD,
532#endif
533 /* 28 VMX_EXIT_MOV_CRX */ hmR0VmxExitMovCRx,
534 /* 29 VMX_EXIT_MOV_DRX */ hmR0VmxExitMovDRx,
535 /* 30 VMX_EXIT_IO_INSTR */ hmR0VmxExitIoInstr,
536 /* 31 VMX_EXIT_RDMSR */ hmR0VmxExitRdmsr,
537 /* 32 VMX_EXIT_WRMSR */ hmR0VmxExitWrmsr,
538 /* 33 VMX_EXIT_ERR_INVALID_GUEST_STATE */ hmR0VmxExitErrInvalidGuestState,
539 /* 34 VMX_EXIT_ERR_MSR_LOAD */ hmR0VmxExitErrMsrLoad,
540 /* 35 UNDEFINED */ hmR0VmxExitErrUndefined,
541 /* 36 VMX_EXIT_MWAIT */ hmR0VmxExitMwait,
542 /* 37 VMX_EXIT_MTF */ hmR0VmxExitMtf,
543 /* 38 UNDEFINED */ hmR0VmxExitErrUndefined,
544 /* 39 VMX_EXIT_MONITOR */ hmR0VmxExitMonitor,
545 /* 40 UNDEFINED */ hmR0VmxExitPause,
546 /* 41 VMX_EXIT_PAUSE */ hmR0VmxExitErrMachineCheck,
547 /* 42 VMX_EXIT_ERR_MACHINE_CHECK */ hmR0VmxExitErrUndefined,
548 /* 43 VMX_EXIT_TPR_BELOW_THRESHOLD */ hmR0VmxExitTprBelowThreshold,
549 /* 44 VMX_EXIT_APIC_ACCESS */ hmR0VmxExitApicAccess,
550 /* 45 UNDEFINED */ hmR0VmxExitErrUndefined,
551 /* 46 VMX_EXIT_GDTR_IDTR_ACCESS */ hmR0VmxExitXdtrAccess,
552 /* 47 VMX_EXIT_LDTR_TR_ACCESS */ hmR0VmxExitXdtrAccess,
553 /* 48 VMX_EXIT_EPT_VIOLATION */ hmR0VmxExitEptViolation,
554 /* 49 VMX_EXIT_EPT_MISCONFIG */ hmR0VmxExitEptMisconfig,
555 /* 50 VMX_EXIT_INVEPT */ hmR0VmxExitSetPendingXcptUD,
556 /* 51 VMX_EXIT_RDTSCP */ hmR0VmxExitRdtscp,
557 /* 52 VMX_EXIT_PREEMPT_TIMER */ hmR0VmxExitPreemptTimer,
558 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitSetPendingXcptUD,
559 /* 54 VMX_EXIT_WBINVD */ hmR0VmxExitWbinvd,
560 /* 55 VMX_EXIT_XSETBV */ hmR0VmxExitXsetbv,
561 /* 56 VMX_EXIT_APIC_WRITE */ hmR0VmxExitErrUndefined,
562 /* 57 VMX_EXIT_RDRAND */ hmR0VmxExitRdrand,
563 /* 58 VMX_EXIT_INVPCID */ hmR0VmxExitInvpcid,
564 /* 59 VMX_EXIT_VMFUNC */ hmR0VmxExitSetPendingXcptUD,
565 /* 60 VMX_EXIT_ENCLS */ hmR0VmxExitErrUndefined,
566 /* 61 VMX_EXIT_RDSEED */ hmR0VmxExitErrUndefined, /* only spurious exits, so undefined */
567 /* 62 VMX_EXIT_PML_FULL */ hmR0VmxExitErrUndefined,
568 /* 63 VMX_EXIT_XSAVES */ hmR0VmxExitSetPendingXcptUD,
569 /* 64 VMX_EXIT_XRSTORS */ hmR0VmxExitSetPendingXcptUD,
570};
571#endif /* HMVMX_USE_FUNCTION_TABLE */
572
573#if defined(VBOX_STRICT) && defined(LOG_ENABLED)
574static const char * const g_apszVmxInstrErrors[HMVMX_INSTR_ERROR_MAX + 1] =
575{
576 /* 0 */ "(Not Used)",
577 /* 1 */ "VMCALL executed in VMX root operation.",
578 /* 2 */ "VMCLEAR with invalid physical address.",
579 /* 3 */ "VMCLEAR with VMXON pointer.",
580 /* 4 */ "VMLAUNCH with non-clear VMCS.",
581 /* 5 */ "VMRESUME with non-launched VMCS.",
582 /* 6 */ "VMRESUME after VMXOFF",
583 /* 7 */ "VM-entry with invalid control fields.",
584 /* 8 */ "VM-entry with invalid host state fields.",
585 /* 9 */ "VMPTRLD with invalid physical address.",
586 /* 10 */ "VMPTRLD with VMXON pointer.",
587 /* 11 */ "VMPTRLD with incorrect revision identifier.",
588 /* 12 */ "VMREAD/VMWRITE from/to unsupported VMCS component.",
589 /* 13 */ "VMWRITE to read-only VMCS component.",
590 /* 14 */ "(Not Used)",
591 /* 15 */ "VMXON executed in VMX root operation.",
592 /* 16 */ "VM-entry with invalid executive-VMCS pointer.",
593 /* 17 */ "VM-entry with non-launched executing VMCS.",
594 /* 18 */ "VM-entry with executive-VMCS pointer not VMXON pointer.",
595 /* 19 */ "VMCALL with non-clear VMCS.",
596 /* 20 */ "VMCALL with invalid VM-exit control fields.",
597 /* 21 */ "(Not Used)",
598 /* 22 */ "VMCALL with incorrect MSEG revision identifier.",
599 /* 23 */ "VMXOFF under dual monitor treatment of SMIs and SMM.",
600 /* 24 */ "VMCALL with invalid SMM-monitor features.",
601 /* 25 */ "VM-entry with invalid VM-execution control fields in executive VMCS.",
602 /* 26 */ "VM-entry with events blocked by MOV SS.",
603 /* 27 */ "(Not Used)",
604 /* 28 */ "Invalid operand to INVEPT/INVVPID."
605};
606#endif /* VBOX_STRICT */
607
608
609/**
610 * Get the CR0 guest/host mask that does not change through the lifetime of a VM.
611 *
612 * Any bit set in this mask is owned by the host/hypervisor and would cause a
613 * VM-exit when modified by the guest.
614 *
615 * @returns The static CR0 guest/host mask.
616 * @param pVCpu The cross context virtual CPU structure.
617 */
618DECL_FORCE_INLINE(uint64_t) hmR0VmxGetFixedCr0Mask(PCVMCPU pVCpu)
619{
620 /*
621 * Modifications to CR0 bits that VT-x ignores saving/restoring (CD, ET, NW) and
622 * to CR0 bits that we require for shadow paging (PG) by the guest must cause VM-exits.
623 */
624 /** @todo Avoid intercepting CR0.PE with unrestricted guest execution. Fix PGM
625 * enmGuestMode to be in-sync with the current mode. See @bugref{6398}
626 * and @bugref{6944}. */
627 PVM pVM = pVCpu->CTX_SUFF(pVM);
628 return ( X86_CR0_PE
629 | X86_CR0_NE
630 | (pVM->hm.s.fNestedPaging ? 0 : X86_CR0_WP)
631 | X86_CR0_PG
632 | X86_CR0_ET /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.ET */
633 | X86_CR0_CD /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.CD */
634 | X86_CR0_NW); /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.NW */
635}
636
637
638/**
639 * Gets the CR4 guest/host mask that does not change through the lifetime of a VM.
640 *
641 * Any bit set in this mask is owned by the host/hypervisor and would cause a
642 * VM-exit when modified by the guest.
643 *
644 * @returns The static CR4 guest/host mask.
645 * @param pVCpu The cross context virtual CPU structure.
646 */
647DECL_FORCE_INLINE(uint64_t) hmR0VmxGetFixedCr4Mask(PCVMCPU pVCpu)
648{
649 /*
650 * We need to look at the host features here (for e.g. OSXSAVE, PCID) because
651 * these bits are reserved on hardware that does not support them. Since the
652 * CPU cannot refer to our virtual CPUID, we need to intercept CR4 changes to
653 * these bits and handle it depending on whether we expose them to the guest.
654 */
655 PVM pVM = pVCpu->CTX_SUFF(pVM);
656 bool const fXSaveRstor = pVM->cpum.ro.HostFeatures.fXSaveRstor;
657 bool const fPcid = pVM->cpum.ro.HostFeatures.fPcid;
658 return ( X86_CR4_VMXE
659 | X86_CR4_VME
660 | X86_CR4_PAE
661 | X86_CR4_PGE
662 | X86_CR4_PSE
663 | (fXSaveRstor ? X86_CR4_OSXSAVE : 0)
664 | (fPcid ? X86_CR4_PCIDE : 0));
665}
666
667
668/**
669 * Returns whether the the VM-exit MSR-store area differs from the VM-exit MSR-load
670 * area.
671 *
672 * @returns @c true if it's different, @c false otherwise.
673 * @param pVmcsInfo The VMCS info. object.
674 */
675DECL_FORCE_INLINE(bool) hmR0VmxIsSeparateExitMsrStoreAreaVmcs(PCVMXVMCSINFO pVmcsInfo)
676{
677 return RT_BOOL( pVmcsInfo->pvGuestMsrStore != pVmcsInfo->pvGuestMsrLoad
678 && pVmcsInfo->pvGuestMsrStore);
679}
680
681
682/**
683 * Adds one or more exceptions to the exception bitmap and commits it to the current
684 * VMCS.
685 *
686 * @returns VBox status code.
687 * @param pVmxTransient The VMX-transient structure.
688 * @param uXcptMask The exception(s) to add.
689 */
690static int hmR0VmxAddXcptInterceptMask(PVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
691{
692 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
693 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
694 if ((uXcptBitmap & uXcptMask) != uXcptMask)
695 {
696 uXcptBitmap |= uXcptMask;
697 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
698 AssertRCReturn(rc, rc);
699 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
700 }
701 return VINF_SUCCESS;
702}
703
704
705/**
706 * Adds an exception to the exception bitmap and commits it to the current VMCS.
707 *
708 * @returns VBox status code.
709 * @param pVmxTransient The VMX-transient structure.
710 * @param uXcpt The exception to add.
711 */
712static int hmR0VmxAddXcptIntercept(PVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
713{
714 Assert(uXcpt <= X86_XCPT_LAST);
715 return hmR0VmxAddXcptInterceptMask(pVmxTransient, RT_BIT_32(uXcpt));
716}
717
718
719/**
720 * Remove one or more exceptions from the exception bitmap and commits it to the
721 * current VMCS.
722 *
723 * This takes care of not removing the exception intercept if a nested-guest
724 * requires the exception to be intercepted.
725 *
726 * @returns VBox status code.
727 * @param pVCpu The cross context virtual CPU structure.
728 * @param pVmxTransient The VMX-transient structure.
729 * @param uXcptMask The exception(s) to remove.
730 */
731static int hmR0VmxRemoveXcptInterceptMask(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
732{
733 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
734 uint32_t u32XcptBitmap = pVmcsInfo->u32XcptBitmap;
735 if (u32XcptBitmap & uXcptMask)
736 {
737#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
738 if (!pVmxTransient->fIsNestedGuest)
739 { /* likely */ }
740 else
741 {
742 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
743 uXcptMask &= ~pVmcsNstGst->u32XcptBitmap;
744 }
745#endif
746#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
747 uXcptMask &= ~( RT_BIT(X86_XCPT_BP)
748 | RT_BIT(X86_XCPT_DE)
749 | RT_BIT(X86_XCPT_NM)
750 | RT_BIT(X86_XCPT_TS)
751 | RT_BIT(X86_XCPT_UD)
752 | RT_BIT(X86_XCPT_NP)
753 | RT_BIT(X86_XCPT_SS)
754 | RT_BIT(X86_XCPT_GP)
755 | RT_BIT(X86_XCPT_PF)
756 | RT_BIT(X86_XCPT_MF));
757#elif defined(HMVMX_ALWAYS_TRAP_PF)
758 uXcptMask &= ~RT_BIT(X86_XCPT_PF);
759#endif
760 if (uXcptMask)
761 {
762 /* Validate we are not removing any essential exception intercepts. */
763 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || !(uXcptMask & RT_BIT(X86_XCPT_PF))); RT_NOREF(pVCpu);
764 Assert(!(uXcptMask & RT_BIT(X86_XCPT_DB)));
765 Assert(!(uXcptMask & RT_BIT(X86_XCPT_AC)));
766
767 /* Remove it from the exception bitmap. */
768 u32XcptBitmap &= ~uXcptMask;
769
770 /* Commit and update the cache if necessary. */
771 if (pVmcsInfo->u32XcptBitmap != u32XcptBitmap)
772 {
773 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
774 AssertRCReturn(rc, rc);
775 pVmcsInfo->u32XcptBitmap = u32XcptBitmap;
776 }
777 }
778 }
779 return VINF_SUCCESS;
780}
781
782
783/**
784 * Remove an exceptions from the exception bitmap and commits it to the current
785 * VMCS.
786 *
787 * @returns VBox status code.
788 * @param pVCpu The cross context virtual CPU structure.
789 * @param pVmxTransient The VMX-transient structure.
790 * @param uXcpt The exception to remove.
791 */
792static int hmR0VmxRemoveXcptIntercept(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
793{
794 return hmR0VmxRemoveXcptInterceptMask(pVCpu, pVmxTransient, RT_BIT(uXcpt));
795}
796
797
798/**
799 * Loads the VMCS specified by the VMCS info. object.
800 *
801 * @returns VBox status code.
802 * @param pVmcsInfo The VMCS info. object.
803 */
804static int hmR0VmxLoadVmcs(PVMXVMCSINFO pVmcsInfo)
805{
806 Assert(pVmcsInfo);
807 Assert(pVmcsInfo->HCPhysVmcs);
808 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
809
810 if (pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_CLEAR)
811 {
812 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysVmcs);
813 if (RT_SUCCESS(rc))
814 {
815 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
816 return VINF_SUCCESS;
817 }
818 return rc;
819 }
820 return VERR_VMX_INVALID_VMCS_LAUNCH_STATE;
821}
822
823
824/**
825 * Clears the VMCS specified by the VMCS info. object.
826 *
827 * @returns VBox status code.
828 * @param pVmcsInfo The VMCS info. object.
829 */
830static int hmR0VmxClearVmcs(PVMXVMCSINFO pVmcsInfo)
831{
832 Assert(pVmcsInfo);
833 Assert(pVmcsInfo->HCPhysVmcs);
834 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
835
836 int rc = VMXClearVmcs(pVmcsInfo->HCPhysVmcs);
837 if (RT_SUCCESS(rc))
838 pVmcsInfo->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
839 return rc;
840}
841
842
843#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
844/**
845 * Switches the current VMCS to the one specified.
846 *
847 * @returns VBox status code.
848 * @param pVmcsInfoFrom The VMCS info. object we are switching from.
849 * @param pVmcsInfoTo The VMCS info. object we are switching to.
850 *
851 * @remarks Called with interrupts disabled.
852 */
853static int hmR0VmxSwitchVmcs(PVMXVMCSINFO pVmcsInfoFrom, PVMXVMCSINFO pVmcsInfoTo)
854{
855 Assert(pVmcsInfoFrom);
856 Assert(pVmcsInfoTo);
857
858 /*
859 * Clear the VMCS we are switching out if it has not already been cleared.
860 * This will sync any CPU internal data back to the VMCS.
861 */
862 if (pVmcsInfoFrom->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
863 {
864 int rc = hmR0VmxClearVmcs(pVmcsInfoFrom);
865 if (RT_SUCCESS(rc))
866 { /* likely */ }
867 else
868 return rc;
869 }
870
871 /*
872 * Clear the VMCS we are switching to if it has not already been cleared.
873 * This will initialize the VMCS launch state to "clear" required for loading it.
874 *
875 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
876 */
877 if (pVmcsInfoTo->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
878 {
879 int rc = hmR0VmxClearVmcs(pVmcsInfoTo);
880 if (RT_SUCCESS(rc))
881 { /* likely */ }
882 else
883 return rc;
884 }
885
886 /*
887 * Finally, load the VMCS we are switching to.
888 */
889 return hmR0VmxLoadVmcs(pVmcsInfoTo);
890}
891#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
892
893
894/**
895 * Updates the VM's last error record.
896 *
897 * If there was a VMX instruction error, reads the error data from the VMCS and
898 * updates VCPU's last error record as well.
899 *
900 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
901 * Can be NULL if @a rc is not VERR_VMX_UNABLE_TO_START_VM or
902 * VERR_VMX_INVALID_VMCS_FIELD.
903 * @param rc The error code.
904 */
905static void hmR0VmxUpdateErrorRecord(PVMCPU pVCpu, int rc)
906{
907 if ( rc == VERR_VMX_INVALID_VMCS_FIELD
908 || rc == VERR_VMX_UNABLE_TO_START_VM)
909 {
910 AssertPtrReturnVoid(pVCpu);
911 VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
912 }
913 pVCpu->CTX_SUFF(pVM)->hm.s.rcInit = rc;
914}
915
916
917#ifdef VBOX_STRICT
918/**
919 * Reads the VM-entry interruption-information field from the VMCS into the VMX
920 * transient structure.
921 *
922 * @returns VBox status code.
923 * @param pVmxTransient The VMX-transient structure.
924 *
925 * @remarks No-long-jump zone!!!
926 */
927DECLINLINE(int) hmR0VmxReadEntryIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
928{
929 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &pVmxTransient->uEntryIntInfo);
930 AssertRCReturn(rc, rc);
931 return VINF_SUCCESS;
932}
933
934
935/**
936 * Reads the VM-entry exception error code field from the VMCS into
937 * the VMX transient structure.
938 *
939 * @returns VBox status code.
940 * @param pVmxTransient The VMX-transient structure.
941 *
942 * @remarks No-long-jump zone!!!
943 */
944DECLINLINE(int) hmR0VmxReadEntryXcptErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
945{
946 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &pVmxTransient->uEntryXcptErrorCode);
947 AssertRCReturn(rc, rc);
948 return VINF_SUCCESS;
949}
950
951
952/**
953 * Reads the VM-entry exception error code field from the VMCS into
954 * the VMX transient structure.
955 *
956 * @returns VBox status code.
957 * @param pVmxTransient The VMX-transient structure.
958 *
959 * @remarks No-long-jump zone!!!
960 */
961DECLINLINE(int) hmR0VmxReadEntryInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
962{
963 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &pVmxTransient->cbEntryInstr);
964 AssertRCReturn(rc, rc);
965 return VINF_SUCCESS;
966}
967#endif /* VBOX_STRICT */
968
969
970/**
971 * Reads the VM-exit interruption-information field from the VMCS into the VMX
972 * transient structure.
973 *
974 * @returns VBox status code.
975 * @param pVmxTransient The VMX-transient structure.
976 */
977DECLINLINE(int) hmR0VmxReadExitIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
978{
979 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_INFO))
980 {
981 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
982 AssertRCReturn(rc,rc);
983 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_INFO;
984 }
985 return VINF_SUCCESS;
986}
987
988
989/**
990 * Reads the VM-exit interruption error code from the VMCS into the VMX
991 * transient structure.
992 *
993 * @returns VBox status code.
994 * @param pVmxTransient The VMX-transient structure.
995 */
996DECLINLINE(int) hmR0VmxReadExitIntErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
997{
998 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE))
999 {
1000 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1001 AssertRCReturn(rc, rc);
1002 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE;
1003 }
1004 return VINF_SUCCESS;
1005}
1006
1007
1008/**
1009 * Reads the VM-exit instruction length field from the VMCS into the VMX
1010 * transient structure.
1011 *
1012 * @returns VBox status code.
1013 * @param pVmxTransient The VMX-transient structure.
1014 */
1015DECLINLINE(int) hmR0VmxReadExitInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1016{
1017 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_LEN))
1018 {
1019 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbInstr);
1020 AssertRCReturn(rc, rc);
1021 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_LEN;
1022 }
1023 return VINF_SUCCESS;
1024}
1025
1026
1027/**
1028 * Reads the VM-exit instruction-information field from the VMCS into
1029 * the VMX transient structure.
1030 *
1031 * @returns VBox status code.
1032 * @param pVmxTransient The VMX-transient structure.
1033 */
1034DECLINLINE(int) hmR0VmxReadExitInstrInfoVmcs(PVMXTRANSIENT pVmxTransient)
1035{
1036 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_INFO))
1037 {
1038 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1039 AssertRCReturn(rc, rc);
1040 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_INFO;
1041 }
1042 return VINF_SUCCESS;
1043}
1044
1045
1046/**
1047 * Reads the VM-exit Qualification from the VMCS into the VMX transient structure.
1048 *
1049 * @returns VBox status code.
1050 * @param pVCpu The cross context virtual CPU structure of the
1051 * calling EMT. (Required for the VMCS cache case.)
1052 * @param pVmxTransient The VMX-transient structure.
1053 */
1054DECLINLINE(int) hmR0VmxReadExitQualVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
1055{
1056 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_QUALIFICATION))
1057 {
1058 int rc = VMXReadVmcsGstN(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual); NOREF(pVCpu);
1059 AssertRCReturn(rc, rc);
1060 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION;
1061 }
1062 return VINF_SUCCESS;
1063}
1064
1065
1066/**
1067 * Reads the Guest-linear address from the VMCS into the VMX transient structure.
1068 *
1069 * @returns VBox status code.
1070 * @param pVCpu The cross context virtual CPU structure of the
1071 * calling EMT. (Required for the VMCS cache case.)
1072 * @param pVmxTransient The VMX-transient structure.
1073 */
1074DECLINLINE(int) hmR0VmxReadGuestLinearAddrVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
1075{
1076 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_LINEAR_ADDR))
1077 {
1078 int rc = VMXReadVmcsGstN(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr); NOREF(pVCpu);
1079 AssertRCReturn(rc, rc);
1080 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_LINEAR_ADDR;
1081 }
1082 return VINF_SUCCESS;
1083}
1084
1085
1086/**
1087 * Reads the IDT-vectoring information field from the VMCS into the VMX
1088 * transient structure.
1089 *
1090 * @returns VBox status code.
1091 * @param pVmxTransient The VMX-transient structure.
1092 *
1093 * @remarks No-long-jump zone!!!
1094 */
1095DECLINLINE(int) hmR0VmxReadIdtVectoringInfoVmcs(PVMXTRANSIENT pVmxTransient)
1096{
1097 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_INFO))
1098 {
1099 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1100 AssertRCReturn(rc, rc);
1101 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_INFO;
1102 }
1103 return VINF_SUCCESS;
1104}
1105
1106
1107/**
1108 * Reads the IDT-vectoring error code from the VMCS into the VMX
1109 * transient structure.
1110 *
1111 * @returns VBox status code.
1112 * @param pVmxTransient The VMX-transient structure.
1113 */
1114DECLINLINE(int) hmR0VmxReadIdtVectoringErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1115{
1116 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_ERROR_CODE))
1117 {
1118 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1119 AssertRCReturn(rc, rc);
1120 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_ERROR_CODE;
1121 }
1122 return VINF_SUCCESS;
1123}
1124
1125
1126/**
1127 * Enters VMX root mode operation on the current CPU.
1128 *
1129 * @returns VBox status code.
1130 * @param pVM The cross context VM structure. Can be
1131 * NULL, after a resume.
1132 * @param HCPhysCpuPage Physical address of the VMXON region.
1133 * @param pvCpuPage Pointer to the VMXON region.
1134 */
1135static int hmR0VmxEnterRootMode(PVM pVM, RTHCPHYS HCPhysCpuPage, void *pvCpuPage)
1136{
1137 Assert(HCPhysCpuPage && HCPhysCpuPage != NIL_RTHCPHYS);
1138 Assert(RT_ALIGN_T(HCPhysCpuPage, _4K, RTHCPHYS) == HCPhysCpuPage);
1139 Assert(pvCpuPage);
1140 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1141
1142 if (pVM)
1143 {
1144 /* Write the VMCS revision identifier to the VMXON region. */
1145 *(uint32_t *)pvCpuPage = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
1146 }
1147
1148 /* Paranoid: Disable interrupts as, in theory, interrupt handlers might mess with CR4. */
1149 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1150
1151 /* Enable the VMX bit in CR4 if necessary. */
1152 RTCCUINTREG const uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
1153
1154 /* Enter VMX root mode. */
1155 int rc = VMXEnable(HCPhysCpuPage);
1156 if (RT_FAILURE(rc))
1157 {
1158 if (!(uOldCr4 & X86_CR4_VMXE))
1159 SUPR0ChangeCR4(0 /* fOrMask */, ~X86_CR4_VMXE);
1160
1161 if (pVM)
1162 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
1163 }
1164
1165 /* Restore interrupts. */
1166 ASMSetFlags(fEFlags);
1167 return rc;
1168}
1169
1170
1171/**
1172 * Exits VMX root mode operation on the current CPU.
1173 *
1174 * @returns VBox status code.
1175 */
1176static int hmR0VmxLeaveRootMode(void)
1177{
1178 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1179
1180 /* Paranoid: Disable interrupts as, in theory, interrupts handlers might mess with CR4. */
1181 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1182
1183 /* If we're for some reason not in VMX root mode, then don't leave it. */
1184 RTCCUINTREG const uHostCR4 = ASMGetCR4();
1185
1186 int rc;
1187 if (uHostCR4 & X86_CR4_VMXE)
1188 {
1189 /* Exit VMX root mode and clear the VMX bit in CR4. */
1190 VMXDisable();
1191 SUPR0ChangeCR4(0 /* fOrMask */, ~X86_CR4_VMXE);
1192 rc = VINF_SUCCESS;
1193 }
1194 else
1195 rc = VERR_VMX_NOT_IN_VMX_ROOT_MODE;
1196
1197 /* Restore interrupts. */
1198 ASMSetFlags(fEFlags);
1199 return rc;
1200}
1201
1202
1203/**
1204 * Allocates and maps a physically contiguous page. The allocated page is
1205 * zero'd out (used by various VT-x structures).
1206 *
1207 * @returns IPRT status code.
1208 * @param pMemObj Pointer to the ring-0 memory object.
1209 * @param ppVirt Where to store the virtual address of the
1210 * allocation.
1211 * @param pHCPhys Where to store the physical address of the
1212 * allocation.
1213 */
1214static int hmR0VmxPageAllocZ(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1215{
1216 AssertPtr(pMemObj);
1217 AssertPtr(ppVirt);
1218 AssertPtr(pHCPhys);
1219 int rc = RTR0MemObjAllocCont(pMemObj, X86_PAGE_4K_SIZE, false /* fExecutable */);
1220 if (RT_FAILURE(rc))
1221 return rc;
1222 *ppVirt = RTR0MemObjAddress(*pMemObj);
1223 *pHCPhys = RTR0MemObjGetPagePhysAddr(*pMemObj, 0 /* iPage */);
1224 ASMMemZero32(*ppVirt, X86_PAGE_4K_SIZE);
1225 return VINF_SUCCESS;
1226}
1227
1228
1229/**
1230 * Frees and unmaps an allocated, physical page.
1231 *
1232 * @param pMemObj Pointer to the ring-0 memory object.
1233 * @param ppVirt Where to re-initialize the virtual address of
1234 * allocation as 0.
1235 * @param pHCPhys Where to re-initialize the physical address of the
1236 * allocation as 0.
1237 */
1238static void hmR0VmxPageFree(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1239{
1240 AssertPtr(pMemObj);
1241 AssertPtr(ppVirt);
1242 AssertPtr(pHCPhys);
1243 /* NULL is valid, accepted and ignored by the free function below. */
1244 RTR0MemObjFree(*pMemObj, true /* fFreeMappings */);
1245 *pMemObj = NIL_RTR0MEMOBJ;
1246 *ppVirt = NULL;
1247 *pHCPhys = NIL_RTHCPHYS;
1248}
1249
1250
1251/**
1252 * Initializes a VMCS info. object.
1253 *
1254 * @param pVmcsInfo The VMCS info. object.
1255 */
1256static void hmR0VmxInitVmcsInfo(PVMXVMCSINFO pVmcsInfo)
1257{
1258 memset(pVmcsInfo, 0, sizeof(*pVmcsInfo));
1259
1260 Assert(pVmcsInfo->hMemObjVmcs == NIL_RTR0MEMOBJ);
1261 Assert(pVmcsInfo->hMemObjMsrBitmap == NIL_RTR0MEMOBJ);
1262 Assert(pVmcsInfo->hMemObjGuestMsrLoad == NIL_RTR0MEMOBJ);
1263 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1264 Assert(pVmcsInfo->hMemObjHostMsrLoad == NIL_RTR0MEMOBJ);
1265 pVmcsInfo->HCPhysVmcs = NIL_RTHCPHYS;
1266 pVmcsInfo->HCPhysMsrBitmap = NIL_RTHCPHYS;
1267 pVmcsInfo->HCPhysGuestMsrLoad = NIL_RTHCPHYS;
1268 pVmcsInfo->HCPhysGuestMsrStore = NIL_RTHCPHYS;
1269 pVmcsInfo->HCPhysHostMsrLoad = NIL_RTHCPHYS;
1270 pVmcsInfo->HCPhysVirtApic = NIL_RTHCPHYS;
1271 pVmcsInfo->HCPhysEPTP = NIL_RTHCPHYS;
1272 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
1273}
1274
1275
1276/**
1277 * Frees the VT-x structures for a VMCS info. object.
1278 *
1279 * @param pVM The cross context VM structure.
1280 * @param pVmcsInfo The VMCS info. object.
1281 */
1282static void hmR0VmxFreeVmcsInfo(PVM pVM, PVMXVMCSINFO pVmcsInfo)
1283{
1284 hmR0VmxPageFree(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1285
1286 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1287 hmR0VmxPageFree(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1288
1289 hmR0VmxPageFree(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad, &pVmcsInfo->HCPhysHostMsrLoad);
1290 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad, &pVmcsInfo->HCPhysGuestMsrLoad);
1291 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrStore, &pVmcsInfo->pvGuestMsrStore, &pVmcsInfo->HCPhysGuestMsrStore);
1292
1293 hmR0VmxInitVmcsInfo(pVmcsInfo);
1294}
1295
1296
1297/**
1298 * Allocates the VT-x structures for a VMCS info. object.
1299 *
1300 * @returns VBox status code.
1301 * @param pVCpu The cross context virtual CPU structure.
1302 * @param pVmcsInfo The VMCS info. object.
1303 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
1304 */
1305static int hmR0VmxAllocVmcsInfo(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
1306{
1307 PVM pVM = pVCpu->CTX_SUFF(pVM);
1308
1309 /* Allocate the guest VM control structure (VMCS). */
1310 int rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1311 if (RT_SUCCESS(rc))
1312 {
1313 if (!fIsNstGstVmcs)
1314 {
1315 /* Get the allocated virtual-APIC page from the virtual APIC device. */
1316 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
1317 && (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW))
1318 {
1319 rc = APICGetApicPageForCpu(pVCpu, &pVmcsInfo->HCPhysVirtApic, (PRTR0PTR)&pVmcsInfo->pbVirtApic,
1320 NULL /* pR3Ptr */, NULL /* pRCPtr */);
1321 }
1322 }
1323 else
1324 {
1325 Assert(pVmcsInfo->HCPhysVirtApic == NIL_RTHCPHYS);
1326 Assert(!pVmcsInfo->pbVirtApic);
1327 }
1328
1329 if (RT_SUCCESS(rc))
1330 {
1331 /*
1332 * Allocate the MSR-bitmap if supported by the CPU. The MSR-bitmap is for
1333 * transparent accesses of specific MSRs.
1334 *
1335 * If the condition for enabling MSR bitmaps changes here, don't forget to
1336 * update HMIsMsrBitmapActive().
1337 *
1338 * We don't share MSR bitmaps between the guest and nested-guest as we then
1339 * don't need to care about carefully restoring the guest MSR bitmap.
1340 * The guest visible nested-guest MSR bitmap needs to remain unchanged.
1341 * Hence, allocate a separate MSR bitmap for the guest and nested-guest.
1342 */
1343 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1344 {
1345 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1346 if (RT_SUCCESS(rc))
1347 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
1348 }
1349
1350 if (RT_SUCCESS(rc))
1351 {
1352 /*
1353 * Allocate the VM-entry MSR-load area for the guest MSRs.
1354 *
1355 * Similar to MSR-bitmaps, we do not share the auto MSR-load/store are between
1356 * the guest and nested-guest.
1357 */
1358 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad,
1359 &pVmcsInfo->HCPhysGuestMsrLoad);
1360 if (RT_SUCCESS(rc))
1361 {
1362 /*
1363 * We use the same page for VM-entry MSR-load and VM-exit MSR store areas.
1364 * These contain the guest MSRs to load on VM-entry and store on VM-exit.
1365 */
1366 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1367 pVmcsInfo->pvGuestMsrStore = pVmcsInfo->pvGuestMsrLoad;
1368 pVmcsInfo->HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrLoad;
1369
1370 /* Allocate the VM-exit MSR-load page for the host MSRs. */
1371 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad,
1372 &pVmcsInfo->HCPhysHostMsrLoad);
1373 }
1374 }
1375 }
1376 }
1377
1378 return rc;
1379}
1380
1381
1382/**
1383 * Free all VT-x structures for the VM.
1384 *
1385 * @returns IPRT status code.
1386 * @param pVM The cross context VM structure.
1387 */
1388static void hmR0VmxStructsFree(PVM pVM)
1389{
1390#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1391 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1392#endif
1393 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess, &pVM->hm.s.vmx.HCPhysApicAccess);
1394
1395 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1396 {
1397 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1398 PVMXVMCSINFO pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
1399 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1400#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1401 if (pVM->cpum.ro.GuestFeatures.fVmx)
1402 {
1403 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1404 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1405 }
1406#endif
1407 }
1408}
1409
1410
1411/**
1412 * Allocate all VT-x structures for the VM.
1413 *
1414 * @returns IPRT status code.
1415 * @param pVM The cross context VM structure.
1416 */
1417static int hmR0VmxStructsAlloc(PVM pVM)
1418{
1419 /*
1420 * Sanity check the VMCS size reported by the CPU as we assume 4KB allocations.
1421 * The VMCS size cannot be more than 4096 bytes.
1422 *
1423 * See Intel spec. Appendix A.1 "Basic VMX Information".
1424 */
1425 uint32_t const cbVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_SIZE);
1426 if (cbVmcs <= X86_PAGE_4K_SIZE)
1427 { /* likely */ }
1428 else
1429 {
1430 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_INVALID_VMCS_SIZE;
1431 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
1432 }
1433
1434 /*
1435 * Initialize/check members up-front so we can cleanup en masse on allocation failures.
1436 */
1437#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1438 Assert(pVM->hm.s.vmx.hMemObjScratch == NIL_RTR0MEMOBJ);
1439 Assert(pVM->hm.s.vmx.pbScratch == NULL);
1440 pVM->hm.s.vmx.HCPhysScratch = NIL_RTHCPHYS;
1441#endif
1442
1443 Assert(pVM->hm.s.vmx.hMemObjApicAccess == NIL_RTR0MEMOBJ);
1444 Assert(pVM->hm.s.vmx.pbApicAccess == NULL);
1445 pVM->hm.s.vmx.HCPhysApicAccess = NIL_RTHCPHYS;
1446
1447 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1448 {
1449 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1450 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfo);
1451 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
1452 }
1453
1454 /*
1455 * Allocate per-VM VT-x structures.
1456 */
1457 int rc = VINF_SUCCESS;
1458#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1459 /* Allocate crash-dump magic scratch page. */
1460 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1461 if (RT_FAILURE(rc))
1462 {
1463 hmR0VmxStructsFree(pVM);
1464 return rc;
1465 }
1466 strcpy((char *)pVM->hm.s.vmx.pbScratch, "SCRATCH Magic");
1467 *(uint64_t *)(pVM->hm.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
1468#endif
1469
1470 /* Allocate the APIC-access page for trapping APIC accesses from the guest. */
1471 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
1472 {
1473 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess,
1474 &pVM->hm.s.vmx.HCPhysApicAccess);
1475 if (RT_FAILURE(rc))
1476 {
1477 hmR0VmxStructsFree(pVM);
1478 return rc;
1479 }
1480 }
1481
1482 /*
1483 * Initialize per-VCPU VT-x structures.
1484 */
1485 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1486 {
1487 /* Allocate the guest VMCS structures. */
1488 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1489 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
1490 if (RT_SUCCESS(rc))
1491 {
1492#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1493 /* Allocate the nested-guest VMCS structures, when the VMX feature is exposed to the guest. */
1494 if (pVM->cpum.ro.GuestFeatures.fVmx)
1495 {
1496 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
1497 if (RT_SUCCESS(rc))
1498 { /* likely */ }
1499 else
1500 break;
1501 }
1502#endif
1503 }
1504 else
1505 break;
1506 }
1507
1508 if (RT_FAILURE(rc))
1509 {
1510 hmR0VmxStructsFree(pVM);
1511 return rc;
1512 }
1513
1514 return VINF_SUCCESS;
1515}
1516
1517
1518#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1519/**
1520 * Returns whether an MSR at the given MSR-bitmap offset is intercepted or not.
1521 *
1522 * @returns @c true if the MSR is intercepted, @c false otherwise.
1523 * @param pvMsrBitmap The MSR bitmap.
1524 * @param offMsr The MSR byte offset.
1525 * @param iBit The bit offset from the byte offset.
1526 */
1527DECLINLINE(bool) hmR0VmxIsMsrBitSet(const void *pvMsrBitmap, uint16_t offMsr, int32_t iBit)
1528{
1529 uint8_t const * const pbMsrBitmap = (uint8_t const * const)pvMsrBitmap;
1530 Assert(pbMsrBitmap);
1531 Assert(offMsr + (iBit >> 3) <= X86_PAGE_4K_SIZE);
1532 return ASMBitTest(pbMsrBitmap + offMsr, iBit);
1533}
1534#endif
1535
1536
1537/**
1538 * Sets the permission bits for the specified MSR in the given MSR bitmap.
1539 *
1540 * If the passed VMCS is a nested-guest VMCS, this function ensures that the
1541 * read/write intercept is cleared from the MSR bitmap used for hardware-assisted
1542 * VMX execution of the nested-guest, only if nested-guest is also not intercepting
1543 * the read/write access of this MSR.
1544 *
1545 * @param pVCpu The cross context virtual CPU structure.
1546 * @param pVmcsInfo The VMCS info. object.
1547 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
1548 * @param idMsr The MSR value.
1549 * @param fMsrpm The MSR permissions (see VMXMSRPM_XXX). This must
1550 * include both a read -and- a write permission!
1551 *
1552 * @sa HMGetVmxMsrPermission.
1553 * @remarks Can be called with interrupts disabled.
1554 */
1555static void hmR0VmxSetMsrPermission(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs, uint32_t idMsr, uint32_t fMsrpm)
1556{
1557 uint8_t *pbMsrBitmap = (uint8_t *)pVmcsInfo->pvMsrBitmap;
1558 Assert(pbMsrBitmap);
1559 Assert(VMXMSRPM_IS_FLAG_VALID(fMsrpm));
1560
1561 /*
1562 * MSR-bitmap Layout:
1563 * Byte index MSR range Interpreted as
1564 * 0x000 - 0x3ff 0x00000000 - 0x00001fff Low MSR read bits.
1565 * 0x400 - 0x7ff 0xc0000000 - 0xc0001fff High MSR read bits.
1566 * 0x800 - 0xbff 0x00000000 - 0x00001fff Low MSR write bits.
1567 * 0xc00 - 0xfff 0xc0000000 - 0xc0001fff High MSR write bits.
1568 *
1569 * A bit corresponding to an MSR within the above range causes a VM-exit
1570 * if the bit is 1 on executions of RDMSR/WRMSR. If an MSR falls out of
1571 * the MSR range, it always cause a VM-exit.
1572 *
1573 * See Intel spec. 24.6.9 "MSR-Bitmap Address".
1574 */
1575 uint16_t const offBitmapRead = 0;
1576 uint16_t const offBitmapWrite = 0x800;
1577 uint16_t offMsr;
1578 int32_t iBit;
1579 if (idMsr <= UINT32_C(0x00001fff))
1580 {
1581 offMsr = 0;
1582 iBit = idMsr;
1583 }
1584 else if (idMsr - UINT32_C(0xc0000000) <= UINT32_C(0x00001fff))
1585 {
1586 offMsr = 0x400;
1587 iBit = idMsr - UINT32_C(0xc0000000);
1588 }
1589 else
1590 AssertMsgFailedReturnVoid(("Invalid MSR %#RX32\n", idMsr));
1591
1592 /*
1593 * Set the MSR read permission.
1594 */
1595 uint16_t const offMsrRead = offBitmapRead + offMsr;
1596 Assert(offMsrRead + (iBit >> 3) < offBitmapWrite);
1597 if (fMsrpm & VMXMSRPM_ALLOW_RD)
1598 {
1599#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1600 bool const fClear = !fIsNstGstVmcs ? true
1601 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrRead, iBit);
1602#else
1603 RT_NOREF2(pVCpu, fIsNstGstVmcs);
1604 bool const fClear = true;
1605#endif
1606 if (fClear)
1607 ASMBitClear(pbMsrBitmap + offMsrRead, iBit);
1608 }
1609 else
1610 ASMBitSet(pbMsrBitmap + offMsrRead, iBit);
1611
1612 /*
1613 * Set the MSR write permission.
1614 */
1615 uint16_t const offMsrWrite = offBitmapWrite + offMsr;
1616 Assert(offMsrWrite + (iBit >> 3) < X86_PAGE_4K_SIZE);
1617 if (fMsrpm & VMXMSRPM_ALLOW_WR)
1618 {
1619#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1620 bool const fClear = !fIsNstGstVmcs ? true
1621 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrWrite, iBit);
1622#else
1623 RT_NOREF2(pVCpu, fIsNstGstVmcs);
1624 bool const fClear = true;
1625#endif
1626 if (fClear)
1627 ASMBitClear(pbMsrBitmap + offMsrWrite, iBit);
1628 }
1629 else
1630 ASMBitSet(pbMsrBitmap + offMsrWrite, iBit);
1631}
1632
1633
1634/**
1635 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR
1636 * area.
1637 *
1638 * @returns VBox status code.
1639 * @param pVCpu The cross context virtual CPU structure.
1640 * @param pVmcsInfo The VMCS info. object.
1641 * @param cMsrs The number of MSRs.
1642 */
1643static int hmR0VmxSetAutoLoadStoreMsrCount(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t cMsrs)
1644{
1645 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */
1646 uint32_t const cMaxSupportedMsrs = VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc);
1647 if (RT_LIKELY(cMsrs < cMaxSupportedMsrs))
1648 {
1649 /* Commit the MSR counts to the VMCS and update the cache. */
1650 if (pVmcsInfo->cEntryMsrLoad != cMsrs)
1651 {
1652 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs);
1653 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs);
1654 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs);
1655 AssertRCReturn(rc, rc);
1656
1657 pVmcsInfo->cEntryMsrLoad = cMsrs;
1658 pVmcsInfo->cExitMsrStore = cMsrs;
1659 pVmcsInfo->cExitMsrLoad = cMsrs;
1660 }
1661 return VINF_SUCCESS;
1662 }
1663
1664 LogRel(("Auto-load/store MSR count exceeded! cMsrs=%u MaxSupported=%u\n", cMsrs, cMaxSupportedMsrs));
1665 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE;
1666 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
1667}
1668
1669
1670/**
1671 * Adds a new (or updates the value of an existing) guest/host MSR
1672 * pair to be swapped during the world-switch as part of the
1673 * auto-load/store MSR area in the VMCS.
1674 *
1675 * @returns VBox status code.
1676 * @param pVCpu The cross context virtual CPU structure.
1677 * @param pVmxTransient The VMX-transient structure.
1678 * @param idMsr The MSR.
1679 * @param uGuestMsrValue Value of the guest MSR.
1680 * @param fSetReadWrite Whether to set the guest read/write access of this
1681 * MSR (thus not causing a VM-exit).
1682 * @param fUpdateHostMsr Whether to update the value of the host MSR if
1683 * necessary.
1684 */
1685static int hmR0VmxAddAutoLoadStoreMsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t idMsr, uint64_t uGuestMsrValue,
1686 bool fSetReadWrite, bool fUpdateHostMsr)
1687{
1688 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1689 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
1690 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
1691 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
1692 uint32_t i;
1693
1694 /* Paranoia. */
1695 Assert(pGuestMsrLoad);
1696
1697 /* Check if the MSR already exists in the VM-entry MSR-load area. */
1698 for (i = 0; i < cMsrs; i++)
1699 {
1700 if (pGuestMsrLoad[i].u32Msr == idMsr)
1701 break;
1702 }
1703
1704 bool fAdded = false;
1705 if (i == cMsrs)
1706 {
1707 /* The MSR does not exist, bump the MSR count to make room for the new MSR. */
1708 ++cMsrs;
1709 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
1710 AssertMsgRCReturn(rc, ("Insufficient space to add MSR to VM-entry MSR-load/store area %u\n", idMsr), rc);
1711
1712 /* Set the guest to read/write this MSR without causing VM-exits. */
1713 if ( fSetReadWrite
1714 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
1715 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_ALLOW_RD_WR);
1716
1717 fAdded = true;
1718 }
1719
1720 /* Update the MSR value for the newly added or already existing MSR. */
1721 pGuestMsrLoad[i].u32Msr = idMsr;
1722 pGuestMsrLoad[i].u64Value = uGuestMsrValue;
1723
1724 /* Create the corresponding slot in the VM-exit MSR-store area if we use a different page. */
1725 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
1726 {
1727 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
1728 pGuestMsrStore[i].u32Msr = idMsr;
1729 pGuestMsrStore[i].u64Value = uGuestMsrValue;
1730 }
1731
1732 /* Update the corresponding slot in the host MSR area. */
1733 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
1734 Assert(pHostMsr != pVmcsInfo->pvGuestMsrLoad);
1735 Assert(pHostMsr != pVmcsInfo->pvGuestMsrStore);
1736 pHostMsr[i].u32Msr = idMsr;
1737
1738 /*
1739 * Only if the caller requests to update the host MSR value AND we've newly added the
1740 * MSR to the host MSR area do we actually update the value. Otherwise, it will be
1741 * updated by hmR0VmxUpdateAutoLoadHostMsrs().
1742 *
1743 * We do this for performance reasons since reading MSRs may be quite expensive.
1744 */
1745 if ( fAdded
1746 && fUpdateHostMsr)
1747 {
1748 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
1749 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1750 pHostMsr[i].u64Value = ASMRdMsr(idMsr);
1751 }
1752 return VINF_SUCCESS;
1753}
1754
1755
1756/**
1757 * Removes a guest/host MSR pair to be swapped during the world-switch from the
1758 * auto-load/store MSR area in the VMCS.
1759 *
1760 * @returns VBox status code.
1761 * @param pVCpu The cross context virtual CPU structure.
1762 * @param pVmxTransient The VMX-transient structure.
1763 * @param idMsr The MSR.
1764 */
1765static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t idMsr)
1766{
1767 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1768 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
1769 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
1770 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
1771
1772 for (uint32_t i = 0; i < cMsrs; i++)
1773 {
1774 /* Find the MSR. */
1775 if (pGuestMsrLoad[i].u32Msr == idMsr)
1776 {
1777 /*
1778 * If it's the last MSR, we only need to reduce the MSR count.
1779 * If it's -not- the last MSR, copy the last MSR in place of it and reduce the MSR count.
1780 */
1781 if (i < cMsrs - 1)
1782 {
1783 /* Remove it from the VM-entry MSR-load area. */
1784 pGuestMsrLoad[i].u32Msr = pGuestMsrLoad[cMsrs - 1].u32Msr;
1785 pGuestMsrLoad[i].u64Value = pGuestMsrLoad[cMsrs - 1].u64Value;
1786
1787 /* Remove it from the VM-exit MSR-store area if it's in a different page. */
1788 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
1789 {
1790 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
1791 Assert(pGuestMsrStore[i].u32Msr == idMsr);
1792 pGuestMsrStore[i].u32Msr = pGuestMsrStore[cMsrs - 1].u32Msr;
1793 pGuestMsrStore[i].u64Value = pGuestMsrStore[cMsrs - 1].u64Value;
1794 }
1795
1796 /* Remove it from the VM-exit MSR-load area. */
1797 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
1798 Assert(pHostMsr[i].u32Msr == idMsr);
1799 pHostMsr[i].u32Msr = pHostMsr[cMsrs - 1].u32Msr;
1800 pHostMsr[i].u64Value = pHostMsr[cMsrs - 1].u64Value;
1801 }
1802
1803 /* Reduce the count to reflect the removed MSR and bail. */
1804 --cMsrs;
1805 break;
1806 }
1807 }
1808
1809 /* Update the VMCS if the count changed (meaning the MSR was found and removed). */
1810 if (cMsrs != pVmcsInfo->cEntryMsrLoad)
1811 {
1812 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
1813 AssertRCReturn(rc, rc);
1814
1815 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */
1816 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1817 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR);
1818
1819 Log4Func(("Removed MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
1820 return VINF_SUCCESS;
1821 }
1822
1823 return VERR_NOT_FOUND;
1824}
1825
1826
1827/**
1828 * Checks if the specified guest MSR is part of the VM-entry MSR-load area.
1829 *
1830 * @returns @c true if found, @c false otherwise.
1831 * @param pVmcsInfo The VMCS info. object.
1832 * @param idMsr The MSR to find.
1833 */
1834static bool hmR0VmxIsAutoLoadGuestMsr(PCVMXVMCSINFO pVmcsInfo, uint32_t idMsr)
1835{
1836 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
1837 uint32_t const cMsrs = pVmcsInfo->cEntryMsrLoad;
1838 Assert(pMsrs);
1839 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
1840 for (uint32_t i = 0; i < cMsrs; i++)
1841 {
1842 if (pMsrs[i].u32Msr == idMsr)
1843 return true;
1844 }
1845 return false;
1846}
1847
1848
1849/**
1850 * Updates the value of all host MSRs in the VM-exit MSR-load area.
1851 *
1852 * @param pVCpu The cross context virtual CPU structure.
1853 * @param pVmcsInfo The VMCS info. object.
1854 *
1855 * @remarks No-long-jump zone!!!
1856 */
1857static void hmR0VmxUpdateAutoLoadHostMsrs(PCVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
1858{
1859 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1860
1861 PVMXAUTOMSR pHostMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
1862 uint32_t const cMsrs = pVmcsInfo->cExitMsrLoad;
1863 Assert(pHostMsrLoad);
1864 Assert(sizeof(*pHostMsrLoad) * cMsrs <= X86_PAGE_4K_SIZE);
1865 for (uint32_t i = 0; i < cMsrs; i++)
1866 {
1867 /*
1868 * Performance hack for the host EFER MSR. We use the cached value rather than re-read it.
1869 * Strict builds will catch mismatches in hmR0VmxCheckAutoLoadStoreMsrs(). See @bugref{7368}.
1870 */
1871 if (pHostMsrLoad[i].u32Msr == MSR_K6_EFER)
1872 pHostMsrLoad[i].u64Value = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
1873 else
1874 pHostMsrLoad[i].u64Value = ASMRdMsr(pHostMsrLoad[i].u32Msr);
1875 }
1876}
1877
1878
1879/**
1880 * Saves a set of host MSRs to allow read/write passthru access to the guest and
1881 * perform lazy restoration of the host MSRs while leaving VT-x.
1882 *
1883 * @param pVCpu The cross context virtual CPU structure.
1884 *
1885 * @remarks No-long-jump zone!!!
1886 */
1887static void hmR0VmxLazySaveHostMsrs(PVMCPU pVCpu)
1888{
1889 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1890
1891 /*
1892 * Note: If you're adding MSRs here, make sure to update the MSR-bitmap accesses in hmR0VmxSetupVmcsProcCtls().
1893 */
1894 if (!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST))
1895 {
1896 Assert(!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)); /* Guest MSRs better not be loaded now. */
1897#if HC_ARCH_BITS == 64
1898 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
1899 {
1900 pVCpu->hm.s.vmx.u64HostMsrLStar = ASMRdMsr(MSR_K8_LSTAR);
1901 pVCpu->hm.s.vmx.u64HostMsrStar = ASMRdMsr(MSR_K6_STAR);
1902 pVCpu->hm.s.vmx.u64HostMsrSfMask = ASMRdMsr(MSR_K8_SF_MASK);
1903 pVCpu->hm.s.vmx.u64HostMsrKernelGsBase = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
1904 }
1905#endif
1906 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_SAVED_HOST;
1907 }
1908}
1909
1910
1911/**
1912 * Checks whether the MSR belongs to the set of guest MSRs that we restore
1913 * lazily while leaving VT-x.
1914 *
1915 * @returns true if it does, false otherwise.
1916 * @param pVCpu The cross context virtual CPU structure.
1917 * @param idMsr The MSR to check.
1918 */
1919static bool hmR0VmxIsLazyGuestMsr(PCVMCPU pVCpu, uint32_t idMsr)
1920{
1921 NOREF(pVCpu);
1922#if HC_ARCH_BITS == 64
1923 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
1924 {
1925 switch (idMsr)
1926 {
1927 case MSR_K8_LSTAR:
1928 case MSR_K6_STAR:
1929 case MSR_K8_SF_MASK:
1930 case MSR_K8_KERNEL_GS_BASE:
1931 return true;
1932 }
1933 }
1934#else
1935 RT_NOREF(pVCpu, idMsr);
1936#endif
1937 return false;
1938}
1939
1940
1941/**
1942 * Loads a set of guests MSRs to allow read/passthru to the guest.
1943 *
1944 * The name of this function is slightly confusing. This function does NOT
1945 * postpone loading, but loads the MSR right now. "hmR0VmxLazy" is simply a
1946 * common prefix for functions dealing with "lazy restoration" of the shared
1947 * MSRs.
1948 *
1949 * @param pVCpu The cross context virtual CPU structure.
1950 *
1951 * @remarks No-long-jump zone!!!
1952 */
1953static void hmR0VmxLazyLoadGuestMsrs(PVMCPU pVCpu)
1954{
1955 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1956 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
1957
1958 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
1959#if HC_ARCH_BITS == 64
1960 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
1961 {
1962 /*
1963 * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
1964 * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
1965 * we can skip a few MSR writes.
1966 *
1967 * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
1968 * guest MSR values in the guest-CPU context might be different to what's currently
1969 * loaded in the CPU. In either case, we need to write the new guest MSR values to the
1970 * CPU, see @bugref{8728}.
1971 */
1972 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
1973 if ( !(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
1974 && pCtx->msrKERNELGSBASE == pVCpu->hm.s.vmx.u64HostMsrKernelGsBase
1975 && pCtx->msrLSTAR == pVCpu->hm.s.vmx.u64HostMsrLStar
1976 && pCtx->msrSTAR == pVCpu->hm.s.vmx.u64HostMsrStar
1977 && pCtx->msrSFMASK == pVCpu->hm.s.vmx.u64HostMsrSfMask)
1978 {
1979#ifdef VBOX_STRICT
1980 Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pCtx->msrKERNELGSBASE);
1981 Assert(ASMRdMsr(MSR_K8_LSTAR) == pCtx->msrLSTAR);
1982 Assert(ASMRdMsr(MSR_K6_STAR) == pCtx->msrSTAR);
1983 Assert(ASMRdMsr(MSR_K8_SF_MASK) == pCtx->msrSFMASK);
1984#endif
1985 }
1986 else
1987 {
1988 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE);
1989 ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR);
1990 ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR);
1991 ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK);
1992 }
1993 }
1994#endif
1995 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
1996}
1997
1998
1999/**
2000 * Performs lazy restoration of the set of host MSRs if they were previously
2001 * loaded with guest MSR values.
2002 *
2003 * @param pVCpu The cross context virtual CPU structure.
2004 *
2005 * @remarks No-long-jump zone!!!
2006 * @remarks The guest MSRs should have been saved back into the guest-CPU
2007 * context by hmR0VmxImportGuestState()!!!
2008 */
2009static void hmR0VmxLazyRestoreHostMsrs(PVMCPU pVCpu)
2010{
2011 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2012 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2013
2014 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2015 {
2016 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2017#if HC_ARCH_BITS == 64
2018 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2019 {
2020 ASMWrMsr(MSR_K8_LSTAR, pVCpu->hm.s.vmx.u64HostMsrLStar);
2021 ASMWrMsr(MSR_K6_STAR, pVCpu->hm.s.vmx.u64HostMsrStar);
2022 ASMWrMsr(MSR_K8_SF_MASK, pVCpu->hm.s.vmx.u64HostMsrSfMask);
2023 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pVCpu->hm.s.vmx.u64HostMsrKernelGsBase);
2024 }
2025#endif
2026 }
2027 pVCpu->hm.s.vmx.fLazyMsrs &= ~(VMX_LAZY_MSRS_LOADED_GUEST | VMX_LAZY_MSRS_SAVED_HOST);
2028}
2029
2030
2031/**
2032 * Verifies that our cached values of the VMCS fields are all consistent with
2033 * what's actually present in the VMCS.
2034 *
2035 * @returns VBox status code.
2036 * @retval VINF_SUCCESS if all our caches match their respective VMCS fields.
2037 * @retval VERR_VMX_VMCS_FIELD_CACHE_INVALID if a cache field doesn't match the
2038 * VMCS content. HMCPU error-field is
2039 * updated, see VMX_VCI_XXX.
2040 * @param pVCpu The cross context virtual CPU structure.
2041 * @param pVmcsInfo The VMCS info. object.
2042 */
2043static int hmR0VmxCheckVmcsCtls(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2044{
2045 uint32_t u32Val;
2046 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
2047 AssertRCReturn(rc, rc);
2048 AssertMsgReturnStmt(pVmcsInfo->u32EntryCtls == u32Val,
2049 ("Cache=%#RX32 VMCS=%#RX32\n", pVmcsInfo->u32EntryCtls, u32Val),
2050 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_ENTRY,
2051 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2052
2053 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val);
2054 AssertRCReturn(rc, rc);
2055 AssertMsgReturnStmt(pVmcsInfo->u32ExitCtls == u32Val,
2056 ("Cache=%#RX32 VMCS=%#RX32\n", pVmcsInfo->u32ExitCtls, u32Val),
2057 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_EXIT,
2058 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2059
2060 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val);
2061 AssertRCReturn(rc, rc);
2062 AssertMsgReturnStmt(pVmcsInfo->u32PinCtls == u32Val,
2063 ("Cache=%#RX32 VMCS=%#RX32\n", pVmcsInfo->u32PinCtls, u32Val),
2064 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PIN_EXEC,
2065 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2066
2067 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val);
2068 AssertRCReturn(rc, rc);
2069 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls == u32Val,
2070 ("Cache=%#RX32 VMCS=%#RX32\n", pVmcsInfo->u32ProcCtls, u32Val),
2071 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC,
2072 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2073
2074 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
2075 {
2076 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val);
2077 AssertRCReturn(rc, rc);
2078 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls2 == u32Val,
2079 ("Cache=%#RX32 VMCS=%#RX32\n", pVmcsInfo->u32ProcCtls2, u32Val),
2080 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC2,
2081 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2082 }
2083
2084 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val);
2085 AssertRCReturn(rc, rc);
2086 AssertMsgReturnStmt(pVmcsInfo->u32XcptBitmap == u32Val,
2087 ("Cache=%#RX32 VMCS=%#RX32\n", pVmcsInfo->u32XcptBitmap, u32Val),
2088 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_XCPT_BITMAP,
2089 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2090
2091 uint64_t u64Val;
2092 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, &u64Val);
2093 AssertRCReturn(rc, rc);
2094 AssertMsgReturnStmt(pVmcsInfo->u64TscOffset == u64Val,
2095 ("Cache=%#RX64 VMCS=%#RX64\n", pVmcsInfo->u64TscOffset, u64Val),
2096 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_TSC_OFFSET,
2097 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2098
2099 return VINF_SUCCESS;
2100}
2101
2102
2103#ifdef VBOX_STRICT
2104/**
2105 * Verifies that our cached host EFER MSR value has not changed since we cached it.
2106 *
2107 * @param pVCpu The cross context virtual CPU structure.
2108 * @param pVmcsInfo The VMCS info. object.
2109 */
2110static void hmR0VmxCheckHostEferMsr(PCVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2111{
2112 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2113
2114 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2115 {
2116 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2117 uint64_t const uHostEferMsrCache = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2118 uint64_t uVmcsEferMsrVmcs;
2119 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2120 AssertRC(rc);
2121
2122 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2123 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2124 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2125 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2126 }
2127}
2128
2129
2130/**
2131 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2132 * VMCS are correct.
2133 *
2134 * @param pVCpu The cross context virtual CPU structure.
2135 * @param pVmcsInfo The VMCS info. object.
2136 */
2137static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2138{
2139 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2140
2141 /* Read the various MSR-area counts from the VMCS. */
2142 uint32_t cEntryLoadMsrs;
2143 uint32_t cExitStoreMsrs;
2144 uint32_t cExitLoadMsrs;
2145 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2146 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2147 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2148
2149 /* Verify all the MSR counts are the same. */
2150 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2151 Assert(cExitStoreMsrs == cExitLoadMsrs);
2152 uint32_t const cMsrs = cExitLoadMsrs;
2153
2154 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2155 Assert(cMsrs < VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc));
2156
2157 /* Verify the MSR counts are within the allocated page size. */
2158 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2159
2160 /* Verify the relevant contents of the MSR areas match. */
2161 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2162 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2163 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2164 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2165 for (uint32_t i = 0; i < cMsrs; i++)
2166 {
2167 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2168 if (fSeparateExitMsrStorePage)
2169 {
2170 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2171 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2172 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2173 }
2174
2175 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2176 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2177 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2178
2179 uint64_t const u64Msr = ASMRdMsr(pHostMsrLoad->u32Msr);
2180 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64Msr,
2181 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2182 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64Msr, cMsrs));
2183
2184 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2185 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2186 {
2187 uint32_t const fMsrpm = HMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2188 if (pGuestMsrLoad->u32Msr == MSR_K6_EFER)
2189 {
2190 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2191 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2192 }
2193 else
2194 {
2195 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_ALLOW_RD_WR) == VMXMSRPM_ALLOW_RD_WR,
2196 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2197 }
2198 }
2199
2200 /* Move to the next MSR. */
2201 pHostMsrLoad++;
2202 pGuestMsrLoad++;
2203 pGuestMsrStore++;
2204 }
2205}
2206#endif /* VBOX_STRICT */
2207
2208
2209/**
2210 * Flushes the TLB using EPT.
2211 *
2212 * @returns VBox status code.
2213 * @param pVCpu The cross context virtual CPU structure of the calling
2214 * EMT. Can be NULL depending on @a enmTlbFlush.
2215 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2216 * enmTlbFlush.
2217 * @param enmTlbFlush Type of flush.
2218 *
2219 * @remarks Caller is responsible for making sure this function is called only
2220 * when NestedPaging is supported and providing @a enmTlbFlush that is
2221 * supported by the CPU.
2222 * @remarks Can be called with interrupts disabled.
2223 */
2224static void hmR0VmxFlushEpt(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2225{
2226 uint64_t au64Descriptor[2];
2227 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2228 au64Descriptor[0] = 0;
2229 else
2230 {
2231 Assert(pVCpu);
2232 Assert(pVmcsInfo);
2233 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2234 }
2235 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2236
2237 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2238 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2239
2240 if ( RT_SUCCESS(rc)
2241 && pVCpu)
2242 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2243}
2244
2245
2246/**
2247 * Flushes the TLB using VPID.
2248 *
2249 * @returns VBox status code.
2250 * @param pVCpu The cross context virtual CPU structure of the calling
2251 * EMT. Can be NULL depending on @a enmTlbFlush.
2252 * @param enmTlbFlush Type of flush.
2253 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2254 * on @a enmTlbFlush).
2255 *
2256 * @remarks Can be called with interrupts disabled.
2257 */
2258static void hmR0VmxFlushVpid(PVMCPU pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2259{
2260 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid);
2261
2262 uint64_t au64Descriptor[2];
2263 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2264 {
2265 au64Descriptor[0] = 0;
2266 au64Descriptor[1] = 0;
2267 }
2268 else
2269 {
2270 AssertPtr(pVCpu);
2271 AssertMsg(pVCpu->hm.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2272 AssertMsg(pVCpu->hm.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2273 au64Descriptor[0] = pVCpu->hm.s.uCurrentAsid;
2274 au64Descriptor[1] = GCPtr;
2275 }
2276
2277 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2278 AssertMsg(rc == VINF_SUCCESS,
2279 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hm.s.uCurrentAsid : 0, GCPtr, rc));
2280
2281 if ( RT_SUCCESS(rc)
2282 && pVCpu)
2283 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2284 NOREF(rc);
2285}
2286
2287
2288/**
2289 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2290 * otherwise there is nothing really to invalidate.
2291 *
2292 * @returns VBox status code.
2293 * @param pVCpu The cross context virtual CPU structure.
2294 * @param GCVirt Guest virtual address of the page to invalidate.
2295 */
2296VMMR0DECL(int) VMXR0InvalidatePage(PVMCPU pVCpu, RTGCPTR GCVirt)
2297{
2298 AssertPtr(pVCpu);
2299 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2300
2301 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2302 {
2303 /*
2304 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2305 * the EPT case. See @bugref{6043} and @bugref{6177}.
2306 *
2307 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2308 * as this function maybe called in a loop with individual addresses.
2309 */
2310 PVM pVM = pVCpu->CTX_SUFF(pVM);
2311 if (pVM->hm.s.vmx.fVpid)
2312 {
2313 bool fVpidFlush = RT_BOOL(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
2314
2315#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
2316 /*
2317 * Workaround Erratum BV75, AAJ159 and others that affect several Intel CPUs
2318 * where executing INVVPID outside 64-bit mode does not flush translations of
2319 * 64-bit linear addresses, see @bugref{6208#c72}.
2320 */
2321 if (RT_HI_U32(GCVirt))
2322 fVpidFlush = false;
2323#endif
2324
2325 if (fVpidFlush)
2326 {
2327 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2328 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2329 }
2330 else
2331 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2332 }
2333 else if (pVM->hm.s.fNestedPaging)
2334 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2335 }
2336
2337 return VINF_SUCCESS;
2338}
2339
2340
2341/**
2342 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2343 * case where neither EPT nor VPID is supported by the CPU.
2344 *
2345 * @param pHostCpu The HM physical-CPU structure.
2346 * @param pVCpu The cross context virtual CPU structure.
2347 *
2348 * @remarks Called with interrupts disabled.
2349 */
2350static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPU pVCpu)
2351{
2352 AssertPtr(pVCpu);
2353 AssertPtr(pHostCpu);
2354
2355 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2356
2357 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2358 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2359 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2360 pVCpu->hm.s.fForceTLBFlush = false;
2361 return;
2362}
2363
2364
2365/**
2366 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
2367 *
2368 * @param pHostCpu The HM physical-CPU structure.
2369 * @param pVCpu The cross context virtual CPU structure.
2370 * @param pVmcsInfo The VMCS info. object.
2371 *
2372 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
2373 * nomenclature. The reason is, to avoid confusion in compare statements
2374 * since the host-CPU copies are named "ASID".
2375 *
2376 * @remarks Called with interrupts disabled.
2377 */
2378static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2379{
2380#ifdef VBOX_WITH_STATISTICS
2381 bool fTlbFlushed = false;
2382# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
2383# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
2384 if (!fTlbFlushed) \
2385 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
2386 } while (0)
2387#else
2388# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
2389# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
2390#endif
2391
2392 AssertPtr(pVCpu);
2393 AssertPtr(pHostCpu);
2394 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2395
2396 PVM pVM = pVCpu->CTX_SUFF(pVM);
2397 AssertMsg(pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid,
2398 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
2399 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hm.s.fNestedPaging, pVM->hm.s.vmx.fVpid));
2400
2401 /*
2402 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
2403 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
2404 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
2405 * cannot reuse the current ASID anymore.
2406 */
2407 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
2408 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
2409 {
2410 ++pHostCpu->uCurrentAsid;
2411 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
2412 {
2413 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
2414 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
2415 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
2416 }
2417
2418 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
2419 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2420 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2421
2422 /*
2423 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
2424 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
2425 */
2426 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2427 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
2428 HMVMX_SET_TAGGED_TLB_FLUSHED();
2429 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2430 }
2431 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
2432 {
2433 /*
2434 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
2435 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
2436 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
2437 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
2438 * mappings, see @bugref{6568}.
2439 *
2440 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
2441 */
2442 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2443 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
2444 HMVMX_SET_TAGGED_TLB_FLUSHED();
2445 }
2446
2447 pVCpu->hm.s.fForceTLBFlush = false;
2448 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
2449
2450 Assert(pVCpu->hm.s.idLastCpu == pHostCpu->idCpu);
2451 Assert(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes);
2452 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
2453 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
2454 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
2455 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
2456 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
2457 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
2458 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
2459
2460 /* Update VMCS with the VPID. */
2461 int rc = VMXWriteVmcs32(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
2462 AssertRC(rc);
2463
2464#undef HMVMX_SET_TAGGED_TLB_FLUSHED
2465}
2466
2467
2468/**
2469 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
2470 *
2471 * @param pHostCpu The HM physical-CPU structure.
2472 * @param pVCpu The cross context virtual CPU structure.
2473 * @param pVmcsInfo The VMCS info. object.
2474 *
2475 * @remarks Called with interrupts disabled.
2476 */
2477static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2478{
2479 AssertPtr(pVCpu);
2480 AssertPtr(pHostCpu);
2481 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2482 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
2483 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
2484
2485 /*
2486 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
2487 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
2488 */
2489 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
2490 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
2491 {
2492 pVCpu->hm.s.fForceTLBFlush = true;
2493 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
2494 }
2495
2496 /* Check for explicit TLB flushes. */
2497 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
2498 {
2499 pVCpu->hm.s.fForceTLBFlush = true;
2500 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
2501 }
2502
2503 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2504 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2505
2506 if (pVCpu->hm.s.fForceTLBFlush)
2507 {
2508 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hm.s.vmx.enmTlbFlushEpt);
2509 pVCpu->hm.s.fForceTLBFlush = false;
2510 }
2511}
2512
2513
2514/**
2515 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
2516 *
2517 * @param pHostCpu The HM physical-CPU structure.
2518 * @param pVCpu The cross context virtual CPU structure.
2519 *
2520 * @remarks Called with interrupts disabled.
2521 */
2522static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPU pVCpu)
2523{
2524 AssertPtr(pVCpu);
2525 AssertPtr(pHostCpu);
2526 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2527 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
2528 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
2529
2530 /*
2531 * Force a TLB flush for the first world switch if the current CPU differs from the one we
2532 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
2533 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
2534 * cannot reuse the current ASID anymore.
2535 */
2536 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
2537 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
2538 {
2539 pVCpu->hm.s.fForceTLBFlush = true;
2540 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
2541 }
2542
2543 /* Check for explicit TLB flushes. */
2544 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
2545 {
2546 /*
2547 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
2548 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
2549 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
2550 * include fExplicitFlush's too) - an obscure corner case.
2551 */
2552 pVCpu->hm.s.fForceTLBFlush = true;
2553 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
2554 }
2555
2556 PVM pVM = pVCpu->CTX_SUFF(pVM);
2557 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2558 if (pVCpu->hm.s.fForceTLBFlush)
2559 {
2560 ++pHostCpu->uCurrentAsid;
2561 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
2562 {
2563 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
2564 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
2565 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
2566 }
2567
2568 pVCpu->hm.s.fForceTLBFlush = false;
2569 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2570 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
2571 if (pHostCpu->fFlushAsidBeforeUse)
2572 {
2573 if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
2574 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
2575 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2576 {
2577 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
2578 pHostCpu->fFlushAsidBeforeUse = false;
2579 }
2580 else
2581 {
2582 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
2583 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
2584 }
2585 }
2586 }
2587
2588 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
2589 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
2590 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
2591 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
2592 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
2593 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
2594 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
2595
2596 int rc = VMXWriteVmcs32(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
2597 AssertRC(rc);
2598}
2599
2600
2601/**
2602 * Flushes the guest TLB entry based on CPU capabilities.
2603 *
2604 * @param pHostCpu The HM physical-CPU structure.
2605 * @param pVCpu The cross context virtual CPU structure.
2606 * @param pVmcsInfo The VMCS info. object.
2607 *
2608 * @remarks Called with interrupts disabled.
2609 */
2610static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
2611{
2612#ifdef HMVMX_ALWAYS_FLUSH_TLB
2613 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2614#endif
2615 PVM pVM = pVCpu->CTX_SUFF(pVM);
2616 switch (pVM->hm.s.vmx.enmTlbFlushType)
2617 {
2618 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
2619 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
2620 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
2621 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
2622 default:
2623 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
2624 break;
2625 }
2626 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
2627}
2628
2629
2630/**
2631 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
2632 * TLB entries from the host TLB before VM-entry.
2633 *
2634 * @returns VBox status code.
2635 * @param pVM The cross context VM structure.
2636 */
2637static int hmR0VmxSetupTaggedTlb(PVM pVM)
2638{
2639 /*
2640 * Determine optimal flush type for nested paging.
2641 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
2642 * unrestricted guest execution (see hmR3InitFinalizeR0()).
2643 */
2644 if (pVM->hm.s.fNestedPaging)
2645 {
2646 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
2647 {
2648 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
2649 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
2650 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
2651 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
2652 else
2653 {
2654 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
2655 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
2656 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
2657 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2658 }
2659
2660 /* Make sure the write-back cacheable memory type for EPT is supported. */
2661 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
2662 {
2663 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
2664 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
2665 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2666 }
2667
2668 /* EPT requires a page-walk length of 4. */
2669 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
2670 {
2671 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
2672 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
2673 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2674 }
2675 }
2676 else
2677 {
2678 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
2679 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
2680 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
2681 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2682 }
2683 }
2684
2685 /*
2686 * Determine optimal flush type for VPID.
2687 */
2688 if (pVM->hm.s.vmx.fVpid)
2689 {
2690 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
2691 {
2692 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
2693 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
2694 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
2695 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
2696 else
2697 {
2698 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
2699 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
2700 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
2701 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
2702 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
2703 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
2704 pVM->hm.s.vmx.fVpid = false;
2705 }
2706 }
2707 else
2708 {
2709 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
2710 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
2711 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
2712 pVM->hm.s.vmx.fVpid = false;
2713 }
2714 }
2715
2716 /*
2717 * Setup the handler for flushing tagged-TLBs.
2718 */
2719 if (pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid)
2720 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
2721 else if (pVM->hm.s.fNestedPaging)
2722 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
2723 else if (pVM->hm.s.vmx.fVpid)
2724 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
2725 else
2726 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
2727 return VINF_SUCCESS;
2728}
2729
2730
2731/**
2732 * Sets up the virtual-APIC page address for the VMCS.
2733 *
2734 * @returns VBox status code.
2735 * @param pVCpu The cross context virtual CPU structure.
2736 * @param pVmcsInfo The VMCS info. object.
2737 */
2738DECLINLINE(int) hmR0VmxSetupVmcsVirtApicAddr(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2739{
2740 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
2741 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
2742 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
2743 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
2744 return VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
2745}
2746
2747
2748/**
2749 * Sets up the MSR-bitmap address for the VMCS.
2750 *
2751 * @returns VBox status code.
2752 * @param pVCpu The cross context virtual CPU structure.
2753 * @param pVmcsInfo The VMCS info. object.
2754 */
2755DECLINLINE(int) hmR0VmxSetupVmcsMsrBitmapAddr(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2756{
2757 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
2758 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
2759 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
2760 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
2761 return VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
2762}
2763
2764
2765/**
2766 * Sets up the APIC-access page address for the VMCS.
2767 *
2768 * @returns VBox status code.
2769 * @param pVCpu The cross context virtual CPU structure.
2770 */
2771DECLINLINE(int) hmR0VmxSetupVmcsApicAccessAddr(PVMCPU pVCpu)
2772{
2773 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysApicAccess;
2774 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
2775 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
2776 return VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
2777}
2778
2779
2780/**
2781 * Sets up the VMCS link pointer for the VMCS.
2782 *
2783 * @returns VBox status code.
2784 * @param pVCpu The cross context virtual CPU structure.
2785 * @param pVmcsInfo The VMCS info. object.
2786 */
2787DECLINLINE(int) hmR0VmxSetupVmcsLinkPtr(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
2788{
2789 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
2790 uint64_t const u64VmcsLinkPtr = pVmcsInfo->u64VmcsLinkPtr;
2791 Assert(u64VmcsLinkPtr == UINT64_C(0xffffffffffffffff)); /* Bits 63:0 MB1. */
2792 return VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, u64VmcsLinkPtr);
2793}
2794
2795
2796/**
2797 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
2798 * in the VMCS.
2799 *
2800 * @returns VBox status code.
2801 * @param pVCpu The cross context virtual CPU structure.
2802 * @param pVmcsInfo The VMCS info. object.
2803 */
2804DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
2805{
2806 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
2807
2808 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
2809 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
2810 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
2811
2812 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
2813 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
2814 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
2815
2816 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
2817 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
2818 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
2819
2820 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad);
2821 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore);
2822 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad);
2823 AssertRCReturn(rc, rc);
2824 return VINF_SUCCESS;
2825}
2826
2827
2828/**
2829 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
2830 *
2831 * @param pVCpu The cross context virtual CPU structure.
2832 * @param pVmcsInfo The VMCS info. object.
2833 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2834 */
2835static void hmR0VmxSetupVmcsMsrPermissions(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2836{
2837 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
2838
2839 /*
2840 * The guest can access the following MSRs (read, write) without causing
2841 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
2842 */
2843 PVM pVM = pVCpu->CTX_SUFF(pVM);
2844 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
2845 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
2846 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
2847 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
2848 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
2849
2850 /*
2851 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
2852 * associated with then. We never need to intercept access (writes need to be
2853 * executed without causing a VM-exit, reads will #GP fault anyway).
2854 *
2855 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
2856 * read/write them. We swap the the guest/host MSR value using the
2857 * auto-load/store MSR area.
2858 */
2859 if (pVM->cpum.ro.GuestFeatures.fIbpb)
2860 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
2861 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
2862 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
2863 if (pVM->cpum.ro.GuestFeatures.fIbrs)
2864 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
2865
2866#if HC_ARCH_BITS == 64
2867 /*
2868 * Allow full read/write access for the following MSRs (mandatory for VT-x)
2869 * required for 64-bit guests.
2870 */
2871 if (pVM->hm.s.fAllow64BitGuests)
2872 {
2873 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
2874 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
2875 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
2876 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
2877 }
2878#endif
2879
2880 /*
2881 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
2882 */
2883#ifdef VBOX_STRICT
2884 Assert(pVmcsInfo->pvMsrBitmap);
2885 uint32_t const fMsrpmEfer = HMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
2886 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
2887#endif
2888}
2889
2890
2891/**
2892 * Sets up pin-based VM-execution controls in the VMCS.
2893 *
2894 * @returns VBox status code.
2895 * @param pVCpu The cross context virtual CPU structure.
2896 * @param pVmcsInfo The VMCS info. object.
2897 */
2898static int hmR0VmxSetupVmcsPinCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
2899{
2900 PVM pVM = pVCpu->CTX_SUFF(pVM);
2901 uint32_t fVal = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0; /* Bits set here must always be set. */
2902 uint32_t const fZap = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
2903
2904 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
2905 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
2906
2907 if (pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
2908 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
2909
2910 /* Enable the VMX-preemption timer. */
2911 if (pVM->hm.s.vmx.fUsePreemptTimer)
2912 {
2913 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
2914 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
2915 }
2916
2917#if 0
2918 /* Enable posted-interrupt processing. */
2919 if (pVM->hm.s.fPostedIntrs)
2920 {
2921 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
2922 Assert(pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
2923 fVal |= VMX_PIN_CTL_POSTED_INT;
2924 }
2925#endif
2926
2927 if ((fVal & fZap) != fVal)
2928 {
2929 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
2930 pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0, fVal, fZap));
2931 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
2932 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2933 }
2934
2935 /* Commit it to the VMCS and update our cache. */
2936 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
2937 AssertRCReturn(rc, rc);
2938 pVmcsInfo->u32PinCtls = fVal;
2939
2940 return VINF_SUCCESS;
2941}
2942
2943
2944/**
2945 * Sets up secondary processor-based VM-execution controls in the VMCS.
2946 *
2947 * @returns VBox status code.
2948 * @param pVCpu The cross context virtual CPU structure.
2949 * @param pVmcsInfo The VMCS info. object.
2950 */
2951static int hmR0VmxSetupVmcsProcCtls2(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
2952{
2953 PVM pVM = pVCpu->CTX_SUFF(pVM);
2954 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
2955 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
2956
2957 /* WBINVD causes a VM-exit. */
2958 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
2959 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
2960
2961 /* Enable EPT (aka nested-paging). */
2962 if (pVM->hm.s.fNestedPaging)
2963 fVal |= VMX_PROC_CTLS2_EPT;
2964
2965 /* Enable the INVPCID instruction if supported by the hardware and we expose
2966 it to the guest. Without this, guest executing INVPCID would cause a #UD. */
2967 if ( (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID)
2968 && pVM->cpum.ro.GuestFeatures.fInvpcid)
2969 fVal |= VMX_PROC_CTLS2_INVPCID;
2970
2971 /* Enable VPID. */
2972 if (pVM->hm.s.vmx.fVpid)
2973 fVal |= VMX_PROC_CTLS2_VPID;
2974
2975 /* Enable unrestricted guest execution. */
2976 if (pVM->hm.s.vmx.fUnrestrictedGuest)
2977 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
2978
2979#if 0
2980 if (pVM->hm.s.fVirtApicRegs)
2981 {
2982 /* Enable APIC-register virtualization. */
2983 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
2984 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
2985
2986 /* Enable virtual-interrupt delivery. */
2987 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
2988 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
2989 }
2990#endif
2991
2992 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is where the TPR shadow resides. */
2993 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
2994 * done dynamically. */
2995 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
2996 {
2997 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
2998 int rc = hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
2999 AssertRCReturn(rc, rc);
3000 }
3001
3002 /* Enable the RDTSCP instruction if supported by the hardware and we expose
3003 it to the guest. Without this, guest executing RDTSCP would cause a #UD. */
3004 if ( (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP)
3005 && pVM->cpum.ro.GuestFeatures.fRdTscP)
3006 fVal |= VMX_PROC_CTLS2_RDTSCP;
3007
3008 /* Enable Pause-Loop exiting. */
3009 if ( pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT
3010 && pVM->hm.s.vmx.cPleGapTicks
3011 && pVM->hm.s.vmx.cPleWindowTicks)
3012 {
3013 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3014
3015 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks);
3016 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks);
3017 AssertRCReturn(rc, rc);
3018 }
3019
3020 if ((fVal & fZap) != fVal)
3021 {
3022 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3023 pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0, fVal, fZap));
3024 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3025 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3026 }
3027
3028 /* Commit it to the VMCS and update our cache. */
3029 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3030 AssertRCReturn(rc, rc);
3031 pVmcsInfo->u32ProcCtls2 = fVal;
3032
3033 return VINF_SUCCESS;
3034}
3035
3036
3037/**
3038 * Sets up processor-based VM-execution controls in the VMCS.
3039 *
3040 * @returns VBox status code.
3041 * @param pVCpu The cross context virtual CPU structure.
3042 * @param pVmcsInfo The VMCS info. object.
3043 */
3044static int hmR0VmxSetupVmcsProcCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3045{
3046 PVM pVM = pVCpu->CTX_SUFF(pVM);
3047
3048 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3049 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3050
3051 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3052 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3053 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3054 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3055 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3056 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3057 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3058
3059 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3060 if ( !(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3061 || (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3062 {
3063 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3064 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3065 }
3066
3067 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3068 if (!pVM->hm.s.fNestedPaging)
3069 {
3070 Assert(!pVM->hm.s.vmx.fUnrestrictedGuest);
3071 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3072 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3073 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3074 }
3075
3076 /* Use TPR shadowing if supported by the CPU. */
3077 if ( PDMHasApic(pVM)
3078 && pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
3079 {
3080 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
3081 /* CR8 writes cause a VM-exit based on TPR threshold. */
3082 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
3083 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
3084 int rc = hmR0VmxSetupVmcsVirtApicAddr(pVCpu, pVmcsInfo);
3085 AssertRCReturn(rc, rc);
3086 }
3087 else
3088 {
3089 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
3090 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
3091 if (pVM->hm.s.fAllow64BitGuests)
3092 {
3093 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
3094 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
3095 }
3096 }
3097
3098 /* Use MSR-bitmaps if supported by the CPU. */
3099 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3100 {
3101 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
3102 int rc = hmR0VmxSetupVmcsMsrBitmapAddr(pVCpu, pVmcsInfo);
3103 AssertRCReturn(rc, rc);
3104 }
3105
3106 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
3107 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3108 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
3109
3110 if ((fVal & fZap) != fVal)
3111 {
3112 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3113 pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0, fVal, fZap));
3114 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
3115 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3116 }
3117
3118 /* Commit it to the VMCS and update our cache. */
3119 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, fVal);
3120 AssertRCReturn(rc, rc);
3121 pVmcsInfo->u32ProcCtls = fVal;
3122
3123 /* Set up MSR permissions that don't change through the lifetime of the VM. */
3124 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3125 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo, false /* fIsNstGstVmcs */);
3126
3127 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
3128 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3129 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
3130
3131 /* Sanity check, should not really happen. */
3132 if (RT_LIKELY(!pVM->hm.s.vmx.fUnrestrictedGuest))
3133 { /* likely */ }
3134 else
3135 {
3136 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
3137 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3138 }
3139
3140 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
3141 return VINF_SUCCESS;
3142}
3143
3144
3145/**
3146 * Sets up miscellaneous (everything other than Pin, Processor and secondary
3147 * Processor-based VM-execution) control fields in the VMCS.
3148 *
3149 * @returns VBox status code.
3150 * @param pVCpu The cross context virtual CPU structure.
3151 * @param pVmcsInfo The VMCS info. object.
3152 */
3153static int hmR0VmxSetupVmcsMiscCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3154{
3155 /* Set the auto-load/store MSR area addresses in the VMCS. */
3156 int rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVCpu, pVmcsInfo);
3157 if (RT_SUCCESS(rc))
3158 {
3159 /* Set the VMCS link pointer in the VMCS. */
3160 rc = hmR0VmxSetupVmcsLinkPtr(pVCpu, pVmcsInfo);
3161 if (RT_SUCCESS(rc))
3162 {
3163 /* Set the CR0/CR4 guest/host mask. */
3164 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
3165 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
3166 rc = VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
3167 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
3168 if (RT_SUCCESS(rc))
3169 {
3170 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
3171 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
3172 return VINF_SUCCESS;
3173 }
3174 LogRelFunc(("Failed to initialize VMCS CR0/CR4 guest/host mask. rc=%Rrc\n", rc));
3175 }
3176 else
3177 LogRelFunc(("Failed to initialize VMCS link pointer. rc=%Rrc\n", rc));
3178 }
3179 else
3180 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
3181 return rc;
3182}
3183
3184
3185/**
3186 * Sets up the initial exception bitmap in the VMCS based on static conditions.
3187 *
3188 * We shall setup those exception intercepts that don't change during the
3189 * lifetime of the VM here. The rest are done dynamically while loading the
3190 * guest state.
3191 *
3192 * @returns VBox status code.
3193 * @param pVCpu The cross context virtual CPU structure.
3194 * @param pVmcsInfo The VMCS info. object.
3195 */
3196static int hmR0VmxSetupVmcsXcptBitmap(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3197{
3198 /*
3199 * The following exceptions are always intercepted:
3200 *
3201 * #AC - To prevent the guest from hanging the CPU.
3202 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
3203 * recursive #DBs can cause a CPU hang.
3204 * #PF - To sync our shadow page tables when nested-paging is not used.
3205 */
3206 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging;
3207 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
3208 | RT_BIT(X86_XCPT_DB)
3209 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
3210
3211 /* Commit it to the VMCS. */
3212 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
3213 AssertRCReturn(rc, rc);
3214
3215 /* Update our cache of the exception bitmap. */
3216 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
3217 return VINF_SUCCESS;
3218}
3219
3220
3221#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3222/**
3223 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
3224 *
3225 * @returns VBox status code.
3226 * @param pVCpu The cross context virtual CPU structure.
3227 * @param pVmcsInfo The VMCS info. object.
3228 */
3229static int hmR0VmxSetupVmcsCtlsNested(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3230{
3231 PVM pVM = pVCpu->CTX_SUFF(pVM);
3232 int rc = hmR0VmxSetupVmcsLinkPtr(pVCpu, pVmcsInfo);
3233 if (RT_SUCCESS(rc))
3234 {
3235 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVCpu, pVmcsInfo);
3236 if (RT_SUCCESS(rc))
3237 {
3238 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3239 rc = hmR0VmxSetupVmcsMsrBitmapAddr(pVCpu, pVmcsInfo);
3240 if (RT_SUCCESS(rc))
3241 {
3242 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3243 rc = hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3244 if (RT_SUCCESS(rc))
3245 return VINF_SUCCESS;
3246
3247 LogRelFunc(("Failed to set up the APIC-access address in the nested-guest VMCS. rc=%Rrc\n", rc));
3248 }
3249 else
3250 LogRelFunc(("Failed to set up the MSR-bitmap address in the nested-guest VMCS. rc=%Rrc\n", rc));
3251 }
3252 else
3253 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
3254 }
3255 else
3256 LogRelFunc(("Failed to set up the auto-load/store MSR addresses in the nested-guest VMCS. rc=%Rrc\n", rc));
3257
3258 return rc;
3259}
3260#endif
3261
3262
3263/**
3264 * Sets up the VMCS for executing a guest (or nested-guest) using hardware-assisted
3265 * VMX.
3266 *
3267 * @returns VBox status code.
3268 * @param pVCpu The cross context virtual CPU structure.
3269 * @param pVmcsInfo The VMCS info. object.
3270 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
3271 */
3272static int hmR0VmxSetupVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
3273{
3274 Assert(pVmcsInfo);
3275 Assert(pVmcsInfo->pvVmcs);
3276 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
3277
3278 /* Set the CPU specified revision identifier at the beginning of the VMCS structure. */
3279 PVM pVM = pVCpu->CTX_SUFF(pVM);
3280 *(uint32_t *)pVmcsInfo->pvVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
3281 const char * const pszVmcs = fIsNstGstVmcs ? "nested-guest VMCS" : "guest VMCS";
3282
3283 LogFlowFunc(("\n"));
3284
3285 /*
3286 * Initialize the VMCS using VMCLEAR before loading the VMCS.
3287 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
3288 */
3289 int rc = hmR0VmxClearVmcs(pVmcsInfo);
3290 if (RT_SUCCESS(rc))
3291 {
3292 rc = hmR0VmxLoadVmcs(pVmcsInfo);
3293 if (RT_SUCCESS(rc))
3294 {
3295 if (!fIsNstGstVmcs)
3296 {
3297 rc = hmR0VmxSetupVmcsPinCtls(pVCpu, pVmcsInfo);
3298 if (RT_SUCCESS(rc))
3299 {
3300 rc = hmR0VmxSetupVmcsProcCtls(pVCpu, pVmcsInfo);
3301 if (RT_SUCCESS(rc))
3302 {
3303 rc = hmR0VmxSetupVmcsMiscCtls(pVCpu, pVmcsInfo);
3304 if (RT_SUCCESS(rc))
3305 {
3306 rc = hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
3307 if (RT_SUCCESS(rc))
3308 { /* likely */ }
3309 else
3310 LogRelFunc(("Failed to initialize exception bitmap. rc=%Rrc\n", rc));
3311 }
3312 else
3313 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
3314 }
3315 else
3316 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
3317 }
3318 else
3319 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
3320 }
3321 else
3322 {
3323#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3324 rc = hmR0VmxSetupVmcsCtlsNested(pVCpu, pVmcsInfo);
3325 if (RT_SUCCESS(rc))
3326 { /* likely */ }
3327 else
3328 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
3329#else
3330 AssertFailed();
3331#endif
3332 }
3333 }
3334 else
3335 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
3336 }
3337 else
3338 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
3339
3340 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
3341 if (RT_SUCCESS(rc))
3342 {
3343 rc = hmR0VmxClearVmcs(pVmcsInfo);
3344 if (RT_SUCCESS(rc))
3345 { /* likely */ }
3346 else
3347 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
3348 }
3349
3350 /*
3351 * Update the last-error record both for failures and success, so we
3352 * can propagate the status code back to ring-3 for diagnostics.
3353 */
3354 hmR0VmxUpdateErrorRecord(pVCpu, rc);
3355 NOREF(pszVmcs);
3356 return rc;
3357}
3358
3359
3360/**
3361 * Does global VT-x initialization (called during module initialization).
3362 *
3363 * @returns VBox status code.
3364 */
3365VMMR0DECL(int) VMXR0GlobalInit(void)
3366{
3367#ifdef HMVMX_USE_FUNCTION_TABLE
3368 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_apfnVMExitHandlers));
3369# ifdef VBOX_STRICT
3370 for (unsigned i = 0; i < RT_ELEMENTS(g_apfnVMExitHandlers); i++)
3371 Assert(g_apfnVMExitHandlers[i]);
3372# endif
3373#endif
3374 return VINF_SUCCESS;
3375}
3376
3377
3378/**
3379 * Does global VT-x termination (called during module termination).
3380 */
3381VMMR0DECL(void) VMXR0GlobalTerm()
3382{
3383 /* Nothing to do currently. */
3384}
3385
3386
3387/**
3388 * Sets up and activates VT-x on the current CPU.
3389 *
3390 * @returns VBox status code.
3391 * @param pHostCpu The HM physical-CPU structure.
3392 * @param pVM The cross context VM structure. Can be
3393 * NULL after a host resume operation.
3394 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
3395 * fEnabledByHost is @c true).
3396 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
3397 * @a fEnabledByHost is @c true).
3398 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
3399 * enable VT-x on the host.
3400 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
3401 */
3402VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVM pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
3403 PCSUPHWVIRTMSRS pHwvirtMsrs)
3404{
3405 Assert(pHostCpu);
3406 Assert(pHwvirtMsrs);
3407 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
3408
3409 /* Enable VT-x if it's not already enabled by the host. */
3410 if (!fEnabledByHost)
3411 {
3412 int rc = hmR0VmxEnterRootMode(pVM, HCPhysCpuPage, pvCpuPage);
3413 if (RT_FAILURE(rc))
3414 return rc;
3415 }
3416
3417 /*
3418 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
3419 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
3420 * invalidated when flushing by VPID.
3421 */
3422 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3423 {
3424 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
3425 pHostCpu->fFlushAsidBeforeUse = false;
3426 }
3427 else
3428 pHostCpu->fFlushAsidBeforeUse = true;
3429
3430 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
3431 ++pHostCpu->cTlbFlushes;
3432
3433 return VINF_SUCCESS;
3434}
3435
3436
3437/**
3438 * Deactivates VT-x on the current CPU.
3439 *
3440 * @returns VBox status code.
3441 * @param pvCpuPage Pointer to the VMXON region.
3442 * @param HCPhysCpuPage Physical address of the VMXON region.
3443 *
3444 * @remarks This function should never be called when SUPR0EnableVTx() or
3445 * similar was used to enable VT-x on the host.
3446 */
3447VMMR0DECL(int) VMXR0DisableCpu(void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
3448{
3449 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
3450
3451 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
3452 return hmR0VmxLeaveRootMode();
3453}
3454
3455
3456/**
3457 * Does per-VM VT-x initialization.
3458 *
3459 * @returns VBox status code.
3460 * @param pVM The cross context VM structure.
3461 */
3462VMMR0DECL(int) VMXR0InitVM(PVM pVM)
3463{
3464 LogFlowFunc(("pVM=%p\n", pVM));
3465
3466 int rc = hmR0VmxStructsAlloc(pVM);
3467 if (RT_FAILURE(rc))
3468 {
3469 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
3470 return rc;
3471 }
3472
3473 return VINF_SUCCESS;
3474}
3475
3476
3477/**
3478 * Does per-VM VT-x termination.
3479 *
3480 * @returns VBox status code.
3481 * @param pVM The cross context VM structure.
3482 */
3483VMMR0DECL(int) VMXR0TermVM(PVM pVM)
3484{
3485 LogFlowFunc(("pVM=%p\n", pVM));
3486
3487#ifdef VBOX_WITH_CRASHDUMP_MAGIC
3488 if (pVM->hm.s.vmx.hMemObjScratch != NIL_RTR0MEMOBJ)
3489 {
3490 Assert(pVM->hm.s.vmx.pvScratch);
3491 ASMMemZero32(pVM->hm.s.vmx.pvScratch, X86_PAGE_4K_SIZE);
3492 }
3493#endif
3494 hmR0VmxStructsFree(pVM);
3495 return VINF_SUCCESS;
3496}
3497
3498
3499/**
3500 * Sets up the VM for execution using hardware-assisted VMX.
3501 * This function is only called once per-VM during initialization.
3502 *
3503 * @returns VBox status code.
3504 * @param pVM The cross context VM structure.
3505 */
3506VMMR0DECL(int) VMXR0SetupVM(PVM pVM)
3507{
3508 AssertPtrReturn(pVM, VERR_INVALID_PARAMETER);
3509 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
3510
3511 LogFlowFunc(("pVM=%p\n", pVM));
3512
3513 /*
3514 * At least verify if VMX is enabled, since we can't check if we're in
3515 * VMX root mode or not without causing a #GP.
3516 */
3517 RTCCUINTREG const uHostCR4 = ASMGetCR4();
3518 if (RT_LIKELY(uHostCR4 & X86_CR4_VMXE))
3519 { /* likely */ }
3520 else
3521 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
3522
3523 /*
3524 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
3525 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
3526 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
3527 */
3528 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
3529 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
3530 || !pVM->hm.s.vmx.pRealModeTSS))
3531 {
3532 LogRelFunc(("Invalid real-on-v86 state.\n"));
3533 return VERR_INTERNAL_ERROR;
3534 }
3535
3536 /* Initialize these always, see hmR3InitFinalizeR0().*/
3537 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
3538 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
3539
3540 /* Setup the tagged-TLB flush handlers. */
3541 int rc = hmR0VmxSetupTaggedTlb(pVM);
3542 if (RT_FAILURE(rc))
3543 {
3544 LogRelFunc(("hmR0VmxSetupTaggedTlb failed! rc=%Rrc\n", rc));
3545 return rc;
3546 }
3547
3548 /* Check if we can use the VMCS controls for swapping the EFER MSR. */
3549 Assert(!pVM->hm.s.vmx.fSupportsVmcsEfer);
3550#if HC_ARCH_BITS == 64
3551 if ( (pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed1 & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
3552 && (pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_LOAD_EFER_MSR)
3553 && (pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_EFER_MSR))
3554 pVM->hm.s.vmx.fSupportsVmcsEfer = true;
3555#endif
3556
3557 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
3558 {
3559 PVMCPU pVCpu = &pVM->aCpus[idCpu];
3560 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
3561
3562 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
3563 if (RT_SUCCESS(rc))
3564 {
3565#if HC_ARCH_BITS == 32
3566 hmR0VmxInitVmcsReadCache(pVCpu);
3567#endif
3568#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3569 if (pVM->cpum.ro.GuestFeatures.fVmx)
3570 {
3571 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
3572 if (RT_SUCCESS(rc))
3573 { /* likely */ }
3574 else
3575 {
3576 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
3577 return rc;
3578 }
3579 }
3580#endif
3581 }
3582 else
3583 {
3584 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
3585 return rc;
3586 }
3587 }
3588
3589 return VINF_SUCCESS;
3590}
3591
3592
3593#if HC_ARCH_BITS == 32
3594# ifdef VBOX_ENABLE_64_BITS_GUESTS
3595/**
3596 * Check if guest state allows safe use of 32-bit switcher again.
3597 *
3598 * Segment bases and protected mode structures must be 32-bit addressable
3599 * because the 32-bit switcher will ignore high dword when writing these VMCS
3600 * fields. See @bugref{8432} for details.
3601 *
3602 * @returns true if safe, false if must continue to use the 64-bit switcher.
3603 * @param pCtx Pointer to the guest-CPU context.
3604 *
3605 * @remarks No-long-jump zone!!!
3606 */
3607static bool hmR0VmxIs32BitSwitcherSafe(PCCPUMCTX pCtx)
3608{
3609 if (pCtx->gdtr.pGdt & UINT64_C(0xffffffff00000000)) return false;
3610 if (pCtx->idtr.pIdt & UINT64_C(0xffffffff00000000)) return false;
3611 if (pCtx->ldtr.u64Base & UINT64_C(0xffffffff00000000)) return false;
3612 if (pCtx->tr.u64Base & UINT64_C(0xffffffff00000000)) return false;
3613 if (pCtx->es.u64Base & UINT64_C(0xffffffff00000000)) return false;
3614 if (pCtx->cs.u64Base & UINT64_C(0xffffffff00000000)) return false;
3615 if (pCtx->ss.u64Base & UINT64_C(0xffffffff00000000)) return false;
3616 if (pCtx->ds.u64Base & UINT64_C(0xffffffff00000000)) return false;
3617 if (pCtx->fs.u64Base & UINT64_C(0xffffffff00000000)) return false;
3618 if (pCtx->gs.u64Base & UINT64_C(0xffffffff00000000)) return false;
3619
3620 /* All good, bases are 32-bit. */
3621 return true;
3622}
3623# endif /* VBOX_ENABLE_64_BITS_GUESTS */
3624
3625# ifdef VBOX_STRICT
3626static bool hmR0VmxIsValidWriteField(uint32_t idxField)
3627{
3628 switch (idxField)
3629 {
3630 case VMX_VMCS_GUEST_RIP:
3631 case VMX_VMCS_GUEST_RSP:
3632 case VMX_VMCS_GUEST_SYSENTER_EIP:
3633 case VMX_VMCS_GUEST_SYSENTER_ESP:
3634 case VMX_VMCS_GUEST_GDTR_BASE:
3635 case VMX_VMCS_GUEST_IDTR_BASE:
3636 case VMX_VMCS_GUEST_CS_BASE:
3637 case VMX_VMCS_GUEST_DS_BASE:
3638 case VMX_VMCS_GUEST_ES_BASE:
3639 case VMX_VMCS_GUEST_FS_BASE:
3640 case VMX_VMCS_GUEST_GS_BASE:
3641 case VMX_VMCS_GUEST_SS_BASE:
3642 case VMX_VMCS_GUEST_LDTR_BASE:
3643 case VMX_VMCS_GUEST_TR_BASE:
3644 case VMX_VMCS_GUEST_CR3:
3645 return true;
3646 }
3647 return false;
3648}
3649
3650static bool hmR0VmxIsValidReadField(uint32_t idxField)
3651{
3652 switch (idxField)
3653 {
3654 /* Read-only fields. */
3655 case VMX_VMCS_RO_EXIT_QUALIFICATION:
3656 return true;
3657 }
3658 /* Remaining readable fields should also be writable. */
3659 return hmR0VmxIsValidWriteField(idxField);
3660}
3661# endif /* VBOX_STRICT */
3662
3663
3664/**
3665 * Executes the specified handler in 64-bit mode.
3666 *
3667 * @returns VBox status code (no informational status codes).
3668 * @param pVCpu The cross context virtual CPU structure.
3669 * @param enmOp The operation to perform.
3670 * @param cParams Number of parameters.
3671 * @param paParam Array of 32-bit parameters.
3672 */
3673VMMR0DECL(int) VMXR0Execute64BitsHandler(PVMCPU pVCpu, HM64ON32OP enmOp, uint32_t cParams, uint32_t *paParam)
3674{
3675 PVM pVM = pVCpu->CTX_SUFF(pVM);
3676 AssertReturn(pVM->hm.s.pfnHost32ToGuest64R0, VERR_HM_NO_32_TO_64_SWITCHER);
3677 Assert(enmOp > HM64ON32OP_INVALID && enmOp < HM64ON32OP_END);
3678 Assert(pVCpu->hm.s.vmx.VmcsCache.Write.cValidEntries <= RT_ELEMENTS(pVCpu->hm.s.vmx.VmcsCache.Write.aField));
3679 Assert(pVCpu->hm.s.vmx.VmcsCache.Read.cValidEntries <= RT_ELEMENTS(pVCpu->hm.s.vmx.VmcsCache.Read.aField));
3680
3681#ifdef VBOX_STRICT
3682 for (uint32_t i = 0; i < pVCpu->hm.s.vmx.VmcsCache.Write.cValidEntries; i++)
3683 Assert(hmR0VmxIsValidWriteField(pVCpu->hm.s.vmx.VmcsCache.Write.aField[i]));
3684
3685 for (uint32_t i = 0; i <pVCpu->hm.s.vmx.VmcsCache.Read.cValidEntries; i++)
3686 Assert(hmR0VmxIsValidReadField(pVCpu->hm.s.vmx.VmcsCache.Read.aField[i]));
3687#endif
3688
3689 /* Disable interrupts. */
3690 RTCCUINTREG fOldEFlags = ASMIntDisableFlags();
3691
3692#ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
3693 RTCPUID idHostCpu = RTMpCpuId();
3694 CPUMR0SetLApic(pVCpu, idHostCpu);
3695#endif
3696
3697 /** @todo replace with hmR0VmxEnterRootMode() and hmR0VmxLeaveRootMode(). */
3698
3699 PCHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
3700 RTHCPHYS const HCPhysCpuPage = pHostCpu->HCPhysMemObj;
3701
3702 /* Clear VMCS. Marking it inactive, clearing implementation-specific data and writing VMCS data back to memory. */
3703 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
3704 hmR0VmxClearVmcs(pVmcsInfo);
3705
3706 /* Leave VMX root mode and disable VMX. */
3707 VMXDisable();
3708 SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
3709
3710 CPUMSetHyperESP(pVCpu, VMMGetStackRC(pVCpu));
3711 CPUMSetHyperEIP(pVCpu, enmOp);
3712 for (int i = (int)cParams - 1; i >= 0; i--)
3713 CPUMPushHyper(pVCpu, paParam[i]);
3714
3715 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatWorldSwitch3264, z);
3716
3717 /* Call the switcher. */
3718 int rc = pVM->hm.s.pfnHost32ToGuest64R0(pVM, RT_UOFFSETOF_DYN(VM, aCpus[pVCpu->idCpu].cpum) - RT_UOFFSETOF(VM, cpum));
3719 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatWorldSwitch3264, z);
3720
3721 /* Re-enable VMX to make sure the VMX instructions don't cause #UD faults. */
3722 SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
3723
3724 /* Re-enter VMX root mode. */
3725 int rc2 = VMXEnable(HCPhysCpuPage);
3726 if (RT_FAILURE(rc2))
3727 {
3728 SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
3729 ASMSetFlags(fOldEFlags);
3730 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
3731 return rc2;
3732 }
3733
3734 /* Restore the VMCS as the current VMCS. */
3735 rc2 = hmR0VmxLoadVmcs(pVmcsInfo);
3736 AssertRC(rc2);
3737 Assert(!(ASMGetFlags() & X86_EFL_IF));
3738 ASMSetFlags(fOldEFlags);
3739 return rc;
3740}
3741
3742
3743/**
3744 * Prepares for and executes VMLAUNCH (64-bit guests) for 32-bit hosts
3745 * supporting 64-bit guests.
3746 *
3747 * @returns VBox status code.
3748 * @param fResume Whether to VMLAUNCH or VMRESUME.
3749 * @param pCtx Pointer to the guest-CPU context.
3750 * @param pCache Pointer to the VMCS batch cache.
3751 * @param pVM The cross context VM structure.
3752 * @param pVCpu The cross context virtual CPU structure.
3753 */
3754DECLASM(int) VMXR0SwitcherStartVM64(RTHCUINT fResume, PCPUMCTX pCtx, PVMXVMCSCACHE pCache, PVM pVM, PVMCPU pVCpu)
3755{
3756 NOREF(fResume);
3757
3758 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
3759 PCHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
3760 RTHCPHYS const HCPhysCpuPage = pHostCpu->HCPhysMemObj;
3761
3762#ifdef VBOX_WITH_CRASHDUMP_MAGIC
3763 pCache->uPos = 1;
3764 pCache->interPD = PGMGetInterPaeCR3(pVM);
3765 pCache->pSwitcher = (uint64_t)pVM->hm.s.pfnHost32ToGuest64R0;
3766#endif
3767
3768#if defined(DEBUG) && defined(VMX_USE_CACHED_VMCS_ACCESSES)
3769 pCache->TestIn.HCPhysCpuPage = 0;
3770 pCache->TestIn.HCPhysVmcs = 0;
3771 pCache->TestIn.pCache = 0;
3772 pCache->TestOut.HCPhysVmcs = 0;
3773 pCache->TestOut.pCache = 0;
3774 pCache->TestOut.pCtx = 0;
3775 pCache->TestOut.eflags = 0;
3776#else
3777 NOREF(pCache);
3778#endif
3779
3780 uint32_t aParam[10];
3781 aParam[0] = RT_LO_U32(HCPhysCpuPage); /* Param 1: VMXON physical address - Lo. */
3782 aParam[1] = RT_HI_U32(HCPhysCpuPage); /* Param 1: VMXON physical address - Hi. */
3783 aParam[2] = RT_LO_U32(pVmcsInfo->HCPhysVmcs); /* Param 2: VMCS physical address - Lo. */
3784 aParam[3] = RT_HI_U32(pVmcsInfo->HCPhysVmcs); /* Param 2: VMCS physical address - Hi. */
3785 aParam[4] = VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VmcsCache);
3786 aParam[5] = 0;
3787 aParam[6] = VM_RC_ADDR(pVM, pVM);
3788 aParam[7] = 0;
3789 aParam[8] = VM_RC_ADDR(pVM, pVCpu);
3790 aParam[9] = 0;
3791
3792#ifdef VBOX_WITH_CRASHDUMP_MAGIC
3793 pCtx->dr[4] = pVM->hm.s.vmx.pScratchPhys + 16 + 8;
3794 *(uint32_t *)(pVM->hm.s.vmx.pScratch + 16 + 8) = 1;
3795#endif
3796 int rc = VMXR0Execute64BitsHandler(pVCpu, HM64ON32OP_VMXRCStartVM64, RT_ELEMENTS(aParam), &aParam[0]);
3797
3798#ifdef VBOX_WITH_CRASHDUMP_MAGIC
3799 Assert(*(uint32_t *)(pVM->hm.s.vmx.pScratch + 16 + 8) == 5);
3800 Assert(pCtx->dr[4] == 10);
3801 *(uint32_t *)(pVM->hm.s.vmx.pScratch + 16 + 8) = 0xff;
3802#endif
3803
3804#if defined(DEBUG) && defined(VMX_USE_CACHED_VMCS_ACCESSES)
3805 AssertMsg(pCache->TestIn.HCPhysCpuPage == HCPhysCpuPage, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysCpuPage, HCPhysCpuPage));
3806 AssertMsg(pCache->TestIn.HCPhysVmcs == pVmcsInfo->HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs,
3807 pVmcsInfo->HCPhysVmcs));
3808 AssertMsg(pCache->TestIn.HCPhysVmcs == pCache->TestOut.HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs,
3809 pCache->TestOut.HCPhysVmcs));
3810 AssertMsg(pCache->TestIn.pCache == pCache->TestOut.pCache, ("%RGv vs %RGv\n", pCache->TestIn.pCache,
3811 pCache->TestOut.pCache));
3812 AssertMsg(pCache->TestIn.pCache == VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VmcsCache),
3813 ("%RGv vs %RGv\n", pCache->TestIn.pCache, VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VmcsCache)));
3814 AssertMsg(pCache->TestIn.pCtx == pCache->TestOut.pCtx, ("%RGv vs %RGv\n", pCache->TestIn.pCtx,
3815 pCache->TestOut.pCtx));
3816 Assert(!(pCache->TestOut.eflags & X86_EFL_IF));
3817#endif
3818 NOREF(pCtx);
3819 return rc;
3820}
3821#endif
3822
3823
3824/**
3825 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
3826 * the VMCS.
3827 *
3828 * @returns VBox status code.
3829 */
3830static int hmR0VmxExportHostControlRegs(void)
3831{
3832 RTCCUINTREG uReg = ASMGetCR0();
3833 int rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_CR0, uReg);
3834 AssertRCReturn(rc, rc);
3835
3836 uReg = ASMGetCR3();
3837 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_CR3, uReg);
3838 AssertRCReturn(rc, rc);
3839
3840 uReg = ASMGetCR4();
3841 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_CR4, uReg);
3842 AssertRCReturn(rc, rc);
3843 return rc;
3844}
3845
3846
3847/**
3848 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
3849 * the host-state area in the VMCS.
3850 *
3851 * @returns VBox status code.
3852 * @param pVCpu The cross context virtual CPU structure.
3853 */
3854static int hmR0VmxExportHostSegmentRegs(PVMCPU pVCpu)
3855{
3856#if HC_ARCH_BITS == 64
3857/**
3858 * Macro for adjusting host segment selectors to satisfy VT-x's VM-entry
3859 * requirements. See hmR0VmxExportHostSegmentRegs().
3860 */
3861# define VMXLOCAL_ADJUST_HOST_SEG(seg, selValue) \
3862 if ((selValue) & (X86_SEL_RPL | X86_SEL_LDT)) \
3863 { \
3864 bool fValidSelector = true; \
3865 if ((selValue) & X86_SEL_LDT) \
3866 { \
3867 uint32_t uAttr = ASMGetSegAttr((selValue)); \
3868 fValidSelector = RT_BOOL(uAttr != UINT32_MAX && (uAttr & X86_DESC_P)); \
3869 } \
3870 if (fValidSelector) \
3871 { \
3872 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##seg; \
3873 pVCpu->hm.s.vmx.RestoreHost.uHostSel##seg = (selValue); \
3874 } \
3875 (selValue) = 0; \
3876 }
3877
3878 /*
3879 * If we've executed guest code using hardware-assisted VMX, the host-state bits
3880 * will be messed up. We should -not- save the messed up state without restoring
3881 * the original host-state, see @bugref{7240}.
3882 *
3883 * This apparently can happen (most likely the FPU changes), deal with it rather than
3884 * asserting. Was observed booting Solaris 10u10 32-bit guest.
3885 */
3886 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
3887 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
3888 {
3889 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags,
3890 pVCpu->idCpu));
3891 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
3892 }
3893 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
3894#else
3895 RT_NOREF(pVCpu);
3896#endif
3897
3898 /*
3899 * Host DS, ES, FS and GS segment registers.
3900 */
3901#if HC_ARCH_BITS == 64
3902 RTSEL uSelDS = ASMGetDS();
3903 RTSEL uSelES = ASMGetES();
3904 RTSEL uSelFS = ASMGetFS();
3905 RTSEL uSelGS = ASMGetGS();
3906#else
3907 RTSEL uSelDS = 0;
3908 RTSEL uSelES = 0;
3909 RTSEL uSelFS = 0;
3910 RTSEL uSelGS = 0;
3911#endif
3912
3913 /*
3914 * Host CS and SS segment registers.
3915 */
3916 RTSEL uSelCS = ASMGetCS();
3917 RTSEL uSelSS = ASMGetSS();
3918
3919 /*
3920 * Host TR segment register.
3921 */
3922 RTSEL uSelTR = ASMGetTR();
3923
3924#if HC_ARCH_BITS == 64
3925 /*
3926 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
3927 * gain VM-entry and restore them before we get preempted.
3928 *
3929 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
3930 */
3931 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
3932 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
3933 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
3934 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
3935# undef VMXLOCAL_ADJUST_HOST_SEG
3936#endif
3937
3938 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
3939 Assert(!(uSelCS & X86_SEL_RPL)); Assert(!(uSelCS & X86_SEL_LDT));
3940 Assert(!(uSelSS & X86_SEL_RPL)); Assert(!(uSelSS & X86_SEL_LDT));
3941 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
3942 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
3943 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
3944 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
3945 Assert(!(uSelTR & X86_SEL_RPL)); Assert(!(uSelTR & X86_SEL_LDT));
3946 Assert(uSelCS);
3947 Assert(uSelTR);
3948
3949 /* Write these host selector fields into the host-state area in the VMCS. */
3950 int rc = VMXWriteVmcs32(VMX_VMCS16_HOST_CS_SEL, uSelCS);
3951 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_SS_SEL, uSelSS);
3952#if HC_ARCH_BITS == 64
3953 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_DS_SEL, uSelDS);
3954 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_ES_SEL, uSelES);
3955 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_FS_SEL, uSelFS);
3956 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_GS_SEL, uSelGS);
3957#else
3958 NOREF(uSelDS);
3959 NOREF(uSelES);
3960 NOREF(uSelFS);
3961 NOREF(uSelGS);
3962#endif
3963 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_TR_SEL, uSelTR);
3964 AssertRCReturn(rc, rc);
3965
3966 /*
3967 * Host GDTR and IDTR.
3968 */
3969 RTGDTR Gdtr;
3970 RTIDTR Idtr;
3971 RT_ZERO(Gdtr);
3972 RT_ZERO(Idtr);
3973 ASMGetGDTR(&Gdtr);
3974 ASMGetIDTR(&Idtr);
3975 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_GDTR_BASE, Gdtr.pGdt);
3976 rc |= VMXWriteVmcsHstN(VMX_VMCS_HOST_IDTR_BASE, Idtr.pIdt);
3977 AssertRCReturn(rc, rc);
3978
3979#if HC_ARCH_BITS == 64
3980 /*
3981 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
3982 * them to the maximum limit (0xffff) on every VM-exit.
3983 */
3984 if (Gdtr.cbGdt != 0xffff)
3985 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
3986
3987 /*
3988 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
3989 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
3990 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
3991 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
3992 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
3993 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
3994 * at 0xffff on hosts where we are sure it won't cause trouble.
3995 */
3996# if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
3997 if (Idtr.cbIdt < 0x0fff)
3998# else
3999 if (Idtr.cbIdt != 0xffff)
4000# endif
4001 {
4002 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4003 AssertCompile(sizeof(Idtr) == sizeof(X86XDTR64));
4004 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostIdtr, &Idtr, sizeof(X86XDTR64));
4005 }
4006#endif
4007
4008 /*
4009 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4010 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4011 * RPL should be too in most cases.
4012 */
4013 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= Gdtr.cbGdt,
4014 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, Gdtr.cbGdt), VERR_VMX_INVALID_HOST_STATE);
4015
4016 PCX86DESCHC pDesc = (PCX86DESCHC)(Gdtr.pGdt + (uSelTR & X86_SEL_MASK));
4017#if HC_ARCH_BITS == 64
4018 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4019
4020 /*
4021 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4022 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4023 * restoration if the host has something else. Task switching is not supported in 64-bit
4024 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4025 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4026 *
4027 * [1] See Intel spec. 3.5 "System Descriptor Types".
4028 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4029 */
4030 PVM pVM = pVCpu->CTX_SUFF(pVM);
4031 Assert(pDesc->System.u4Type == 11);
4032 if ( pDesc->System.u16LimitLow != 0x67
4033 || pDesc->System.u4LimitHigh)
4034 {
4035 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4036 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4037 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4038 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4039 pVCpu->hm.s.vmx.RestoreHost.uHostSelTR = uSelTR;
4040 }
4041
4042 /*
4043 * Store the GDTR as we need it when restoring the GDT and while restoring the TR.
4044 */
4045 if (pVCpu->hm.s.vmx.fRestoreHostFlags & (VMX_RESTORE_HOST_GDTR | VMX_RESTORE_HOST_SEL_TR))
4046 {
4047 AssertCompile(sizeof(Gdtr) == sizeof(X86XDTR64));
4048 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostGdtr, &Gdtr, sizeof(X86XDTR64));
4049 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4050 {
4051 /* The GDT is read-only but the writable GDT is available. */
4052 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4053 pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.cb = Gdtr.cbGdt;
4054 rc = SUPR0GetCurrentGdtRw(&pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4055 AssertRCReturn(rc, rc);
4056 }
4057 }
4058#else
4059 uintptr_t const uTRBase = X86DESC_BASE(pDesc);
4060#endif
4061 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_TR_BASE, uTRBase);
4062 AssertRCReturn(rc, rc);
4063
4064 /*
4065 * Host FS base and GS base.
4066 */
4067#if HC_ARCH_BITS == 64
4068 uint64_t const u64FSBase = ASMRdMsr(MSR_K8_FS_BASE);
4069 uint64_t const u64GSBase = ASMRdMsr(MSR_K8_GS_BASE);
4070 rc = VMXWriteVmcs64(VMX_VMCS_HOST_FS_BASE, u64FSBase);
4071 rc |= VMXWriteVmcs64(VMX_VMCS_HOST_GS_BASE, u64GSBase);
4072 AssertRCReturn(rc, rc);
4073
4074 /* Store the base if we have to restore FS or GS manually as we need to restore the base as well. */
4075 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_FS)
4076 pVCpu->hm.s.vmx.RestoreHost.uHostFSBase = u64FSBase;
4077 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_GS)
4078 pVCpu->hm.s.vmx.RestoreHost.uHostGSBase = u64GSBase;
4079#endif
4080 return VINF_SUCCESS;
4081}
4082
4083
4084/**
4085 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4086 * host-state area of the VMCS.
4087 *
4088 * These MSRs will be automatically restored on the host after every successful
4089 * VM-exit.
4090 *
4091 * @returns VBox status code.
4092 * @param pVCpu The cross context virtual CPU structure.
4093 *
4094 * @remarks No-long-jump zone!!!
4095 */
4096static int hmR0VmxExportHostMsrs(PVMCPU pVCpu)
4097{
4098 AssertPtr(pVCpu);
4099
4100 /*
4101 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4102 * rather than swapping them on every VM-entry.
4103 */
4104 hmR0VmxLazySaveHostMsrs(pVCpu);
4105
4106 /*
4107 * Host Sysenter MSRs.
4108 */
4109 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS));
4110#if HC_ARCH_BITS == 32
4111 rc |= VMXWriteVmcs32(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr_Low(MSR_IA32_SYSENTER_ESP));
4112 rc |= VMXWriteVmcs32(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr_Low(MSR_IA32_SYSENTER_EIP));
4113#else
4114 rc |= VMXWriteVmcs64(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP));
4115 rc |= VMXWriteVmcs64(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP));
4116#endif
4117 AssertRCReturn(rc, rc);
4118
4119 /*
4120 * Host EFER MSR.
4121 *
4122 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4123 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4124 */
4125 PVM pVM = pVCpu->CTX_SUFF(pVM);
4126 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
4127 {
4128 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, pVM->hm.s.vmx.u64HostMsrEfer);
4129 AssertRCReturn(rc, rc);
4130 }
4131
4132 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4133 * hmR0VmxExportGuestEntryExitCtls(). */
4134
4135 return VINF_SUCCESS;
4136}
4137
4138
4139/**
4140 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4141 *
4142 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4143 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4144 *
4145 * @returns true if we need to load guest EFER, false otherwise.
4146 * @param pVCpu The cross context virtual CPU structure.
4147 *
4148 * @remarks Requires EFER, CR4.
4149 * @remarks No-long-jump zone!!!
4150 */
4151static bool hmR0VmxShouldSwapEferMsr(PCVMCPU pVCpu)
4152{
4153#ifdef HMVMX_ALWAYS_SWAP_EFER
4154 RT_NOREF(pVCpu);
4155 return true;
4156#else
4157 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4158#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
4159 /* For 32-bit hosts running 64-bit guests, we always swap EFER MSR in the world-switcher. Nothing to do here. */
4160 if (CPUMIsGuestInLongModeEx(pCtx))
4161 return false;
4162#endif
4163
4164 PVM pVM = pVCpu->CTX_SUFF(pVM);
4165 uint64_t const u64HostEfer = pVM->hm.s.vmx.u64HostMsrEfer;
4166 uint64_t const u64GuestEfer = pCtx->msrEFER;
4167
4168 /*
4169 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4170 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4171 */
4172 if ( CPUMIsGuestInLongModeEx(pCtx)
4173 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4174 return true;
4175
4176 /*
4177 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4178 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4179 *
4180 * See Intel spec. 4.5 "IA-32e Paging".
4181 * See Intel spec. 4.1.1 "Three Paging Modes".
4182 *
4183 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4184 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4185 */
4186 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4187 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4188 if ( (pCtx->cr4 & X86_CR4_PAE)
4189 && (pCtx->cr0 & X86_CR0_PG)
4190 && (u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4191 {
4192 /* Assert that host is NX capable. */
4193 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4194 return true;
4195 }
4196
4197 return false;
4198#endif
4199}
4200
4201/**
4202 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
4203 * VMCS.
4204 *
4205 * This is typically required when the guest changes paging mode.
4206 *
4207 * @returns VBox status code.
4208 * @param pVCpu The cross context virtual CPU structure.
4209 * @param pVmxTransient The VMX-transient structure.
4210 *
4211 * @remarks Requires EFER.
4212 * @remarks No-long-jump zone!!!
4213 */
4214static int hmR0VmxExportGuestEntryExitCtls(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
4215{
4216 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
4217 {
4218 PVM pVM = pVCpu->CTX_SUFF(pVM);
4219 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4220
4221 /*
4222 * VM-entry controls.
4223 */
4224 {
4225 uint32_t fVal = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4226 uint32_t const fZap = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4227
4228 /*
4229 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
4230 * The first VT-x capable CPUs only supported the 1-setting of this bit.
4231 *
4232 * For nested-guests, this is a mandatory VM-entry control. It's also
4233 * required because we do not want to leak host bits to the nested-guest.
4234 */
4235 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
4236
4237 /*
4238 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
4239 *
4240 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
4241 * required to get the nested-guest working with hardware-assisted VMX execution.
4242 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a nested-hypervisor
4243 * can skip intercepting changes to the EFER MSR. This is why it it needs to be done
4244 * here rather than while merging the guest VMCS controls.
4245 */
4246 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
4247 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
4248 else
4249 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
4250
4251 /*
4252 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
4253 *
4254 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
4255 * regardless of whether the nested-guest VMCS specifies it because we are free to
4256 * load whatever MSRs we require and we do not need to modify the guest visible copy
4257 * of the VM-entry MSR load area.
4258 */
4259 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4260 && hmR0VmxShouldSwapEferMsr(pVCpu))
4261 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
4262 else
4263 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
4264
4265 /*
4266 * The following should -not- be set (since we're not in SMM mode):
4267 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
4268 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
4269 */
4270
4271 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
4272 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
4273
4274 if ((fVal & fZap) == fVal)
4275 { /* likely */ }
4276 else
4277 {
4278 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
4279 pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0, fVal, fZap));
4280 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
4281 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4282 }
4283
4284 /* Commit it to the VMCS. */
4285 if (pVmcsInfo->u32EntryCtls != fVal)
4286 {
4287 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
4288 AssertRCReturn(rc, rc);
4289 pVmcsInfo->u32EntryCtls = fVal;
4290 }
4291 }
4292
4293 /*
4294 * VM-exit controls.
4295 */
4296 {
4297 uint32_t fVal = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4298 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4299
4300 /*
4301 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
4302 * supported the 1-setting of this bit.
4303 *
4304 * For nested-guests, we set the "save debug controls" as the converse
4305 * "load debug controls" is mandatory for nested-guests anyway.
4306 */
4307 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
4308
4309 /*
4310 * Set the host long mode active (EFER.LMA) bit (which Intel calls
4311 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
4312 * host EFER.LMA and EFER.LME bit to this value. See assertion in
4313 * hmR0VmxExportHostMsrs().
4314 *
4315 * For nested-guests, we always set this bit as we do not support 32-bit
4316 * hosts.
4317 */
4318#if HC_ARCH_BITS == 64
4319 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
4320#else
4321 Assert(!pVmxTransient->fIsNestedGuest);
4322 Assert( pVmcsInfo->pfnStartVM == VMXR0SwitcherStartVM64
4323 || pVmcsInfo->pfnStartVM == VMXR0StartVM32);
4324 /* Set the host address-space size based on the switcher, not guest state. See @bugref{8432}. */
4325 if (pVmcsInfo->pfnStartVM == VMXR0SwitcherStartVM64)
4326 {
4327 /* The switcher returns to long mode, the EFER MSR is managed by the switcher. */
4328 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
4329 }
4330 else
4331 Assert(!(fVal & VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE));
4332#endif
4333
4334 /*
4335 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
4336 *
4337 * For nested-guests, we should use the "save IA32_EFER" control if we also
4338 * used the "load IA32_EFER" control while exporting VM-entry controls.
4339 */
4340 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4341 && hmR0VmxShouldSwapEferMsr(pVCpu))
4342 {
4343 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
4344 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
4345 }
4346
4347 /*
4348 * Enable saving of the VMX-preemption timer value on VM-exit.
4349 * For nested-guests, currently not exposed/used.
4350 */
4351 if ( pVM->hm.s.vmx.fUsePreemptTimer
4352 && (pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER))
4353 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
4354
4355 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
4356 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
4357
4358 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
4359 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
4360 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
4361
4362 if ((fVal & fZap) == fVal)
4363 { /* likely */ }
4364 else
4365 {
4366 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
4367 pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0, fVal, fZap));
4368 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
4369 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4370 }
4371
4372 /* Commit it to the VMCS. */
4373 if (pVmcsInfo->u32ExitCtls != fVal)
4374 {
4375 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
4376 AssertRCReturn(rc, rc);
4377 pVmcsInfo->u32ExitCtls = fVal;
4378 }
4379 }
4380
4381 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
4382 }
4383 return VINF_SUCCESS;
4384}
4385
4386
4387/**
4388 * Sets the TPR threshold in the VMCS.
4389 *
4390 * @returns VBox status code.
4391 * @param pVCpu The cross context virtual CPU structure.
4392 * @param pVmcsInfo The VMCS info. object.
4393 * @param u32TprThreshold The TPR threshold (task-priority class only).
4394 */
4395DECLINLINE(int) hmR0VmxApicSetTprThreshold(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
4396{
4397 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
4398 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
4399 RT_NOREF2(pVCpu, pVmcsInfo);
4400 return VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
4401}
4402
4403
4404/**
4405 * Exports the guest APIC TPR state into the VMCS.
4406 *
4407 * @returns VBox status code.
4408 * @param pVCpu The cross context virtual CPU structure.
4409 * @param pVmxTransient The VMX-transient structure.
4410 *
4411 * @remarks No-long-jump zone!!!
4412 */
4413static int hmR0VmxExportGuestApicTpr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
4414{
4415 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
4416 {
4417 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
4418
4419 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4420 if (!pVmxTransient->fIsNestedGuest)
4421 {
4422 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
4423 && APICIsEnabled(pVCpu))
4424 {
4425 /*
4426 * Setup TPR shadowing.
4427 */
4428 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
4429 {
4430 bool fPendingIntr = false;
4431 uint8_t u8Tpr = 0;
4432 uint8_t u8PendingIntr = 0;
4433 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
4434 AssertRCReturn(rc, rc);
4435
4436 /*
4437 * If there are interrupts pending but masked by the TPR, instruct VT-x to
4438 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
4439 * priority of the pending interrupt so we can deliver the interrupt. If there
4440 * are no interrupts pending, set threshold to 0 to not cause any
4441 * TPR-below-threshold VM-exits.
4442 */
4443 Assert(pVmcsInfo->pbVirtApic);
4444 pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR] = u8Tpr;
4445 uint32_t u32TprThreshold = 0;
4446 if (fPendingIntr)
4447 {
4448 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
4449 (which is the Task-Priority Class). */
4450 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
4451 const uint8_t u8TprPriority = u8Tpr >> 4;
4452 if (u8PendingPriority <= u8TprPriority)
4453 u32TprThreshold = u8PendingPriority;
4454 }
4455
4456 rc = hmR0VmxApicSetTprThreshold(pVCpu, pVmcsInfo, u32TprThreshold);
4457 AssertRCReturn(rc, rc);
4458 }
4459 }
4460 }
4461 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
4462 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
4463 }
4464 return VINF_SUCCESS;
4465}
4466
4467
4468/**
4469 * Gets the guest interruptibility-state.
4470 *
4471 * @returns Guest's interruptibility-state.
4472 * @param pVCpu The cross context virtual CPU structure.
4473 * @param pVmcsInfo The VMCS info. object.
4474 *
4475 * @remarks No-long-jump zone!!!
4476 */
4477static uint32_t hmR0VmxGetGuestIntrState(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
4478{
4479 /*
4480 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
4481 */
4482 uint32_t fIntrState = 0;
4483 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
4484 {
4485 /* If inhibition is active, RIP and RFLAGS should've been updated
4486 (i.e. read previously from the VMCS or from ring-3). */
4487 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4488#ifdef VBOX_STRICT
4489 uint64_t const fExtrn = ASMAtomicUoReadU64(&pCtx->fExtrn);
4490 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
4491 AssertMsg(!(fExtrn & (CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS)), ("%#x\n", fExtrn));
4492#endif
4493 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
4494 {
4495 if (pCtx->eflags.Bits.u1IF)
4496 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
4497 else
4498 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
4499 }
4500 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
4501 {
4502 /*
4503 * We can clear the inhibit force flag as even if we go back to the recompiler
4504 * without executing guest code in VT-x, the flag's condition to be cleared is
4505 * met and thus the cleared state is correct.
4506 */
4507 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
4508 }
4509 }
4510
4511 /*
4512 * NMIs to the guest are blocked after an NMI is injected until the guest executes an IRET. We only
4513 * bother with virtual-NMI blocking when we have support for virtual NMIs in the CPU, otherwise
4514 * setting this would block host-NMIs and IRET will not clear the blocking.
4515 *
4516 * We always set NMI-exiting so when the host receives an NMI we get a VM-exit.
4517 *
4518 * See Intel spec. 26.6.1 "Interruptibility state". See @bugref{7445}.
4519 */
4520 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
4521 && CPUMIsGuestNmiBlocking(pVCpu))
4522 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
4523
4524 return fIntrState;
4525}
4526
4527
4528/**
4529 * Exports the exception intercepts required for guest execution in the VMCS.
4530 *
4531 * @returns VBox status code.
4532 * @param pVCpu The cross context virtual CPU structure.
4533 * @param pVmxTransient The VMX-transient structure.
4534 *
4535 * @remarks No-long-jump zone!!!
4536 */
4537static int hmR0VmxExportGuestXcptIntercepts(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
4538{
4539 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_XCPT_INTERCEPTS)
4540 {
4541 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
4542 if ( !pVmxTransient->fIsNestedGuest
4543 && pVCpu->hm.s.fGIMTrapXcptUD)
4544 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
4545 else
4546 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
4547
4548 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
4549 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_XCPT_INTERCEPTS);
4550 }
4551 return VINF_SUCCESS;
4552}
4553
4554
4555/**
4556 * Exports the guest's RIP into the guest-state area in the VMCS.
4557 *
4558 * @returns VBox status code.
4559 * @param pVCpu The cross context virtual CPU structure.
4560 *
4561 * @remarks No-long-jump zone!!!
4562 */
4563static int hmR0VmxExportGuestRip(PVMCPU pVCpu)
4564{
4565 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
4566 {
4567 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
4568
4569 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
4570 AssertRCReturn(rc, rc);
4571
4572 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
4573 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
4574 }
4575 return VINF_SUCCESS;
4576}
4577
4578
4579/**
4580 * Exports the guest's RSP into the guest-state area in the VMCS.
4581 *
4582 * @returns VBox status code.
4583 * @param pVCpu The cross context virtual CPU structure.
4584 *
4585 * @remarks No-long-jump zone!!!
4586 */
4587static int hmR0VmxExportGuestRsp(PVMCPU pVCpu)
4588{
4589 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
4590 {
4591 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
4592
4593 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
4594 AssertRCReturn(rc, rc);
4595
4596 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
4597 }
4598 return VINF_SUCCESS;
4599}
4600
4601
4602/**
4603 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
4604 *
4605 * @returns VBox status code.
4606 * @param pVCpu The cross context virtual CPU structure.
4607 * @param pVmxTransient The VMX-transient structure.
4608 *
4609 * @remarks No-long-jump zone!!!
4610 */
4611static int hmR0VmxExportGuestRflags(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
4612{
4613 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
4614 {
4615 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
4616
4617 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
4618 Let us assert it as such and use 32-bit VMWRITE. */
4619 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
4620 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
4621 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
4622 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
4623
4624 /*
4625 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
4626 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
4627 * can run the real-mode guest code under Virtual 8086 mode.
4628 */
4629 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4630 if (pVmcsInfo->RealMode.fRealOnV86Active)
4631 {
4632 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
4633 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
4634 Assert(!pVmxTransient->fIsNestedGuest);
4635 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
4636 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
4637 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
4638 }
4639
4640 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
4641 AssertRCReturn(rc, rc);
4642
4643 /*
4644 * Setup pending debug exceptions if the guest is single-stepping using EFLAGS.TF.
4645 *
4646 * We must avoid setting any automatic debug exceptions delivery when single-stepping
4647 * through the hypervisor debugger using EFLAGS.TF.
4648 */
4649 if ( !pVmxTransient->fIsNestedGuest
4650 && !pVCpu->hm.s.fSingleInstruction
4651 && fEFlags.Bits.u1TF)
4652 {
4653 /** @todo r=ramshankar: Warning!! We ASSUME EFLAGS.TF will not cleared on
4654 * premature trips to ring-3 esp since IEM does not yet handle it. */
4655 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BS);
4656 AssertRCReturn(rc, rc);
4657 }
4658 /** @todo NSTVMX: Handling copying of VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS from
4659 * nested-guest VMCS. */
4660
4661 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
4662 Log4Func(("EFlags=%#RX32\n", fEFlags.u32));
4663 }
4664 return VINF_SUCCESS;
4665}
4666
4667
4668/**
4669 * Exports the guest CR0 control register into the guest-state area in the VMCS.
4670 *
4671 * The guest FPU state is always pre-loaded hence we don't need to bother about
4672 * sharing FPU related CR0 bits between the guest and host.
4673 *
4674 * @returns VBox status code.
4675 * @param pVCpu The cross context virtual CPU structure.
4676 * @param pVmxTransient The VMX-transient structure.
4677 *
4678 * @remarks No-long-jump zone!!!
4679 */
4680static int hmR0VmxExportGuestCR0(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
4681{
4682 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
4683 {
4684 PVM pVM = pVCpu->CTX_SUFF(pVM);
4685 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4686
4687 /*
4688 * Figure out fixed CR0 bits in VMX operation.
4689 */
4690 uint64_t fSetCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
4691 uint64_t const fZapCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
4692 if (pVM->hm.s.vmx.fUnrestrictedGuest)
4693 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
4694 else
4695 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
4696
4697 if (!pVmxTransient->fIsNestedGuest)
4698 {
4699 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
4700 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
4701 uint64_t const u64ShadowCr0 = u64GuestCr0;
4702 Assert(!RT_HI_U32(u64GuestCr0));
4703
4704 /*
4705 * Setup VT-x's view of the guest CR0.
4706 */
4707 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
4708 if (pVM->hm.s.fNestedPaging)
4709 {
4710 if (CPUMIsGuestPagingEnabled(pVCpu))
4711 {
4712 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
4713 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
4714 | VMX_PROC_CTLS_CR3_STORE_EXIT);
4715 }
4716 else
4717 {
4718 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
4719 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
4720 | VMX_PROC_CTLS_CR3_STORE_EXIT;
4721 }
4722
4723 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
4724 if (pVM->hm.s.vmx.fUnrestrictedGuest)
4725 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
4726 }
4727 else
4728 {
4729 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
4730 u64GuestCr0 |= X86_CR0_WP;
4731 }
4732
4733 /*
4734 * Guest FPU bits.
4735 *
4736 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
4737 * using CR0.TS.
4738 *
4739 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
4740 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
4741 */
4742 u64GuestCr0 |= X86_CR0_NE;
4743
4744 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
4745 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
4746
4747 /*
4748 * Update exception intercepts.
4749 */
4750 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
4751 if (pVmcsInfo->RealMode.fRealOnV86Active)
4752 {
4753 Assert(PDMVmmDevHeapIsEnabled(pVM));
4754 Assert(pVM->hm.s.vmx.pRealModeTSS);
4755 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
4756 }
4757 else
4758 {
4759 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
4760 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
4761 if (fInterceptMF)
4762 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
4763 }
4764
4765 /* Additional intercepts for debugging, define these yourself explicitly. */
4766#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
4767 uXcptBitmap |= 0
4768 | RT_BIT(X86_XCPT_BP)
4769 | RT_BIT(X86_XCPT_DE)
4770 | RT_BIT(X86_XCPT_NM)
4771 | RT_BIT(X86_XCPT_TS)
4772 | RT_BIT(X86_XCPT_UD)
4773 | RT_BIT(X86_XCPT_NP)
4774 | RT_BIT(X86_XCPT_SS)
4775 | RT_BIT(X86_XCPT_GP)
4776 | RT_BIT(X86_XCPT_PF)
4777 | RT_BIT(X86_XCPT_MF)
4778 ;
4779#elif defined(HMVMX_ALWAYS_TRAP_PF)
4780 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
4781#endif
4782 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
4783 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
4784 Assert(pVM->hm.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
4785
4786 /* Apply the fixed CR0 bits and enable caching. */
4787 u64GuestCr0 |= fSetCr0;
4788 u64GuestCr0 &= fZapCr0;
4789 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
4790
4791 /* Commit the CR0 and related fields to the guest VMCS. */
4792 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_CR0, u64GuestCr0); /** @todo Fix to 64-bit when we drop 32-bit. */
4793 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0);
4794 if (uProcCtls != pVmcsInfo->u32ProcCtls)
4795 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
4796 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
4797 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
4798 AssertRCReturn(rc, rc);
4799
4800 /* Update our caches. */
4801 pVmcsInfo->u32ProcCtls = uProcCtls;
4802 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
4803
4804 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
4805 }
4806 else
4807 {
4808 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
4809 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
4810 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
4811 uint64_t const u64ShadowCr0 = pVmcsNstGst->u64Cr0ReadShadow.u;
4812 Assert(!RT_HI_U32(u64GuestCr0));
4813 Assert(u64GuestCr0 & X86_CR0_NE);
4814
4815 /* Apply the fixed CR0 bits and enable caching. */
4816 u64GuestCr0 |= fSetCr0;
4817 u64GuestCr0 &= fZapCr0;
4818 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
4819
4820 /* Commit the CR0 and CR0 read shadow to the nested-guest VMCS. */
4821 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_CR0, u64GuestCr0); /** @todo NSTVMX: Fix to 64-bit when we drop 32-bit. */
4822 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0);
4823 AssertRCReturn(rc, rc);
4824
4825 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
4826 }
4827
4828 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
4829 }
4830
4831 return VINF_SUCCESS;
4832}
4833
4834
4835/**
4836 * Exports the guest control registers (CR3, CR4) into the guest-state area
4837 * in the VMCS.
4838 *
4839 * @returns VBox strict status code.
4840 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
4841 * without unrestricted guest access and the VMMDev is not presently
4842 * mapped (e.g. EFI32).
4843 *
4844 * @param pVCpu The cross context virtual CPU structure.
4845 * @param pVmxTransient The VMX-transient structure.
4846 *
4847 * @remarks No-long-jump zone!!!
4848 */
4849static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
4850{
4851 int rc = VINF_SUCCESS;
4852 PVM pVM = pVCpu->CTX_SUFF(pVM);
4853
4854 /*
4855 * Guest CR2.
4856 * It's always loaded in the assembler code. Nothing to do here.
4857 */
4858
4859 /*
4860 * Guest CR3.
4861 */
4862 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
4863 {
4864 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
4865
4866 RTGCPHYS GCPhysGuestCR3 = NIL_RTGCPHYS;
4867 if (pVM->hm.s.fNestedPaging)
4868 {
4869 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4870 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
4871
4872 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
4873 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
4874 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
4875 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
4876
4877 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
4878 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
4879 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
4880
4881 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
4882 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
4883 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
4884 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
4885 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
4886 || (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
4887 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
4888
4889 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
4890 AssertRCReturn(rc, rc);
4891
4892 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4893 if ( pVM->hm.s.vmx.fUnrestrictedGuest
4894 || CPUMIsGuestPagingEnabledEx(pCtx))
4895 {
4896 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
4897 if (CPUMIsGuestInPAEModeEx(pCtx))
4898 {
4899 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
4900 AssertRCReturn(rc, rc);
4901 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u);
4902 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u);
4903 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u);
4904 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u);
4905 AssertRCReturn(rc, rc);
4906 }
4907
4908 /*
4909 * The guest's view of its CR3 is unblemished with nested paging when the
4910 * guest is using paging or we have unrestricted guest execution to handle
4911 * the guest when it's not using paging.
4912 */
4913 GCPhysGuestCR3 = pCtx->cr3;
4914 }
4915 else
4916 {
4917 /*
4918 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
4919 * thinks it accesses physical memory directly, we use our identity-mapped
4920 * page table to map guest-linear to guest-physical addresses. EPT takes care
4921 * of translating it to host-physical addresses.
4922 */
4923 RTGCPHYS GCPhys;
4924 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
4925
4926 /* We obtain it here every time as the guest could have relocated this PCI region. */
4927 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
4928 if (RT_SUCCESS(rc))
4929 { /* likely */ }
4930 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
4931 {
4932 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
4933 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
4934 }
4935 else
4936 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
4937
4938 GCPhysGuestCR3 = GCPhys;
4939 }
4940
4941 Log4Func(("u32GuestCr3=%#RGp (GstN)\n", GCPhysGuestCR3));
4942 rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_CR3, GCPhysGuestCR3);
4943 AssertRCReturn(rc, rc);
4944 }
4945 else
4946 {
4947 /* Non-nested paging case, just use the hypervisor's CR3. */
4948 RTHCPHYS const HCPhysGuestCR3 = PGMGetHyperCR3(pVCpu);
4949
4950 Log4Func(("u32GuestCr3=%#RHv (HstN)\n", HCPhysGuestCR3));
4951 rc = VMXWriteVmcsHstN(VMX_VMCS_GUEST_CR3, HCPhysGuestCR3);
4952 AssertRCReturn(rc, rc);
4953 }
4954
4955 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
4956 }
4957
4958 /*
4959 * Guest CR4.
4960 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
4961 */
4962 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
4963 {
4964 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4965 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4966 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
4967
4968 /*
4969 * Figure out fixed CR4 bits in VMX operation.
4970 */
4971 uint64_t const fSetCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
4972 uint64_t const fZapCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
4973
4974 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
4975 uint64_t u64GuestCr4 = pCtx->cr4;
4976 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest ? pCtx->cr4 : pVmcsNstGst->u64Cr4ReadShadow.u;
4977 Assert(!RT_HI_U32(u64GuestCr4));
4978
4979 /*
4980 * Setup VT-x's view of the guest CR4.
4981 *
4982 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
4983 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
4984 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
4985 *
4986 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
4987 */
4988 if (pVmcsInfo->RealMode.fRealOnV86Active)
4989 {
4990 Assert(pVM->hm.s.vmx.pRealModeTSS);
4991 Assert(PDMVmmDevHeapIsEnabled(pVM));
4992 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
4993 }
4994
4995 if (pVM->hm.s.fNestedPaging)
4996 {
4997 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
4998 && !pVM->hm.s.vmx.fUnrestrictedGuest)
4999 {
5000 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
5001 u64GuestCr4 |= X86_CR4_PSE;
5002 /* Our identity mapping is a 32-bit page directory. */
5003 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5004 }
5005 /* else use guest CR4.*/
5006 }
5007 else
5008 {
5009 Assert(!pVmxTransient->fIsNestedGuest);
5010
5011 /*
5012 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
5013 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
5014 */
5015 switch (pVCpu->hm.s.enmShadowMode)
5016 {
5017 case PGMMODE_REAL: /* Real-mode. */
5018 case PGMMODE_PROTECTED: /* Protected mode without paging. */
5019 case PGMMODE_32_BIT: /* 32-bit paging. */
5020 {
5021 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5022 break;
5023 }
5024
5025 case PGMMODE_PAE: /* PAE paging. */
5026 case PGMMODE_PAE_NX: /* PAE paging with NX. */
5027 {
5028 u64GuestCr4 |= X86_CR4_PAE;
5029 break;
5030 }
5031
5032 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
5033 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
5034#ifdef VBOX_ENABLE_64_BITS_GUESTS
5035 break;
5036#endif
5037 default:
5038 AssertFailed();
5039 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
5040 }
5041 }
5042
5043 /* Apply the fixed CR4 bits (mainly CR4.VMXE). */
5044 u64GuestCr4 |= fSetCr4;
5045 u64GuestCr4 &= fZapCr4;
5046
5047 /* Commit the CR4 and CR4 read shadow to the guest VMCS. */
5048 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_CR4, u64GuestCr4); /** @todo Fix to 64-bit when we drop 32-bit. */
5049 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4);
5050 AssertRCReturn(rc, rc);
5051
5052 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
5053 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
5054
5055 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
5056
5057 Log4Func(("cr4=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
5058 }
5059 return rc;
5060}
5061
5062
5063/**
5064 * Exports the guest debug registers into the guest-state area in the VMCS.
5065 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
5066 *
5067 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
5068 *
5069 * @returns VBox status code.
5070 * @param pVCpu The cross context virtual CPU structure.
5071 * @param pVmxTransient The VMX-transient structure.
5072 *
5073 * @remarks No-long-jump zone!!!
5074 */
5075static int hmR0VmxExportSharedDebugState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5076{
5077 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5078
5079 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
5080 * stepping. */
5081 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5082 if (pVmxTransient->fIsNestedGuest)
5083 {
5084 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
5085 AssertRCReturn(rc, rc);
5086 return VINF_SUCCESS;
5087 }
5088
5089#ifdef VBOX_STRICT
5090 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
5091 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
5092 {
5093 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
5094 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
5095 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
5096 }
5097#endif
5098
5099 bool fSteppingDB = false;
5100 bool fInterceptMovDRx = false;
5101 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5102 if (pVCpu->hm.s.fSingleInstruction)
5103 {
5104 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
5105 PVM pVM = pVCpu->CTX_SUFF(pVM);
5106 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
5107 {
5108 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
5109 Assert(fSteppingDB == false);
5110 }
5111 else
5112 {
5113 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
5114 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
5115 pVCpu->hm.s.fClearTrapFlag = true;
5116 fSteppingDB = true;
5117 }
5118 }
5119
5120 uint32_t u32GuestDr7;
5121 if ( fSteppingDB
5122 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
5123 {
5124 /*
5125 * Use the combined guest and host DRx values found in the hypervisor register set
5126 * because the hypervisor debugger has breakpoints active or someone is single stepping
5127 * on the host side without a monitor trap flag.
5128 *
5129 * Note! DBGF expects a clean DR6 state before executing guest code.
5130 */
5131#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
5132 if ( CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
5133 && !CPUMIsHyperDebugStateActivePending(pVCpu))
5134 {
5135 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
5136 Assert(CPUMIsHyperDebugStateActivePending(pVCpu));
5137 Assert(!CPUMIsGuestDebugStateActivePending(pVCpu));
5138 }
5139 else
5140#endif
5141 if (!CPUMIsHyperDebugStateActive(pVCpu))
5142 {
5143 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
5144 Assert(CPUMIsHyperDebugStateActive(pVCpu));
5145 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
5146 }
5147
5148 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
5149 u32GuestDr7 = (uint32_t)CPUMGetHyperDR7(pVCpu);
5150 pVCpu->hm.s.fUsingHyperDR7 = true;
5151 fInterceptMovDRx = true;
5152 }
5153 else
5154 {
5155 /*
5156 * If the guest has enabled debug registers, we need to load them prior to
5157 * executing guest code so they'll trigger at the right time.
5158 */
5159 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
5160 {
5161#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
5162 if ( CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
5163 && !CPUMIsGuestDebugStateActivePending(pVCpu))
5164 {
5165 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
5166 Assert(CPUMIsGuestDebugStateActivePending(pVCpu));
5167 Assert(!CPUMIsHyperDebugStateActivePending(pVCpu));
5168 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
5169 }
5170 else
5171#endif
5172 if (!CPUMIsGuestDebugStateActive(pVCpu))
5173 {
5174 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
5175 Assert(CPUMIsGuestDebugStateActive(pVCpu));
5176 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
5177 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
5178 }
5179 Assert(!fInterceptMovDRx);
5180 }
5181 /*
5182 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
5183 * must intercept #DB in order to maintain a correct DR6 guest value, and
5184 * because we need to intercept it to prevent nested #DBs from hanging the
5185 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
5186 */
5187#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
5188 else if ( !CPUMIsGuestDebugStateActivePending(pVCpu)
5189 && !CPUMIsGuestDebugStateActive(pVCpu))
5190#else
5191 else if (!CPUMIsGuestDebugStateActive(pVCpu))
5192#endif
5193 {
5194 fInterceptMovDRx = true;
5195 }
5196
5197 /* Update DR7 with the actual guest value. */
5198 u32GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
5199 pVCpu->hm.s.fUsingHyperDR7 = false;
5200 }
5201
5202 if (fInterceptMovDRx)
5203 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
5204 else
5205 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
5206
5207 /*
5208 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
5209 * monitor-trap flag and update our cache.
5210 */
5211 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5212 {
5213 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5214 AssertRCReturn(rc2, rc2);
5215 pVmcsInfo->u32ProcCtls = uProcCtls;
5216 }
5217
5218 /*
5219 * Update guest DR7.
5220 */
5221 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_DR7, u32GuestDr7);
5222 AssertRCReturn(rc, rc);
5223
5224 /*
5225 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
5226 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
5227 *
5228 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5229 */
5230 if (fSteppingDB)
5231 {
5232 Assert(pVCpu->hm.s.fSingleInstruction);
5233 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
5234
5235 uint32_t fIntrState = 0;
5236 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
5237 AssertRCReturn(rc, rc);
5238
5239 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
5240 {
5241 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
5242 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
5243 AssertRCReturn(rc, rc);
5244 }
5245 }
5246
5247 return VINF_SUCCESS;
5248}
5249
5250
5251#ifdef VBOX_STRICT
5252/**
5253 * Strict function to validate segment registers.
5254 *
5255 * @param pVCpu The cross context virtual CPU structure.
5256 * @param pVmcsInfo The VMCS info. object.
5257 *
5258 * @remarks Will import guest CR0 on strict builds during validation of
5259 * segments.
5260 */
5261static void hmR0VmxValidateSegmentRegs(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
5262{
5263 /*
5264 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
5265 *
5266 * The reason we check for attribute value 0 in this function and not just the unusable bit is
5267 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
5268 * unusable bit and doesn't change the guest-context value.
5269 */
5270 PVM pVM = pVCpu->CTX_SUFF(pVM);
5271 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5272 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
5273 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
5274 && ( !CPUMIsGuestInRealModeEx(pCtx)
5275 && !CPUMIsGuestInV86ModeEx(pCtx)))
5276 {
5277 /* Protected mode checks */
5278 /* CS */
5279 Assert(pCtx->cs.Attr.n.u1Present);
5280 Assert(!(pCtx->cs.Attr.u & 0xf00));
5281 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
5282 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
5283 || !(pCtx->cs.Attr.n.u1Granularity));
5284 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
5285 || (pCtx->cs.Attr.n.u1Granularity));
5286 /* CS cannot be loaded with NULL in protected mode. */
5287 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
5288 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
5289 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
5290 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
5291 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
5292 else
5293 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
5294 /* SS */
5295 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
5296 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
5297 if ( !(pCtx->cr0 & X86_CR0_PE)
5298 || pCtx->cs.Attr.n.u4Type == 3)
5299 {
5300 Assert(!pCtx->ss.Attr.n.u2Dpl);
5301 }
5302 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
5303 {
5304 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
5305 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
5306 Assert(pCtx->ss.Attr.n.u1Present);
5307 Assert(!(pCtx->ss.Attr.u & 0xf00));
5308 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
5309 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
5310 || !(pCtx->ss.Attr.n.u1Granularity));
5311 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
5312 || (pCtx->ss.Attr.n.u1Granularity));
5313 }
5314 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
5315 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
5316 {
5317 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5318 Assert(pCtx->ds.Attr.n.u1Present);
5319 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
5320 Assert(!(pCtx->ds.Attr.u & 0xf00));
5321 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
5322 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
5323 || !(pCtx->ds.Attr.n.u1Granularity));
5324 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
5325 || (pCtx->ds.Attr.n.u1Granularity));
5326 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5327 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
5328 }
5329 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
5330 {
5331 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5332 Assert(pCtx->es.Attr.n.u1Present);
5333 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
5334 Assert(!(pCtx->es.Attr.u & 0xf00));
5335 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
5336 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
5337 || !(pCtx->es.Attr.n.u1Granularity));
5338 Assert( !(pCtx->es.u32Limit & 0xfff00000)
5339 || (pCtx->es.Attr.n.u1Granularity));
5340 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5341 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
5342 }
5343 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
5344 {
5345 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5346 Assert(pCtx->fs.Attr.n.u1Present);
5347 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
5348 Assert(!(pCtx->fs.Attr.u & 0xf00));
5349 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
5350 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
5351 || !(pCtx->fs.Attr.n.u1Granularity));
5352 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
5353 || (pCtx->fs.Attr.n.u1Granularity));
5354 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5355 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
5356 }
5357 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
5358 {
5359 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5360 Assert(pCtx->gs.Attr.n.u1Present);
5361 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
5362 Assert(!(pCtx->gs.Attr.u & 0xf00));
5363 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
5364 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
5365 || !(pCtx->gs.Attr.n.u1Granularity));
5366 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
5367 || (pCtx->gs.Attr.n.u1Granularity));
5368 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5369 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
5370 }
5371 /* 64-bit capable CPUs. */
5372# if HC_ARCH_BITS == 64
5373 Assert(!RT_HI_U32(pCtx->cs.u64Base));
5374 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
5375 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
5376 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
5377# endif
5378 }
5379 else if ( CPUMIsGuestInV86ModeEx(pCtx)
5380 || ( CPUMIsGuestInRealModeEx(pCtx)
5381 && !pVM->hm.s.vmx.fUnrestrictedGuest))
5382 {
5383 /* Real and v86 mode checks. */
5384 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
5385 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
5386 if (pVmcsInfo->RealMode.fRealOnV86Active)
5387 {
5388 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
5389 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
5390 }
5391 else
5392 {
5393 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
5394 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
5395 }
5396
5397 /* CS */
5398 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
5399 Assert(pCtx->cs.u32Limit == 0xffff);
5400 Assert(u32CSAttr == 0xf3);
5401 /* SS */
5402 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
5403 Assert(pCtx->ss.u32Limit == 0xffff);
5404 Assert(u32SSAttr == 0xf3);
5405 /* DS */
5406 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
5407 Assert(pCtx->ds.u32Limit == 0xffff);
5408 Assert(u32DSAttr == 0xf3);
5409 /* ES */
5410 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
5411 Assert(pCtx->es.u32Limit == 0xffff);
5412 Assert(u32ESAttr == 0xf3);
5413 /* FS */
5414 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
5415 Assert(pCtx->fs.u32Limit == 0xffff);
5416 Assert(u32FSAttr == 0xf3);
5417 /* GS */
5418 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
5419 Assert(pCtx->gs.u32Limit == 0xffff);
5420 Assert(u32GSAttr == 0xf3);
5421 /* 64-bit capable CPUs. */
5422# if HC_ARCH_BITS == 64
5423 Assert(!RT_HI_U32(pCtx->cs.u64Base));
5424 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
5425 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
5426 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
5427# endif
5428 }
5429}
5430#endif /* VBOX_STRICT */
5431
5432
5433/**
5434 * Exports a guest segment register into the guest-state area in the VMCS.
5435 *
5436 * @returns VBox status code.
5437 * @param pVCpu The cross context virtual CPU structure.
5438 * @param pVmcsInfo The VMCS info. object.
5439 * @param iSegReg The segment register number (X86_SREG_XXX).
5440 * @param pSelReg Pointer to the segment selector.
5441 *
5442 * @remarks No-long-jump zone!!!
5443 */
5444static int hmR0VmxExportGuestSegReg(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, uint8_t iSegReg, PCCPUMSELREG pSelReg)
5445{
5446 Assert(iSegReg < X86_SREG_COUNT);
5447 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
5448 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
5449 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
5450 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
5451
5452 uint32_t u32Access = pSelReg->Attr.u;
5453 if (pVmcsInfo->RealMode.fRealOnV86Active)
5454 {
5455 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
5456 u32Access = 0xf3;
5457 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
5458 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
5459 RT_NOREF_PV(pVCpu);
5460 }
5461 else
5462 {
5463 /*
5464 * The way to differentiate between whether this is really a null selector or was just
5465 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
5466 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
5467 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
5468 * NULL selectors loaded in protected-mode have their attribute as 0.
5469 */
5470 if (!u32Access)
5471 u32Access = X86DESCATTR_UNUSABLE;
5472 }
5473
5474 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
5475 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
5476 ("Access bit not set for usable segment. idx=%#x sel=%#x attr %#x\n", idxBase, pSelReg, pSelReg->Attr.u));
5477
5478 /*
5479 * Commit it to the VMCS.
5480 */
5481 int rc = VMXWriteVmcs32(idxSel, pSelReg->Sel);
5482 rc |= VMXWriteVmcs32(idxLimit, pSelReg->u32Limit);
5483 rc |= VMXWriteVmcsGstN(idxBase, pSelReg->u64Base);
5484 rc |= VMXWriteVmcs32(idxAttr, u32Access);
5485 AssertRCReturn(rc, rc);
5486 return rc;
5487}
5488
5489
5490/**
5491 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
5492 * area in the VMCS.
5493 *
5494 * @returns VBox status code.
5495 * @param pVCpu The cross context virtual CPU structure.
5496 * @param pVmxTransient The VMX-transient structure.
5497 *
5498 * @remarks Will import guest CR0 on strict builds during validation of
5499 * segments.
5500 * @remarks No-long-jump zone!!!
5501 */
5502static int hmR0VmxExportGuestSegRegsXdtr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5503{
5504 int rc = VERR_INTERNAL_ERROR_5;
5505 PVM pVM = pVCpu->CTX_SUFF(pVM);
5506 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5507 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5508
5509 /*
5510 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
5511 */
5512 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
5513 {
5514#ifdef VBOX_WITH_REM
5515 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
5516 {
5517 Assert(!pVmxTransient->fIsNestedGuest);
5518 Assert(pVM->hm.s.vmx.pRealModeTSS);
5519 AssertCompile(PGMMODE_REAL < PGMMODE_PROTECTED);
5520 if ( pVmcsInfo->fWasInRealMode
5521 && PGMGetGuestMode(pVCpu) >= PGMMODE_PROTECTED)
5522 {
5523 /* Signal that the recompiler must flush its code-cache as the guest -may- rewrite code it will later execute
5524 in real-mode (e.g. OpenBSD 4.0) */
5525 REMFlushTBs(pVM);
5526 Log4Func(("Switch to protected mode detected!\n"));
5527 pVmcsInfo->fWasInRealMode = false;
5528 }
5529 }
5530#endif
5531 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
5532 {
5533 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
5534 if (pVmcsInfo->RealMode.fRealOnV86Active)
5535 pVmcsInfo->RealMode.AttrCS.u = pCtx->cs.Attr.u;
5536 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
5537 AssertRCReturn(rc, rc);
5538 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
5539 }
5540
5541 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
5542 {
5543 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
5544 if (pVmcsInfo->RealMode.fRealOnV86Active)
5545 pVmcsInfo->RealMode.AttrSS.u = pCtx->ss.Attr.u;
5546 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
5547 AssertRCReturn(rc, rc);
5548 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
5549 }
5550
5551 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
5552 {
5553 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
5554 if (pVmcsInfo->RealMode.fRealOnV86Active)
5555 pVmcsInfo->RealMode.AttrDS.u = pCtx->ds.Attr.u;
5556 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
5557 AssertRCReturn(rc, rc);
5558 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
5559 }
5560
5561 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
5562 {
5563 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
5564 if (pVmcsInfo->RealMode.fRealOnV86Active)
5565 pVmcsInfo->RealMode.AttrES.u = pCtx->es.Attr.u;
5566 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
5567 AssertRCReturn(rc, rc);
5568 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
5569 }
5570
5571 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
5572 {
5573 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
5574 if (pVmcsInfo->RealMode.fRealOnV86Active)
5575 pVmcsInfo->RealMode.AttrFS.u = pCtx->fs.Attr.u;
5576 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
5577 AssertRCReturn(rc, rc);
5578 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
5579 }
5580
5581 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
5582 {
5583 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
5584 if (pVmcsInfo->RealMode.fRealOnV86Active)
5585 pVmcsInfo->RealMode.AttrGS.u = pCtx->gs.Attr.u;
5586 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
5587 AssertRCReturn(rc, rc);
5588 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
5589 }
5590
5591#ifdef VBOX_STRICT
5592 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
5593#endif
5594 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
5595 pCtx->cs.Attr.u));
5596 }
5597
5598 /*
5599 * Guest TR.
5600 */
5601 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
5602 {
5603 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
5604
5605 /*
5606 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
5607 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
5608 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
5609 */
5610 uint16_t u16Sel;
5611 uint32_t u32Limit;
5612 uint64_t u64Base;
5613 uint32_t u32AccessRights;
5614 if (!pVmcsInfo->RealMode.fRealOnV86Active)
5615 {
5616 u16Sel = pCtx->tr.Sel;
5617 u32Limit = pCtx->tr.u32Limit;
5618 u64Base = pCtx->tr.u64Base;
5619 u32AccessRights = pCtx->tr.Attr.u;
5620 }
5621 else
5622 {
5623 Assert(!pVmxTransient->fIsNestedGuest);
5624 Assert(pVM->hm.s.vmx.pRealModeTSS);
5625 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
5626
5627 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
5628 RTGCPHYS GCPhys;
5629 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
5630 AssertRCReturn(rc, rc);
5631
5632 X86DESCATTR DescAttr;
5633 DescAttr.u = 0;
5634 DescAttr.n.u1Present = 1;
5635 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
5636
5637 u16Sel = 0;
5638 u32Limit = HM_VTX_TSS_SIZE;
5639 u64Base = GCPhys;
5640 u32AccessRights = DescAttr.u;
5641 }
5642
5643 /* Validate. */
5644 Assert(!(u16Sel & RT_BIT(2)));
5645 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
5646 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
5647 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
5648 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
5649 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
5650 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
5651 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
5652 Assert( (u32Limit & 0xfff) == 0xfff
5653 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
5654 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
5655 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
5656
5657 rc = VMXWriteVmcs32(VMX_VMCS16_GUEST_TR_SEL, u16Sel);
5658 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit);
5659 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights);
5660 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_TR_BASE, u64Base);
5661 AssertRCReturn(rc, rc);
5662
5663 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
5664 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
5665 }
5666
5667 /*
5668 * Guest GDTR.
5669 */
5670 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
5671 {
5672 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
5673
5674 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt);
5675 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt);
5676 AssertRCReturn(rc, rc);
5677
5678 /* Validate. */
5679 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
5680
5681 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
5682 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
5683 }
5684
5685 /*
5686 * Guest LDTR.
5687 */
5688 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
5689 {
5690 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
5691
5692 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
5693 uint32_t u32Access;
5694 if ( !pVmxTransient->fIsNestedGuest
5695 && !pCtx->ldtr.Attr.u)
5696 u32Access = X86DESCATTR_UNUSABLE;
5697 else
5698 u32Access = pCtx->ldtr.Attr.u;
5699
5700 rc = VMXWriteVmcs32(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel);
5701 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit);
5702 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access);
5703 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base);
5704 AssertRCReturn(rc, rc);
5705
5706 /* Validate. */
5707 if (!(u32Access & X86DESCATTR_UNUSABLE))
5708 {
5709 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
5710 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
5711 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
5712 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
5713 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
5714 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
5715 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
5716 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
5717 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
5718 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
5719 }
5720
5721 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
5722 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
5723 }
5724
5725 /*
5726 * Guest IDTR.
5727 */
5728 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
5729 {
5730 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
5731
5732 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt);
5733 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt);
5734 AssertRCReturn(rc, rc);
5735
5736 /* Validate. */
5737 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
5738
5739 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
5740 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
5741 }
5742
5743 return VINF_SUCCESS;
5744}
5745
5746
5747/**
5748 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
5749 * areas.
5750 *
5751 * These MSRs will automatically be loaded to the host CPU on every successful
5752 * VM-entry and stored from the host CPU on every successful VM-exit.
5753 *
5754 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
5755 * actual host MSR values are not- updated here for performance reasons. See
5756 * hmR0VmxExportHostMsrs().
5757 *
5758 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
5759 *
5760 * @returns VBox status code.
5761 * @param pVCpu The cross context virtual CPU structure.
5762 * @param pVmxTransient The VMX-transient structure.
5763 *
5764 * @remarks No-long-jump zone!!!
5765 */
5766static int hmR0VmxExportGuestMsrs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5767{
5768 AssertPtr(pVCpu);
5769 AssertPtr(pVmxTransient);
5770
5771 PVM pVM = pVCpu->CTX_SUFF(pVM);
5772 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5773
5774 /*
5775 * MSRs that we use the auto-load/store MSR area in the VMCS.
5776 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs().
5777 * The host MSR values are updated when it's safe in hmR0VmxLazySaveHostMsrs().
5778 *
5779 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
5780 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
5781 * emulation, nothing to do here.
5782 */
5783 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
5784 {
5785 if ( !pVmxTransient->fIsNestedGuest
5786 && pVM->hm.s.fAllow64BitGuests)
5787 {
5788#if HC_ARCH_BITS == 32
5789 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSCALL_MSRS | CPUMCTX_EXTRN_KERNEL_GS_BASE);
5790 Assert(!pVmxTransient->fIsNestedGuest);
5791
5792 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_LSTAR, pCtx->msrLSTAR, true, false);
5793 rc |= hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_STAR, pCtx->msrSTAR, true, false);
5794 rc |= hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_SF_MASK, pCtx->msrSFMASK, true, false);
5795 rc |= hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE, true, false);
5796 AssertRCReturn(rc, rc);
5797#endif
5798 }
5799 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
5800 }
5801
5802 /*
5803 * Guest Sysenter MSRs.
5804 */
5805 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
5806 {
5807 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
5808
5809 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
5810 {
5811 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
5812 AssertRCReturn(rc, rc);
5813 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
5814 }
5815
5816 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
5817 {
5818 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
5819 AssertRCReturn(rc, rc);
5820 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
5821 }
5822
5823 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
5824 {
5825 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
5826 AssertRCReturn(rc, rc);
5827 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
5828 }
5829 }
5830
5831 /*
5832 * Guest/host EFER MSR.
5833 */
5834 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
5835 {
5836 /* Whether we are using the VMCS to swap the EFER MSR must have been
5837 determined earlier while exporting VM-entry/VM-exit controls. */
5838 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
5839 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
5840
5841 if (hmR0VmxShouldSwapEferMsr(pVCpu))
5842 {
5843 /*
5844 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
5845 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
5846 */
5847 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
5848 {
5849 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, pCtx->msrEFER);
5850 AssertRCReturn(rc, rc);
5851 }
5852 else
5853 {
5854 /*
5855 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
5856 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
5857 */
5858 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, pCtx->msrEFER,
5859 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
5860 AssertRCReturn(rc, rc);
5861 }
5862 }
5863 else if (!pVM->hm.s.vmx.fSupportsVmcsEfer)
5864 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
5865
5866 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
5867 }
5868
5869 /*
5870 * Other MSRs.
5871 * Speculation Control (R/W).
5872 */
5873 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
5874 {
5875 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
5876 if (pVM->cpum.ro.GuestFeatures.fIbrs)
5877 {
5878 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
5879 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
5880 AssertRCReturn(rc, rc);
5881 }
5882 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
5883 }
5884
5885 return VINF_SUCCESS;
5886}
5887
5888
5889/**
5890 * Selects up the appropriate function to run guest code.
5891 *
5892 * @returns VBox status code.
5893 * @param pVCpu The cross context virtual CPU structure.
5894 * @param pVmxTransient The VMX-transient structure.
5895 *
5896 * @remarks No-long-jump zone!!!
5897 */
5898static int hmR0VmxSelectVMRunHandler(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5899{
5900 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5901 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5902
5903 if (CPUMIsGuestInLongModeEx(pCtx))
5904 {
5905#ifndef VBOX_ENABLE_64_BITS_GUESTS
5906 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
5907#endif
5908 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests); /* Guaranteed by hmR3InitFinalizeR0(). */
5909#if HC_ARCH_BITS == 32
5910 /* 32-bit host. We need to switch to 64-bit before running the 64-bit guest. */
5911 if (pVmcsInfo->pfnStartVM != VMXR0SwitcherStartVM64)
5912 {
5913#ifdef VBOX_STRICT
5914 if (pVmcsInfo->pfnStartVM != NULL) /* Very first VM-entry would have saved host-state already, ignore it. */
5915 {
5916 /* Currently, all mode changes sends us back to ring-3, so these should be set. See @bugref{6944}. */
5917 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
5918 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
5919 AssertMsg(fCtxChanged & (HM_CHANGED_VMX_ENTRY_EXIT_CTLS | HM_CHANGED_GUEST_EFER_MSR),
5920 ("fCtxChanged=%#RX64\n", fCtxChanged));
5921 }
5922#endif
5923 pVmcsInfo->pfnStartVM = VMXR0SwitcherStartVM64;
5924
5925 /* Mark that we've switched to 64-bit handler, we can't safely switch back to 32-bit for
5926 the rest of the VM run (until VM reset). See @bugref{8432#c7}. */
5927 pVmcsInfo->fSwitchedTo64on32 = true;
5928 Log4Func(("Selected 64-bit switcher\n"));
5929 }
5930#else
5931 /* 64-bit host. */
5932 pVmcsInfo->pfnStartVM = VMXR0StartVM64;
5933#endif
5934 }
5935 else
5936 {
5937 /* Guest is not in long mode, use the 32-bit handler. */
5938#if HC_ARCH_BITS == 32
5939 if ( pVmcsInfo->pfnStartVM != VMXR0StartVM32
5940 && !pVmcsInfo->fSwitchedTo64on32 /* If set, guest mode change does not imply switcher change. */
5941 && pVmcsInfo->pfnStartVM != NULL) /* Very first VM-entry would have saved host-state already, ignore it. */
5942 {
5943# ifdef VBOX_STRICT
5944 /* Currently, all mode changes sends us back to ring-3, so these should be set. See @bugref{6944}. */
5945 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
5946 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
5947 AssertMsg(fCtxChanged & (HM_CHANGED_VMX_ENTRY_EXIT_CTLS | HM_CHANGED_GUEST_EFER_MSR),
5948 ("fCtxChanged=%#RX64\n", fCtxChanged));
5949# endif
5950 }
5951# ifdef VBOX_ENABLE_64_BITS_GUESTS
5952 /*
5953 * Keep using the 64-bit switcher even though we're in 32-bit because of bad Intel
5954 * design, see @bugref{8432#c7}. If real-on-v86 mode is active, clear the 64-bit
5955 * switcher flag now because we know the guest is in a sane state where it's safe
5956 * to use the 32-bit switcher. Otherwise, check the guest state if it's safe to use
5957 * the much faster 32-bit switcher again.
5958 */
5959 if (!pVmcsInfo->fSwitchedTo64on32)
5960 {
5961 if (pVmcsInfo->pfnStartVM != VMXR0StartVM32)
5962 Log4Func(("Selected 32-bit switcher\n"));
5963 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
5964 }
5965 else
5966 {
5967 Assert(pVmcsInfo->pfnStartVM == VMXR0SwitcherStartVM64);
5968 if ( pVmcsInfo->RealMode.fRealOnV86Active
5969 || hmR0VmxIs32BitSwitcherSafe(pCtx))
5970 {
5971 pVmcsInfo->fSwitchedTo64on32 = false;
5972 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
5973 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR
5974 | HM_CHANGED_VMX_ENTRY_EXIT_CTLS
5975 | HM_CHANGED_HOST_CONTEXT);
5976 Log4Func(("Selected 32-bit switcher (safe)\n"));
5977 }
5978 }
5979# else
5980 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
5981# endif
5982#else
5983 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
5984#endif
5985 }
5986 Assert(pVmcsInfo->pfnStartVM);
5987 return VINF_SUCCESS;
5988}
5989
5990
5991/**
5992 * Wrapper for running the guest code in VT-x.
5993 *
5994 * @returns VBox status code, no informational status codes.
5995 * @param pVCpu The cross context virtual CPU structure.
5996 * @param pVmxTransient The VMX-transient structure.
5997 *
5998 * @remarks No-long-jump zone!!!
5999 */
6000DECLINLINE(int) hmR0VmxRunGuest(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6001{
6002 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
6003 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6004 pCtx->fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
6005
6006 /** @todo Add stats for VMRESUME vs VMLAUNCH. */
6007
6008 /*
6009 * 64-bit Windows uses XMM registers in the kernel as the Microsoft compiler expresses
6010 * floating-point operations using SSE instructions. Some XMM registers (XMM6-XMM15) are
6011 * callee-saved and thus the need for this XMM wrapper.
6012 *
6013 * See MSDN "Configuring Programs for 64-bit/x64 Software Conventions / Register Usage".
6014 */
6015 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6016 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
6017 PVM pVM = pVCpu->CTX_SUFF(pVM);
6018#ifdef VBOX_WITH_KERNEL_USING_XMM
6019 int rc = hmR0VMXStartVMWrapXMM(fResumeVM, pCtx, &pVCpu->hm.s.vmx.VmcsCache, pVM, pVCpu, pVmcsInfo->pfnStartVM);
6020#else
6021 int rc = pVmcsInfo->pfnStartVM(fResumeVM, pCtx, &pVCpu->hm.s.vmx.VmcsCache, pVM, pVCpu);
6022#endif
6023 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
6024 return rc;
6025}
6026
6027
6028/**
6029 * Reports world-switch error and dumps some useful debug info.
6030 *
6031 * @param pVCpu The cross context virtual CPU structure.
6032 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
6033 * @param pVmxTransient The VMX-transient structure (only
6034 * exitReason updated).
6035 */
6036static void hmR0VmxReportWorldSwitchError(PVMCPU pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
6037{
6038 Assert(pVCpu);
6039 Assert(pVmxTransient);
6040 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
6041
6042 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
6043 switch (rcVMRun)
6044 {
6045 case VERR_VMX_INVALID_VMXON_PTR:
6046 AssertFailed();
6047 break;
6048 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
6049 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
6050 {
6051 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
6052 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
6053 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
6054 AssertRC(rc);
6055
6056 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
6057 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
6058 Cannot do it here as we may have been long preempted. */
6059
6060#ifdef VBOX_STRICT
6061 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6062 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
6063 pVmxTransient->uExitReason));
6064 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
6065 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
6066 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
6067 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
6068 else
6069 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
6070 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
6071 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
6072
6073 /* VMX control bits. */
6074 uint32_t u32Val;
6075 uint64_t u64Val;
6076 RTHCUINTREG uHCReg;
6077 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val); AssertRC(rc);
6078 Log4(("VMX_VMCS32_CTRL_PIN_EXEC %#RX32\n", u32Val));
6079 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val); AssertRC(rc);
6080 Log4(("VMX_VMCS32_CTRL_PROC_EXEC %#RX32\n", u32Val));
6081 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
6082 {
6083 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val); AssertRC(rc);
6084 Log4(("VMX_VMCS32_CTRL_PROC_EXEC2 %#RX32\n", u32Val));
6085 }
6086 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val); AssertRC(rc);
6087 Log4(("VMX_VMCS32_CTRL_ENTRY %#RX32\n", u32Val));
6088 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val); AssertRC(rc);
6089 Log4(("VMX_VMCS32_CTRL_EXIT %#RX32\n", u32Val));
6090 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_CR3_TARGET_COUNT, &u32Val); AssertRC(rc);
6091 Log4(("VMX_VMCS32_CTRL_CR3_TARGET_COUNT %#RX32\n", u32Val));
6092 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32Val); AssertRC(rc);
6093 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", u32Val));
6094 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &u32Val); AssertRC(rc);
6095 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", u32Val));
6096 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &u32Val); AssertRC(rc);
6097 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %u\n", u32Val));
6098 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, &u32Val); AssertRC(rc);
6099 Log4(("VMX_VMCS32_CTRL_TPR_THRESHOLD %u\n", u32Val));
6100 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &u32Val); AssertRC(rc);
6101 Log4(("VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT %u (guest MSRs)\n", u32Val));
6102 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &u32Val); AssertRC(rc);
6103 Log4(("VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT %u (host MSRs)\n", u32Val));
6104 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &u32Val); AssertRC(rc);
6105 Log4(("VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT %u (guest MSRs)\n", u32Val));
6106 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val); AssertRC(rc);
6107 Log4(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP %#RX32\n", u32Val));
6108 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, &u32Val); AssertRC(rc);
6109 Log4(("VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK %#RX32\n", u32Val));
6110 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, &u32Val); AssertRC(rc);
6111 Log4(("VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH %#RX32\n", u32Val));
6112 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, &uHCReg); AssertRC(rc);
6113 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RHr\n", uHCReg));
6114 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, &uHCReg); AssertRC(rc);
6115 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
6116 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, &uHCReg); AssertRC(rc);
6117 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RHr\n", uHCReg));
6118 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_READ_SHADOW, &uHCReg); AssertRC(rc);
6119 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
6120 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
6121 {
6122 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
6123 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
6124 }
6125
6126 /* Guest bits. */
6127 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RIP, &u64Val); AssertRC(rc);
6128 Log4(("Old Guest Rip %#RX64 New %#RX64\n", pVCpu->cpum.GstCtx.rip, u64Val));
6129 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RSP, &u64Val); AssertRC(rc);
6130 Log4(("Old Guest Rsp %#RX64 New %#RX64\n", pVCpu->cpum.GstCtx.rsp, u64Val));
6131 rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &u32Val); AssertRC(rc);
6132 Log4(("Old Guest Rflags %#RX32 New %#RX32\n", pVCpu->cpum.GstCtx.eflags.u32, u32Val));
6133 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid)
6134 {
6135 rc = VMXReadVmcs32(VMX_VMCS16_VPID, &u32Val); AssertRC(rc);
6136 Log4(("VMX_VMCS16_VPID %u\n", u32Val));
6137 }
6138
6139 /* Host bits. */
6140 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_CR0, &uHCReg); AssertRC(rc);
6141 Log4(("Host CR0 %#RHr\n", uHCReg));
6142 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_CR3, &uHCReg); AssertRC(rc);
6143 Log4(("Host CR3 %#RHr\n", uHCReg));
6144 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_CR4, &uHCReg); AssertRC(rc);
6145 Log4(("Host CR4 %#RHr\n", uHCReg));
6146
6147 RTGDTR HostGdtr;
6148 PCX86DESCHC pDesc;
6149 ASMGetGDTR(&HostGdtr);
6150 rc = VMXReadVmcs32(VMX_VMCS16_HOST_CS_SEL, &u32Val); AssertRC(rc);
6151 Log4(("Host CS %#08x\n", u32Val));
6152 if (u32Val < HostGdtr.cbGdt)
6153 {
6154 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
6155 hmR0DumpDescriptor(pDesc, u32Val, "CS: ");
6156 }
6157
6158 rc = VMXReadVmcs32(VMX_VMCS16_HOST_DS_SEL, &u32Val); AssertRC(rc);
6159 Log4(("Host DS %#08x\n", u32Val));
6160 if (u32Val < HostGdtr.cbGdt)
6161 {
6162 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
6163 hmR0DumpDescriptor(pDesc, u32Val, "DS: ");
6164 }
6165
6166 rc = VMXReadVmcs32(VMX_VMCS16_HOST_ES_SEL, &u32Val); AssertRC(rc);
6167 Log4(("Host ES %#08x\n", u32Val));
6168 if (u32Val < HostGdtr.cbGdt)
6169 {
6170 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
6171 hmR0DumpDescriptor(pDesc, u32Val, "ES: ");
6172 }
6173
6174 rc = VMXReadVmcs32(VMX_VMCS16_HOST_FS_SEL, &u32Val); AssertRC(rc);
6175 Log4(("Host FS %#08x\n", u32Val));
6176 if (u32Val < HostGdtr.cbGdt)
6177 {
6178 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
6179 hmR0DumpDescriptor(pDesc, u32Val, "FS: ");
6180 }
6181
6182 rc = VMXReadVmcs32(VMX_VMCS16_HOST_GS_SEL, &u32Val); AssertRC(rc);
6183 Log4(("Host GS %#08x\n", u32Val));
6184 if (u32Val < HostGdtr.cbGdt)
6185 {
6186 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
6187 hmR0DumpDescriptor(pDesc, u32Val, "GS: ");
6188 }
6189
6190 rc = VMXReadVmcs32(VMX_VMCS16_HOST_SS_SEL, &u32Val); AssertRC(rc);
6191 Log4(("Host SS %#08x\n", u32Val));
6192 if (u32Val < HostGdtr.cbGdt)
6193 {
6194 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
6195 hmR0DumpDescriptor(pDesc, u32Val, "SS: ");
6196 }
6197
6198 rc = VMXReadVmcs32(VMX_VMCS16_HOST_TR_SEL, &u32Val); AssertRC(rc);
6199 Log4(("Host TR %#08x\n", u32Val));
6200 if (u32Val < HostGdtr.cbGdt)
6201 {
6202 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
6203 hmR0DumpDescriptor(pDesc, u32Val, "TR: ");
6204 }
6205
6206 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_TR_BASE, &uHCReg); AssertRC(rc);
6207 Log4(("Host TR Base %#RHv\n", uHCReg));
6208 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_GDTR_BASE, &uHCReg); AssertRC(rc);
6209 Log4(("Host GDTR Base %#RHv\n", uHCReg));
6210 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_IDTR_BASE, &uHCReg); AssertRC(rc);
6211 Log4(("Host IDTR Base %#RHv\n", uHCReg));
6212 rc = VMXReadVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, &u32Val); AssertRC(rc);
6213 Log4(("Host SYSENTER CS %#08x\n", u32Val));
6214 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_SYSENTER_EIP, &uHCReg); AssertRC(rc);
6215 Log4(("Host SYSENTER EIP %#RHv\n", uHCReg));
6216 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_SYSENTER_ESP, &uHCReg); AssertRC(rc);
6217 Log4(("Host SYSENTER ESP %#RHv\n", uHCReg));
6218 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_RSP, &uHCReg); AssertRC(rc);
6219 Log4(("Host RSP %#RHv\n", uHCReg));
6220 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_RIP, &uHCReg); AssertRC(rc);
6221 Log4(("Host RIP %#RHv\n", uHCReg));
6222# if HC_ARCH_BITS == 64
6223 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
6224 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
6225 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
6226 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
6227 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
6228 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
6229# endif
6230#endif /* VBOX_STRICT */
6231 break;
6232 }
6233
6234 default:
6235 /* Impossible */
6236 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
6237 break;
6238 }
6239}
6240
6241
6242#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
6243# ifndef VMX_USE_CACHED_VMCS_ACCESSES
6244# error "VMX_USE_CACHED_VMCS_ACCESSES not defined when it should be!"
6245# endif
6246
6247/**
6248 * Initialize the VMCS-Read cache.
6249 *
6250 * The VMCS cache is used for 32-bit hosts running 64-bit guests (except 32-bit
6251 * Darwin which runs with 64-bit paging in 32-bit mode) for 64-bit fields that
6252 * cannot be accessed in 32-bit mode. Some 64-bit fields -can- be accessed
6253 * (those that have a 32-bit FULL & HIGH part).
6254 *
6255 * @param pVCpu The cross context virtual CPU structure.
6256 */
6257static void hmR0VmxInitVmcsReadCache(PVMCPU pVCpu)
6258{
6259#define VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, idxField) \
6260 do { \
6261 Assert(pCache->Read.aField[idxField##_CACHE_IDX] == 0); \
6262 pCache->Read.aField[idxField##_CACHE_IDX] = idxField; \
6263 pCache->Read.aFieldVal[idxField##_CACHE_IDX] = 0; \
6264 ++cReadFields; \
6265 } while (0)
6266
6267 PVMXVMCSCACHE pCache = &pVCpu->hm.s.vmx.VmcsCache;
6268 uint32_t cReadFields = 0;
6269
6270 /*
6271 * Don't remove the #if 0'd fields in this code. They're listed here for consistency
6272 * and serve to indicate exceptions to the rules.
6273 */
6274
6275 /* Guest-natural selector base fields. */
6276#if 0
6277 /* These are 32-bit in practice. See Intel spec. 2.5 "Control Registers". */
6278 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR0);
6279 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR4);
6280#endif
6281 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_ES_BASE);
6282 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CS_BASE);
6283 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_SS_BASE);
6284 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_DS_BASE);
6285 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_FS_BASE);
6286 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_GS_BASE);
6287 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_LDTR_BASE);
6288 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_TR_BASE);
6289 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_GDTR_BASE);
6290 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_IDTR_BASE);
6291 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_RSP);
6292 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_RIP);
6293#if 0
6294 /* Unused natural width guest-state fields. */
6295 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS);
6296 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR3); /* Handled in nested paging case */
6297#endif
6298 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_SYSENTER_ESP);
6299 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_SYSENTER_EIP);
6300
6301 /* 64-bit guest-state fields; unused as we use two 32-bit VMREADs for
6302 these 64-bit fields (using "FULL" and "HIGH" fields). */
6303#if 0
6304 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL);
6305 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_DEBUGCTL_FULL);
6306 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PAT_FULL);
6307 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_EFER_FULL);
6308 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL);
6309 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE0_FULL);
6310 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE1_FULL);
6311 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE2_FULL);
6312 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE3_FULL);
6313#endif
6314
6315 /* Natural width guest-state fields. */
6316 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_RO_EXIT_QUALIFICATION);
6317 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_RO_GUEST_LINEAR_ADDR);
6318
6319 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
6320 {
6321 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR3);
6322 AssertMsg(cReadFields == VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX, ("cReadFields=%u expected %u\n", cReadFields,
6323 VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX));
6324 pCache->Read.cValidEntries = VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX;
6325 }
6326 else
6327 {
6328 AssertMsg(cReadFields == VMX_VMCS_MAX_CACHE_IDX, ("cReadFields=%u expected %u\n", cReadFields, VMX_VMCS_MAX_CACHE_IDX));
6329 pCache->Read.cValidEntries = VMX_VMCS_MAX_CACHE_IDX;
6330 }
6331
6332#undef VMXLOCAL_INIT_READ_CACHE_FIELD
6333}
6334
6335
6336/**
6337 * Writes a field into the VMCS. This can either directly invoke a VMWRITE or
6338 * queue up the VMWRITE by using the VMCS write cache (on 32-bit hosts, except
6339 * darwin, running 64-bit guests).
6340 *
6341 * @returns VBox status code.
6342 * @param pVCpu The cross context virtual CPU structure.
6343 * @param idxField The VMCS field encoding.
6344 * @param u64Val 16, 32 or 64-bit value.
6345 */
6346VMMR0DECL(int) VMXWriteVmcs64Ex(PVMCPU pVCpu, uint32_t idxField, uint64_t u64Val)
6347{
6348 int rc;
6349 switch (idxField)
6350 {
6351 /*
6352 * These fields consists of a "FULL" and a "HIGH" part which can be written to individually.
6353 */
6354 /* 64-bit Control fields. */
6355 case VMX_VMCS64_CTRL_IO_BITMAP_A_FULL:
6356 case VMX_VMCS64_CTRL_IO_BITMAP_B_FULL:
6357 case VMX_VMCS64_CTRL_MSR_BITMAP_FULL:
6358 case VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL:
6359 case VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL:
6360 case VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL:
6361 case VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL:
6362 case VMX_VMCS64_CTRL_TSC_OFFSET_FULL:
6363 case VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL:
6364 case VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL:
6365 case VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL:
6366 case VMX_VMCS64_CTRL_EPTP_FULL:
6367 case VMX_VMCS64_CTRL_EPTP_LIST_FULL:
6368 /* 64-bit Guest-state fields. */
6369 case VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL:
6370 case VMX_VMCS64_GUEST_DEBUGCTL_FULL:
6371 case VMX_VMCS64_GUEST_PAT_FULL:
6372 case VMX_VMCS64_GUEST_EFER_FULL:
6373 case VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL:
6374 case VMX_VMCS64_GUEST_PDPTE0_FULL:
6375 case VMX_VMCS64_GUEST_PDPTE1_FULL:
6376 case VMX_VMCS64_GUEST_PDPTE2_FULL:
6377 case VMX_VMCS64_GUEST_PDPTE3_FULL:
6378 /* 64-bit Host-state fields. */
6379 case VMX_VMCS64_HOST_PAT_FULL:
6380 case VMX_VMCS64_HOST_EFER_FULL:
6381 case VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL:
6382 {
6383 rc = VMXWriteVmcs32(idxField, RT_LO_U32(u64Val));
6384 rc |= VMXWriteVmcs32(idxField + 1, RT_HI_U32(u64Val));
6385 break;
6386 }
6387
6388 /*
6389 * These fields do not have high and low parts. Queue up the VMWRITE by using the VMCS write-cache (for 64-bit
6390 * values). When we switch the host to 64-bit mode for running 64-bit guests, these VMWRITEs get executed then.
6391 */
6392 /* Natural-width Guest-state fields. */
6393 case VMX_VMCS_GUEST_CR3:
6394 case VMX_VMCS_GUEST_ES_BASE:
6395 case VMX_VMCS_GUEST_CS_BASE:
6396 case VMX_VMCS_GUEST_SS_BASE:
6397 case VMX_VMCS_GUEST_DS_BASE:
6398 case VMX_VMCS_GUEST_FS_BASE:
6399 case VMX_VMCS_GUEST_GS_BASE:
6400 case VMX_VMCS_GUEST_LDTR_BASE:
6401 case VMX_VMCS_GUEST_TR_BASE:
6402 case VMX_VMCS_GUEST_GDTR_BASE:
6403 case VMX_VMCS_GUEST_IDTR_BASE:
6404 case VMX_VMCS_GUEST_RSP:
6405 case VMX_VMCS_GUEST_RIP:
6406 case VMX_VMCS_GUEST_SYSENTER_ESP:
6407 case VMX_VMCS_GUEST_SYSENTER_EIP:
6408 {
6409 if (!(RT_HI_U32(u64Val)))
6410 {
6411 /* If this field is 64-bit, VT-x will zero out the top bits. */
6412 rc = VMXWriteVmcs32(idxField, RT_LO_U32(u64Val));
6413 }
6414 else
6415 {
6416 /* Assert that only the 32->64 switcher case should ever come here. */
6417 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests);
6418 rc = VMXWriteCachedVmcsEx(pVCpu, idxField, u64Val);
6419 }
6420 break;
6421 }
6422
6423 default:
6424 {
6425 AssertMsgFailed(("VMXWriteVmcs64Ex: Invalid field %#RX32 (pVCpu=%p u64Val=%#RX64)\n", idxField, pVCpu, u64Val));
6426 pVCpu->hm.s.u32HMError = idxField;
6427 rc = VERR_INVALID_PARAMETER;
6428 break;
6429 }
6430 }
6431 AssertRCReturn(rc, rc);
6432 return rc;
6433}
6434
6435
6436/**
6437 * Queue up a VMWRITE by using the VMCS write cache.
6438 * This is only used on 32-bit hosts (except darwin) for 64-bit guests.
6439 *
6440 * @param pVCpu The cross context virtual CPU structure.
6441 * @param idxField The VMCS field encoding.
6442 * @param u64Val 16, 32 or 64-bit value.
6443 */
6444VMMR0DECL(int) VMXWriteCachedVmcsEx(PVMCPU pVCpu, uint32_t idxField, uint64_t u64Val)
6445{
6446 AssertPtr(pVCpu);
6447 PVMXVMCSCACHE pCache = &pVCpu->hm.s.vmx.VmcsCache;
6448
6449 AssertMsgReturn(pCache->Write.cValidEntries < VMX_VMCS_CACHE_MAX_ENTRY - 1,
6450 ("entries=%u\n", pCache->Write.cValidEntries), VERR_ACCESS_DENIED);
6451
6452 /* Make sure there are no duplicates. */
6453 for (uint32_t i = 0; i < pCache->Write.cValidEntries; i++)
6454 {
6455 if (pCache->Write.aField[i] == idxField)
6456 {
6457 pCache->Write.aFieldVal[i] = u64Val;
6458 return VINF_SUCCESS;
6459 }
6460 }
6461
6462 pCache->Write.aField[pCache->Write.cValidEntries] = idxField;
6463 pCache->Write.aFieldVal[pCache->Write.cValidEntries] = u64Val;
6464 pCache->Write.cValidEntries++;
6465 return VINF_SUCCESS;
6466}
6467#endif /* HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS) */
6468
6469
6470/**
6471 * Sets up the usage of TSC-offsetting and updates the VMCS.
6472 *
6473 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
6474 * VMX-preemption timer.
6475 *
6476 * @returns VBox status code.
6477 * @param pVCpu The cross context virtual CPU structure.
6478 * @param pVmxTransient The VMX-transient structure.
6479 *
6480 * @remarks No-long-jump zone!!!
6481 */
6482static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6483{
6484 bool fOffsettedTsc;
6485 bool fParavirtTsc;
6486 uint64_t uTscOffset;
6487 PVM pVM = pVCpu->CTX_SUFF(pVM);
6488 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6489
6490 if (pVM->hm.s.vmx.fUsePreemptTimer)
6491 {
6492 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc);
6493
6494 /* Make sure the returned values have sane upper and lower boundaries. */
6495 uint64_t u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
6496 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second */
6497 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
6498 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
6499
6500 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
6501 * preemption timers here. We probably need to clamp the preemption timer,
6502 * after converting the timer value to the host. */
6503 uint32_t cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
6504 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
6505 AssertRC(rc);
6506 }
6507 else
6508 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
6509
6510 if (fParavirtTsc)
6511 {
6512 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
6513 information before every VM-entry, hence disable it for performance sake. */
6514#if 0
6515 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
6516 AssertRC(rc);
6517#endif
6518 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
6519 }
6520
6521 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
6522 if ( fOffsettedTsc
6523 && RT_LIKELY(!pVCpu->hm.s.fDebugWantRdTscExit))
6524 {
6525 if (pVmxTransient->fIsNestedGuest)
6526 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
6527 if (pVmcsInfo->u64TscOffset != uTscOffset)
6528 {
6529 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, uTscOffset);
6530 AssertRC(rc);
6531 pVmcsInfo->u64TscOffset = uTscOffset;
6532 }
6533
6534 if (uProcCtls & VMX_PROC_CTLS_RDTSC_EXIT)
6535 {
6536 uProcCtls &= ~VMX_PROC_CTLS_RDTSC_EXIT;
6537 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
6538 AssertRC(rc);
6539 pVmcsInfo->u32ProcCtls = uProcCtls;
6540 }
6541 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
6542 }
6543 else
6544 {
6545 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
6546 if (!(uProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
6547 {
6548 uProcCtls |= VMX_PROC_CTLS_RDTSC_EXIT;
6549 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
6550 AssertRC(rc);
6551 pVmcsInfo->u32ProcCtls = uProcCtls;
6552 }
6553 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
6554 }
6555}
6556
6557
6558/**
6559 * Gets the IEM exception flags for the specified vector and IDT vectoring /
6560 * VM-exit interruption info type.
6561 *
6562 * @returns The IEM exception flags.
6563 * @param uVector The event vector.
6564 * @param uVmxEventType The VMX event type.
6565 *
6566 * @remarks This function currently only constructs flags required for
6567 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
6568 * and CR2 aspects of an exception are not included).
6569 */
6570static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
6571{
6572 uint32_t fIemXcptFlags;
6573 switch (uVmxEventType)
6574 {
6575 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
6576 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
6577 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
6578 break;
6579
6580 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
6581 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
6582 break;
6583
6584 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
6585 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
6586 break;
6587
6588 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
6589 {
6590 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
6591 if (uVector == X86_XCPT_BP)
6592 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
6593 else if (uVector == X86_XCPT_OF)
6594 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
6595 else
6596 {
6597 fIemXcptFlags = 0;
6598 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
6599 }
6600 break;
6601 }
6602
6603 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
6604 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
6605 break;
6606
6607 default:
6608 fIemXcptFlags = 0;
6609 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
6610 break;
6611 }
6612 return fIemXcptFlags;
6613}
6614
6615
6616/**
6617 * Sets an event as a pending event to be injected into the guest.
6618 *
6619 * @param pVCpu The cross context virtual CPU structure.
6620 * @param u32IntInfo The VM-entry interruption-information field.
6621 * @param cbInstr The VM-entry instruction length in bytes (for software
6622 * interrupts, exceptions and privileged software
6623 * exceptions).
6624 * @param u32ErrCode The VM-entry exception error code.
6625 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
6626 * page-fault.
6627 */
6628DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPU pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
6629 RTGCUINTPTR GCPtrFaultAddress)
6630{
6631 Assert(!pVCpu->hm.s.Event.fPending);
6632 pVCpu->hm.s.Event.fPending = true;
6633 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
6634 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
6635 pVCpu->hm.s.Event.cbInstr = cbInstr;
6636 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
6637}
6638
6639
6640/**
6641 * Sets an external interrupt as pending-for-injection into the VM.
6642 *
6643 * @param pVCpu The cross context virtual CPU structure.
6644 * @param u8Interrupt The external interrupt vector.
6645 */
6646DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPU pVCpu, uint8_t u8Interrupt)
6647{
6648 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
6649 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
6650 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6651 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6652 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6653}
6654
6655
6656/**
6657 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
6658 *
6659 * @param pVCpu The cross context virtual CPU structure.
6660 */
6661DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPU pVCpu)
6662{
6663 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
6664 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
6665 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6666 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6667 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6668}
6669
6670
6671/**
6672 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
6673 *
6674 * @param pVCpu The cross context virtual CPU structure.
6675 */
6676DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPU pVCpu)
6677{
6678 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
6679 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6680 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
6681 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6682 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6683}
6684
6685
6686/**
6687 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
6688 *
6689 * @param pVCpu The cross context virtual CPU structure.
6690 */
6691DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPU pVCpu)
6692{
6693 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
6694 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6695 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6696 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6697 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6698}
6699
6700
6701/**
6702 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
6703 *
6704 * @param pVCpu The cross context virtual CPU structure.
6705 */
6706DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPU pVCpu)
6707{
6708 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
6709 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6710 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6711 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6712 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6713}
6714
6715
6716#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
6717/**
6718 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
6719 *
6720 * @param pVCpu The cross context virtual CPU structure.
6721 * @param u32ErrCode The error code for the general-protection exception.
6722 */
6723DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPU pVCpu, uint32_t u32ErrCode)
6724{
6725 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
6726 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6727 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
6728 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6729 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
6730}
6731
6732
6733/**
6734 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
6735 *
6736 * @param pVCpu The cross context virtual CPU structure.
6737 * @param u32ErrCode The error code for the stack exception.
6738 */
6739DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPU pVCpu, uint32_t u32ErrCode)
6740{
6741 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
6742 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6743 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
6744 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6745 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
6746}
6747
6748
6749/**
6750 * Decodes the memory operand of an instruction that caused a VM-exit.
6751 *
6752 * The VM-exit qualification field provides the displacement field for memory
6753 * operand instructions, if any.
6754 *
6755 * @returns Strict VBox status code (i.e. informational status codes too).
6756 * @retval VINF_SUCCESS if the operand was successfully decoded.
6757 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
6758 * operand.
6759 * @param pVCpu The cross context virtual CPU structure.
6760 * @param uExitInstrInfo The VM-exit instruction information field.
6761 * @param enmMemAccess The memory operand's access type (read or write).
6762 * @param GCPtrDisp The instruction displacement field, if any. For
6763 * RIP-relative addressing pass RIP + displacement here.
6764 * @param pGCPtrMem Where to store the effective destination memory address.
6765 */
6766static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPU pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
6767 PRTGCPTR pGCPtrMem)
6768{
6769 Assert(pGCPtrMem);
6770 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
6771 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
6772 | CPUMCTX_EXTRN_CR0);
6773
6774 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
6775 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
6776 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
6777
6778 VMXEXITINSTRINFO ExitInstrInfo;
6779 ExitInstrInfo.u = uExitInstrInfo;
6780 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
6781 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
6782 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
6783 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
6784 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
6785 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
6786 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
6787 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
6788 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
6789
6790 /*
6791 * Validate instruction information.
6792 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
6793 */
6794 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
6795 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
6796 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
6797 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
6798 AssertLogRelMsgReturn(fIsMemOperand,
6799 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
6800
6801 /*
6802 * Compute the complete effective address.
6803 *
6804 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
6805 * See AMD spec. 4.5.2 "Segment Registers".
6806 */
6807 RTGCPTR GCPtrMem = GCPtrDisp;
6808 if (fBaseRegValid)
6809 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
6810 if (fIdxRegValid)
6811 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
6812
6813 RTGCPTR const GCPtrOff = GCPtrMem;
6814 if ( !fIsLongMode
6815 || iSegReg >= X86_SREG_FS)
6816 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
6817 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
6818
6819 /*
6820 * Validate effective address.
6821 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
6822 */
6823 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
6824 Assert(cbAccess > 0);
6825 if (fIsLongMode)
6826 {
6827 if (X86_IS_CANONICAL(GCPtrMem))
6828 {
6829 *pGCPtrMem = GCPtrMem;
6830 return VINF_SUCCESS;
6831 }
6832
6833 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
6834 * "Data Limit Checks in 64-bit Mode". */
6835 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
6836 hmR0VmxSetPendingXcptGP(pVCpu, 0);
6837 return VINF_HM_PENDING_XCPT;
6838 }
6839
6840 /*
6841 * This is a watered down version of iemMemApplySegment().
6842 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
6843 * and segment CPL/DPL checks are skipped.
6844 */
6845 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
6846 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
6847 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
6848
6849 /* Check if the segment is present and usable. */
6850 if ( pSel->Attr.n.u1Present
6851 && !pSel->Attr.n.u1Unusable)
6852 {
6853 Assert(pSel->Attr.n.u1DescType);
6854 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
6855 {
6856 /* Check permissions for the data segment. */
6857 if ( enmMemAccess == VMXMEMACCESS_WRITE
6858 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
6859 {
6860 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
6861 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
6862 return VINF_HM_PENDING_XCPT;
6863 }
6864
6865 /* Check limits if it's a normal data segment. */
6866 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
6867 {
6868 if ( GCPtrFirst32 > pSel->u32Limit
6869 || GCPtrLast32 > pSel->u32Limit)
6870 {
6871 Log4Func(("Data segment limit exceeded."
6872 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
6873 GCPtrLast32, pSel->u32Limit));
6874 if (iSegReg == X86_SREG_SS)
6875 hmR0VmxSetPendingXcptSS(pVCpu, 0);
6876 else
6877 hmR0VmxSetPendingXcptGP(pVCpu, 0);
6878 return VINF_HM_PENDING_XCPT;
6879 }
6880 }
6881 else
6882 {
6883 /* Check limits if it's an expand-down data segment.
6884 Note! The upper boundary is defined by the B bit, not the G bit! */
6885 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
6886 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
6887 {
6888 Log4Func(("Expand-down data segment limit exceeded."
6889 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
6890 GCPtrLast32, pSel->u32Limit));
6891 if (iSegReg == X86_SREG_SS)
6892 hmR0VmxSetPendingXcptSS(pVCpu, 0);
6893 else
6894 hmR0VmxSetPendingXcptGP(pVCpu, 0);
6895 return VINF_HM_PENDING_XCPT;
6896 }
6897 }
6898 }
6899 else
6900 {
6901 /* Check permissions for the code segment. */
6902 if ( enmMemAccess == VMXMEMACCESS_WRITE
6903 || ( enmMemAccess == VMXMEMACCESS_READ
6904 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
6905 {
6906 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
6907 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
6908 hmR0VmxSetPendingXcptGP(pVCpu, 0);
6909 return VINF_HM_PENDING_XCPT;
6910 }
6911
6912 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
6913 if ( GCPtrFirst32 > pSel->u32Limit
6914 || GCPtrLast32 > pSel->u32Limit)
6915 {
6916 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
6917 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
6918 if (iSegReg == X86_SREG_SS)
6919 hmR0VmxSetPendingXcptSS(pVCpu, 0);
6920 else
6921 hmR0VmxSetPendingXcptGP(pVCpu, 0);
6922 return VINF_HM_PENDING_XCPT;
6923 }
6924 }
6925 }
6926 else
6927 {
6928 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
6929 hmR0VmxSetPendingXcptGP(pVCpu, 0);
6930 return VINF_HM_PENDING_XCPT;
6931 }
6932
6933 *pGCPtrMem = GCPtrMem;
6934 return VINF_SUCCESS;
6935}
6936
6937
6938/**
6939 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
6940 * guest attempting to execute a VMX instruction.
6941 *
6942 * @returns Strict VBox status code (i.e. informational status codes too).
6943 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
6944 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
6945 *
6946 * @param pVCpu The cross context virtual CPU structure.
6947 * @param uExitReason The VM-exit reason.
6948 *
6949 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
6950 * @remarks No-long-jump zone!!!
6951 */
6952static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPU pVCpu, uint32_t uExitReason)
6953{
6954 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
6955 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
6956
6957 if ( CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx)
6958 || ( CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
6959 && !CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx)))
6960 {
6961 Log4Func(("In real/v86-mode or long-mode outside 64-bit code segment -> #UD\n"));
6962 hmR0VmxSetPendingXcptUD(pVCpu);
6963 return VINF_HM_PENDING_XCPT;
6964 }
6965
6966 if (uExitReason == VMX_EXIT_VMXON)
6967 {
6968 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
6969
6970 /*
6971 * We check CR4.VMXE because it is required to be always set while in VMX operation
6972 * by physical CPUs and our CR4 read shadow is only consulted when executing specific
6973 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
6974 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
6975 */
6976 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
6977 {
6978 Log4Func(("CR4.VMXE is not set -> #UD\n"));
6979 hmR0VmxSetPendingXcptUD(pVCpu);
6980 return VINF_HM_PENDING_XCPT;
6981 }
6982 }
6983 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
6984 {
6985 /*
6986 * The guest has not entered VMX operation but attempted to execute a VMX instruction
6987 * (other than VMXON), we need to raise a #UD.
6988 */
6989 Log4Func(("Not in VMX root mode -> #UD\n"));
6990 hmR0VmxSetPendingXcptUD(pVCpu);
6991 return VINF_HM_PENDING_XCPT;
6992 }
6993
6994 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
6995 {
6996 /*
6997 * The nested-guest attempted to execute a VMX instruction, cause a VM-exit and let
6998 * the guest hypervisor deal with it.
6999 */
7000 /** @todo NSTVMX: Trigger a VM-exit */
7001 }
7002
7003 /*
7004 * VMX instructions require CPL 0 except in VMX non-root mode where the VM-exit intercept
7005 * (above) takes preceedence over the CPL check.
7006 */
7007 if (CPUMGetGuestCPL(pVCpu) > 0)
7008 {
7009 Log4Func(("CPL > 0 -> #GP(0)\n"));
7010 hmR0VmxSetPendingXcptGP(pVCpu, 0);
7011 return VINF_HM_PENDING_XCPT;
7012 }
7013
7014 return VINF_SUCCESS;
7015}
7016#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
7017
7018
7019static void hmR0VmxFixUnusableSegRegAttr(PVMCPU pVCpu, PCPUMSELREG pSelReg, uint32_t idxSel)
7020{
7021 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
7022
7023 /*
7024 * If VT-x marks the segment as unusable, most other bits remain undefined:
7025 * - For CS the L, D and G bits have meaning.
7026 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
7027 * - For the remaining data segments no bits are defined.
7028 *
7029 * The present bit and the unusable bit has been observed to be set at the
7030 * same time (the selector was supposed to be invalid as we started executing
7031 * a V8086 interrupt in ring-0).
7032 *
7033 * What should be important for the rest of the VBox code, is that the P bit is
7034 * cleared. Some of the other VBox code recognizes the unusable bit, but
7035 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7036 * safe side here, we'll strip off P and other bits we don't care about. If
7037 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7038 *
7039 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7040 */
7041#ifdef VBOX_STRICT
7042 uint32_t const uAttr = pSelReg->Attr.u;
7043#endif
7044
7045 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7046 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7047 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7048
7049#ifdef VBOX_STRICT
7050 VMMRZCallRing3Disable(pVCpu);
7051 Log4Func(("Unusable %#x: sel=%#x attr=%#x -> %#x\n", idxSel, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7052# ifdef DEBUG_bird
7053 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7054 ("%#x: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7055 idxSel, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7056# endif
7057 VMMRZCallRing3Enable(pVCpu);
7058 NOREF(uAttr);
7059#endif
7060 RT_NOREF2(pVCpu, idxSel);
7061}
7062
7063
7064/**
7065 * Imports a guest segment register from the current VMCS into the guest-CPU
7066 * context.
7067 *
7068 * @returns VBox status code.
7069 * @param pVCpu The cross context virtual CPU structure.
7070 * @param iSegReg The segment register number (X86_SREG_XXX).
7071 *
7072 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7073 * do not log!
7074 */
7075static int hmR0VmxImportGuestSegReg(PVMCPU pVCpu, uint8_t iSegReg)
7076{
7077 Assert(iSegReg < X86_SREG_COUNT);
7078
7079 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
7080 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
7081 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
7082#ifdef VMX_USE_CACHED_VMCS_ACCESSES
7083 uint32_t const idxBase = g_aVmcsCacheSegBase[iSegReg];
7084#else
7085 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
7086#endif
7087 uint64_t u64Base;
7088 uint32_t u32Sel, u32Limit, u32Attr;
7089 int rc = VMXReadVmcs32(idxSel, &u32Sel);
7090 rc |= VMXReadVmcs32(idxLimit, &u32Limit);
7091 rc |= VMXReadVmcs32(idxAttr, &u32Attr);
7092 rc |= VMXReadVmcsGstNByIdxVal(idxBase, &u64Base);
7093 if (RT_SUCCESS(rc))
7094 {
7095 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7096 pSelReg->Sel = u32Sel;
7097 pSelReg->ValidSel = u32Sel;
7098 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7099 pSelReg->u32Limit = u32Limit;
7100 pSelReg->u64Base = u64Base;
7101 pSelReg->Attr.u = u32Attr;
7102 if (u32Attr & X86DESCATTR_UNUSABLE)
7103 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, idxSel);
7104 }
7105 return rc;
7106}
7107
7108
7109/**
7110 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7111 *
7112 * @returns VBox status code.
7113 * @param pVCpu The cross context virtual CPU structure.
7114 *
7115 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7116 * do not log!
7117 */
7118static int hmR0VmxImportGuestLdtr(PVMCPU pVCpu)
7119{
7120 uint64_t u64Base;
7121 uint32_t u32Sel, u32Limit, u32Attr;
7122 int rc = VMXReadVmcs32(VMX_VMCS16_GUEST_LDTR_SEL, &u32Sel);
7123 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit);
7124 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr);
7125 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_LDTR_BASE, &u64Base);
7126 if (RT_SUCCESS(rc))
7127 {
7128 pVCpu->cpum.GstCtx.ldtr.Sel = u32Sel;
7129 pVCpu->cpum.GstCtx.ldtr.ValidSel = u32Sel;
7130 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7131 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7132 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7133 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7134 if (u32Attr & X86DESCATTR_UNUSABLE)
7135 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, VMX_VMCS16_GUEST_LDTR_SEL);
7136 }
7137 return rc;
7138}
7139
7140
7141/**
7142 * Imports the guest TR from the current VMCS into the guest-CPU context.
7143 *
7144 * @returns VBox status code.
7145 * @param pVCpu The cross context virtual CPU structure.
7146 *
7147 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7148 * do not log!
7149 */
7150static int hmR0VmxImportGuestTr(PVMCPU pVCpu)
7151{
7152 uint32_t u32Sel, u32Limit, u32Attr;
7153 uint64_t u64Base;
7154 int rc = VMXReadVmcs32(VMX_VMCS16_GUEST_TR_SEL, &u32Sel);
7155 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit);
7156 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr);
7157 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_TR_BASE, &u64Base);
7158 AssertRCReturn(rc, rc);
7159
7160 pVCpu->cpum.GstCtx.tr.Sel = u32Sel;
7161 pVCpu->cpum.GstCtx.tr.ValidSel = u32Sel;
7162 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7163 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7164 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7165 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7166 /* TR is the only selector that can never be unusable. */
7167 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7168 return VINF_SUCCESS;
7169}
7170
7171
7172/**
7173 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7174 *
7175 * @returns VBox status code.
7176 * @param pVCpu The cross context virtual CPU structure.
7177 *
7178 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7179 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7180 * instead!!!
7181 */
7182static int hmR0VmxImportGuestRip(PVMCPU pVCpu)
7183{
7184 uint64_t u64Val;
7185 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7186 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7187 {
7188 int rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RIP, &u64Val);
7189 if (RT_SUCCESS(rc))
7190 {
7191 pCtx->rip = u64Val;
7192 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7193 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7194 }
7195 return rc;
7196 }
7197 return VINF_SUCCESS;
7198}
7199
7200
7201/**
7202 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7203 *
7204 * @returns VBox status code.
7205 * @param pVCpu The cross context virtual CPU structure.
7206 * @param pVmcsInfo The VMCS info. object.
7207 *
7208 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7209 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7210 * instead!!!
7211 */
7212static int hmR0VmxImportGuestRFlags(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
7213{
7214 uint32_t u32Val;
7215 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7216 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7217 {
7218 int rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &u32Val);
7219 if (RT_SUCCESS(rc))
7220 {
7221 pCtx->eflags.u32 = u32Val;
7222
7223 /* Restore eflags for real-on-v86-mode hack. */
7224 if (pVmcsInfo->RealMode.fRealOnV86Active)
7225 {
7226 pCtx->eflags.Bits.u1VM = 0;
7227 pCtx->eflags.Bits.u2IOPL = pVmcsInfo->RealMode.Eflags.Bits.u2IOPL;
7228 }
7229 }
7230 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7231 return rc;
7232 }
7233 return VINF_SUCCESS;
7234}
7235
7236
7237/**
7238 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7239 * context.
7240 *
7241 * @returns VBox status code.
7242 * @param pVCpu The cross context virtual CPU structure.
7243 * @param pVmcsInfo The VMCS info. object.
7244 *
7245 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7246 * do not log!
7247 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7248 * instead!!!
7249 */
7250static int hmR0VmxImportGuestIntrState(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
7251{
7252 uint32_t u32Val;
7253 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val);
7254 if (RT_SUCCESS(rc))
7255 {
7256 if (!u32Val)
7257 {
7258 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7259 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7260
7261 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
7262 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_BLOCK_NMIS);
7263 }
7264 else
7265 {
7266 /*
7267 * We must import RIP here to set our EM interrupt-inhibited state.
7268 * We also import RFLAGS as our code that evaluates pending interrupts
7269 * before VM-entry requires it.
7270 */
7271 rc = hmR0VmxImportGuestRip(pVCpu);
7272 rc |= hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7273 if (RT_SUCCESS(rc))
7274 {
7275 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
7276 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
7277 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7278 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7279
7280 if (u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI)
7281 {
7282 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
7283 VMCPU_FF_SET(pVCpu, VMCPU_FF_BLOCK_NMIS);
7284 }
7285 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
7286 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_BLOCK_NMIS);
7287 }
7288 }
7289 }
7290 return rc;
7291}
7292
7293
7294/**
7295 * Worker for VMXR0ImportStateOnDemand.
7296 *
7297 * @returns VBox status code.
7298 * @param pVCpu The cross context virtual CPU structure.
7299 * @param pVmcsInfo The VMCS info. object.
7300 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7301 */
7302static int hmR0VmxImportGuestState(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
7303{
7304#define VMXLOCAL_BREAK_RC(a_rc) \
7305 if (RT_SUCCESS(a_rc)) \
7306 { } \
7307 else \
7308 break
7309
7310 int rc = VINF_SUCCESS;
7311 PVM pVM = pVCpu->CTX_SUFF(pVM);
7312 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7313 uint64_t u64Val;
7314 uint32_t u32Val;
7315
7316 /*
7317 * Note! This is hack to workaround a mysterious BSOD observed with release builds
7318 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
7319 * neither are other host platforms.
7320 *
7321 * Committing this temporarily as it prevents BSOD.
7322 */
7323#ifdef RT_OS_WINDOWS
7324 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
7325 return VERR_HM_IPE_1;
7326#endif
7327
7328 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
7329
7330 /*
7331 * We disable interrupts to make the updating of the state and in particular
7332 * the fExtrn modification atomic wrt to preemption hooks.
7333 */
7334 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
7335
7336 fWhat &= pCtx->fExtrn;
7337 if (fWhat)
7338 {
7339 do
7340 {
7341 if (fWhat & CPUMCTX_EXTRN_RIP)
7342 {
7343 rc = hmR0VmxImportGuestRip(pVCpu);
7344 VMXLOCAL_BREAK_RC(rc);
7345 }
7346
7347 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
7348 {
7349 rc = hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7350 VMXLOCAL_BREAK_RC(rc);
7351 }
7352
7353 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
7354 {
7355 rc = hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
7356 VMXLOCAL_BREAK_RC(rc);
7357 }
7358
7359 if (fWhat & CPUMCTX_EXTRN_RSP)
7360 {
7361 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RSP, &u64Val);
7362 VMXLOCAL_BREAK_RC(rc);
7363 pCtx->rsp = u64Val;
7364 }
7365
7366 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
7367 {
7368 bool const fRealOnV86Active = pVmcsInfo->RealMode.fRealOnV86Active;
7369 if (fWhat & CPUMCTX_EXTRN_CS)
7370 {
7371 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
7372 rc |= hmR0VmxImportGuestRip(pVCpu);
7373 if (fRealOnV86Active)
7374 pCtx->cs.Attr.u = pVmcsInfo->RealMode.AttrCS.u;
7375 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
7376 }
7377 if (fWhat & CPUMCTX_EXTRN_SS)
7378 {
7379 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
7380 if (fRealOnV86Active)
7381 pCtx->ss.Attr.u = pVmcsInfo->RealMode.AttrSS.u;
7382 }
7383 if (fWhat & CPUMCTX_EXTRN_DS)
7384 {
7385 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
7386 if (fRealOnV86Active)
7387 pCtx->ds.Attr.u = pVmcsInfo->RealMode.AttrDS.u;
7388 }
7389 if (fWhat & CPUMCTX_EXTRN_ES)
7390 {
7391 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
7392 if (fRealOnV86Active)
7393 pCtx->es.Attr.u = pVmcsInfo->RealMode.AttrES.u;
7394 }
7395 if (fWhat & CPUMCTX_EXTRN_FS)
7396 {
7397 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
7398 if (fRealOnV86Active)
7399 pCtx->fs.Attr.u = pVmcsInfo->RealMode.AttrFS.u;
7400 }
7401 if (fWhat & CPUMCTX_EXTRN_GS)
7402 {
7403 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
7404 if (fRealOnV86Active)
7405 pCtx->gs.Attr.u = pVmcsInfo->RealMode.AttrGS.u;
7406 }
7407 VMXLOCAL_BREAK_RC(rc);
7408 }
7409
7410 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
7411 {
7412 if (fWhat & CPUMCTX_EXTRN_LDTR)
7413 rc |= hmR0VmxImportGuestLdtr(pVCpu);
7414
7415 if (fWhat & CPUMCTX_EXTRN_GDTR)
7416 {
7417 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
7418 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
7419 pCtx->gdtr.pGdt = u64Val;
7420 pCtx->gdtr.cbGdt = u32Val;
7421 }
7422
7423 /* Guest IDTR. */
7424 if (fWhat & CPUMCTX_EXTRN_IDTR)
7425 {
7426 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
7427 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
7428 pCtx->idtr.pIdt = u64Val;
7429 pCtx->idtr.cbIdt = u32Val;
7430 }
7431
7432 /* Guest TR. */
7433 if (fWhat & CPUMCTX_EXTRN_TR)
7434 {
7435 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
7436 don't need to import that one. */
7437 if (!pVmcsInfo->RealMode.fRealOnV86Active)
7438 rc |= hmR0VmxImportGuestTr(pVCpu);
7439 }
7440 VMXLOCAL_BREAK_RC(rc);
7441 }
7442
7443 if (fWhat & CPUMCTX_EXTRN_DR7)
7444 {
7445 if (!pVCpu->hm.s.fUsingHyperDR7)
7446 {
7447 /* Upper 32-bits are always zero. See Intel spec. 2.7.3 "Loading and Storing Debug Registers". */
7448 rc = VMXReadVmcs32(VMX_VMCS_GUEST_DR7, &u32Val);
7449 VMXLOCAL_BREAK_RC(rc);
7450 pCtx->dr[7] = u32Val;
7451 }
7452 }
7453
7454 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
7455 {
7456 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip);
7457 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp);
7458 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val);
7459 pCtx->SysEnter.cs = u32Val;
7460 VMXLOCAL_BREAK_RC(rc);
7461 }
7462
7463#if HC_ARCH_BITS == 64
7464 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
7465 {
7466 if ( pVM->hm.s.fAllow64BitGuests
7467 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7468 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
7469 }
7470
7471 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
7472 {
7473 if ( pVM->hm.s.fAllow64BitGuests
7474 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7475 {
7476 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
7477 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
7478 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
7479 }
7480 }
7481#endif
7482
7483 if ( (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
7484#if HC_ARCH_BITS == 32
7485 || (fWhat & (CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS))
7486#endif
7487 )
7488 {
7489 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
7490 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
7491 Assert(pMsrs);
7492 Assert(cMsrs <= VMX_MISC_MAX_MSRS(pVM->hm.s.vmx.Msrs.u64Misc));
7493 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
7494 for (uint32_t i = 0; i < cMsrs; i++)
7495 {
7496 uint32_t const idMsr = pMsrs[i].u32Msr;
7497 switch (idMsr)
7498 {
7499 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
7500 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
7501 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
7502#if HC_ARCH_BITS == 32
7503 case MSR_K8_LSTAR: pCtx->msrLSTAR = pMsrs[i].u64Value; break;
7504 case MSR_K6_STAR: pCtx->msrSTAR = pMsrs[i].u64Value; break;
7505 case MSR_K8_SF_MASK: pCtx->msrSFMASK = pMsrs[i].u64Value; break;
7506 case MSR_K8_KERNEL_GS_BASE: pCtx->msrKERNELGSBASE = pMsrs[i].u64Value; break;
7507#endif
7508 default:
7509 {
7510 pCtx->fExtrn = 0;
7511 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
7512 ASMSetFlags(fEFlags);
7513 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
7514 return VERR_HM_UNEXPECTED_LD_ST_MSR;
7515 }
7516 }
7517 }
7518 }
7519
7520 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
7521 {
7522 uint64_t u64Shadow;
7523 if (fWhat & CPUMCTX_EXTRN_CR0)
7524 {
7525 /** @todo r=ramshankar: We only read 32-bits here for legacy/convenience reasons,
7526 * remove when we drop 32-bit host w/ 64-bit host support, see
7527 * @bugref{9180#c39}. */
7528 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32Val);
7529#if HC_ARCH_BITS == 32
7530 uint32_t u32Shadow;
7531 rc |= VMXReadVmcs32(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u32Shadow);
7532 u64Shadow = u32Shadow;
7533#else
7534 rc |= VMXReadVmcs64(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow);
7535#endif
7536 VMXLOCAL_BREAK_RC(rc);
7537 u64Val = u32Val;
7538 u64Val = (u64Val & ~pVmcsInfo->u64Cr0Mask)
7539 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7540 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
7541 CPUMSetGuestCR0(pVCpu, u64Val);
7542 VMMRZCallRing3Enable(pVCpu);
7543 }
7544
7545 if (fWhat & CPUMCTX_EXTRN_CR4)
7546 {
7547 /** @todo r=ramshankar: We only read 32-bits here for legacy/convenience reasons,
7548 * remove when we drop 32-bit host w/ 64-bit host support, see
7549 * @bugref{9180#c39}. */
7550 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR4, &u32Val);
7551#if HC_ARCH_BITS == 32
7552 uint32_t u32Shadow;
7553 rc |= VMXReadVmcs32(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u32Shadow);
7554 u64Shadow = u32Shadow;
7555#else
7556 rc |= VMXReadVmcs64(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow);
7557#endif
7558 VMXLOCAL_BREAK_RC(rc);
7559 u64Val = u32Val;
7560 u64Val = (u64Val & ~pVmcsInfo->u64Cr4Mask)
7561 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7562 pCtx->cr4 = u64Val;
7563 }
7564
7565 if (fWhat & CPUMCTX_EXTRN_CR3)
7566 {
7567 /* CR0.PG bit changes are always intercepted, so it's up to date. */
7568 if ( pVM->hm.s.vmx.fUnrestrictedGuest
7569 || ( pVM->hm.s.fNestedPaging
7570 && CPUMIsGuestPagingEnabledEx(pCtx)))
7571 {
7572 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_CR3, &u64Val);
7573 VMXLOCAL_BREAK_RC(rc);
7574 if (pCtx->cr3 != u64Val)
7575 {
7576 pCtx->cr3 = u64Val;
7577 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
7578 }
7579
7580 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
7581 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
7582 if (CPUMIsGuestInPAEModeEx(pCtx))
7583 {
7584 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u);
7585 rc |= VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u);
7586 rc |= VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u);
7587 rc |= VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u);
7588 VMXLOCAL_BREAK_RC(rc);
7589 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
7590 }
7591 }
7592 }
7593 }
7594 } while (0);
7595
7596 if (RT_SUCCESS(rc))
7597 {
7598 /* Update fExtrn. */
7599 pCtx->fExtrn &= ~fWhat;
7600
7601 /* If everything has been imported, clear the HM keeper bit. */
7602 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
7603 {
7604 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
7605 Assert(!pCtx->fExtrn);
7606 }
7607 }
7608 }
7609 else
7610 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
7611
7612 ASMSetFlags(fEFlags);
7613
7614 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
7615
7616 if (RT_SUCCESS(rc))
7617 { /* likely */ }
7618 else
7619 return rc;
7620
7621 /*
7622 * Honor any pending CR3 updates.
7623 *
7624 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> hmR0VmxCallRing3Callback()
7625 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
7626 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
7627 *
7628 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
7629 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
7630 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
7631 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
7632 *
7633 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
7634 */
7635 if (VMMRZCallRing3IsEnabled(pVCpu))
7636 {
7637 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
7638 {
7639 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
7640 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
7641 }
7642
7643 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
7644 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
7645
7646 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
7647 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
7648 }
7649
7650 return VINF_SUCCESS;
7651#undef VMXLOCAL_BREAK_RC
7652}
7653
7654
7655/**
7656 * Saves the guest state from the VMCS into the guest-CPU context.
7657 *
7658 * @returns VBox status code.
7659 * @param pVCpu The cross context virtual CPU structure.
7660 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7661 */
7662VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPU pVCpu, uint64_t fWhat)
7663{
7664 PCVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7665 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
7666}
7667
7668
7669/**
7670 * Check per-VM and per-VCPU force flag actions that require us to go back to
7671 * ring-3 for one reason or another.
7672 *
7673 * @returns Strict VBox status code (i.e. informational status codes too)
7674 * @retval VINF_SUCCESS if we don't have any actions that require going back to
7675 * ring-3.
7676 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
7677 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
7678 * interrupts)
7679 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
7680 * all EMTs to be in ring-3.
7681 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
7682 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
7683 * to the EM loop.
7684 *
7685 * @param pVCpu The cross context virtual CPU structure.
7686 * @param fStepping Whether we are single-stepping the guest using the
7687 * hypervisor debugger.
7688 */
7689static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPU pVCpu, bool fStepping)
7690{
7691 Assert(VMMRZCallRing3IsEnabled(pVCpu));
7692
7693 /*
7694 * Update pending interrupts into the APIC's IRR.
7695 */
7696 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
7697 APICUpdatePendingInterrupts(pVCpu);
7698
7699 /*
7700 * Anything pending? Should be more likely than not if we're doing a good job.
7701 */
7702 PVM pVM = pVCpu->CTX_SUFF(pVM);
7703 if ( !fStepping
7704 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
7705 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
7706 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
7707 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
7708 return VINF_SUCCESS;
7709
7710 /* Pending PGM C3 sync. */
7711 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
7712 {
7713 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7714 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
7715 VBOXSTRICTRC rcStrict2 = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
7716 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
7717 if (rcStrict2 != VINF_SUCCESS)
7718 {
7719 AssertRC(VBOXSTRICTRC_VAL(rcStrict2));
7720 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict2)));
7721 return rcStrict2;
7722 }
7723 }
7724
7725 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
7726 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
7727 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
7728 {
7729 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
7730 int rc2 = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
7731 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc2));
7732 return rc2;
7733 }
7734
7735 /* Pending VM request packets, such as hardware interrupts. */
7736 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
7737 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
7738 {
7739 Log4Func(("Pending VM request forcing us back to ring-3\n"));
7740 return VINF_EM_PENDING_REQUEST;
7741 }
7742
7743 /* Pending PGM pool flushes. */
7744 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
7745 {
7746 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
7747 return VINF_PGM_POOL_FLUSH_PENDING;
7748 }
7749
7750 /* Pending DMA requests. */
7751 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
7752 {
7753 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
7754 return VINF_EM_RAW_TO_R3;
7755 }
7756
7757 return VINF_SUCCESS;
7758}
7759
7760
7761/**
7762 * Converts any TRPM trap into a pending HM event. This is typically used when
7763 * entering from ring-3 (not longjmp returns).
7764 *
7765 * @param pVCpu The cross context virtual CPU structure.
7766 */
7767static void hmR0VmxTrpmTrapToPendingEvent(PVMCPU pVCpu)
7768{
7769 Assert(TRPMHasTrap(pVCpu));
7770 Assert(!pVCpu->hm.s.Event.fPending);
7771
7772 uint8_t uVector;
7773 TRPMEVENT enmTrpmEvent;
7774 RTGCUINT uErrCode;
7775 RTGCUINTPTR GCPtrFaultAddress;
7776 uint8_t cbInstr;
7777
7778 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr);
7779 AssertRC(rc);
7780
7781 /* Refer Intel spec. 24.8.3 "VM-entry Controls for Event Injection" for the format of u32IntInfo. */
7782 uint32_t u32IntInfo = uVector | VMX_EXIT_INT_INFO_VALID;
7783 if (enmTrpmEvent == TRPM_TRAP)
7784 {
7785 /** @todo r=ramshankar: TRPM currently offers no way to determine a \#DB that was
7786 * generated using INT1 (ICEBP). */
7787 switch (uVector)
7788 {
7789 case X86_XCPT_NMI:
7790 u32IntInfo |= (VMX_EXIT_INT_INFO_TYPE_NMI << VMX_EXIT_INT_INFO_TYPE_SHIFT);
7791 break;
7792
7793 case X86_XCPT_BP:
7794 case X86_XCPT_OF:
7795 u32IntInfo |= (VMX_EXIT_INT_INFO_TYPE_SW_XCPT << VMX_EXIT_INT_INFO_TYPE_SHIFT);
7796 break;
7797
7798 case X86_XCPT_PF:
7799 case X86_XCPT_DF:
7800 case X86_XCPT_TS:
7801 case X86_XCPT_NP:
7802 case X86_XCPT_SS:
7803 case X86_XCPT_GP:
7804 case X86_XCPT_AC:
7805 u32IntInfo |= VMX_EXIT_INT_INFO_ERROR_CODE_VALID;
7806 RT_FALL_THRU();
7807 default:
7808 u32IntInfo |= (VMX_EXIT_INT_INFO_TYPE_HW_XCPT << VMX_EXIT_INT_INFO_TYPE_SHIFT);
7809 break;
7810 }
7811 }
7812 else if (enmTrpmEvent == TRPM_HARDWARE_INT)
7813 u32IntInfo |= (VMX_EXIT_INT_INFO_TYPE_EXT_INT << VMX_EXIT_INT_INFO_TYPE_SHIFT);
7814 else if (enmTrpmEvent == TRPM_SOFTWARE_INT)
7815 {
7816 switch (uVector)
7817 {
7818 case X86_XCPT_BP:
7819 case X86_XCPT_OF:
7820 u32IntInfo |= (VMX_EXIT_INT_INFO_TYPE_SW_XCPT << VMX_EXIT_INT_INFO_TYPE_SHIFT);
7821 break;
7822
7823 default:
7824 Assert(uVector == X86_XCPT_DB);
7825 u32IntInfo |= (VMX_EXIT_INT_INFO_TYPE_SW_INT << VMX_EXIT_INT_INFO_TYPE_SHIFT);
7826 break;
7827 }
7828 }
7829 else
7830 AssertMsgFailed(("Invalid TRPM event type %d\n", enmTrpmEvent));
7831
7832 rc = TRPMResetTrap(pVCpu);
7833 AssertRC(rc);
7834 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
7835 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
7836
7837 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
7838}
7839
7840
7841/**
7842 * Converts the pending HM event into a TRPM trap.
7843 *
7844 * @param pVCpu The cross context virtual CPU structure.
7845 */
7846static void hmR0VmxPendingEventToTrpmTrap(PVMCPU pVCpu)
7847{
7848 Assert(pVCpu->hm.s.Event.fPending);
7849
7850 uint32_t uVectorType = VMX_IDT_VECTORING_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
7851 uint32_t uVector = VMX_IDT_VECTORING_INFO_VECTOR(pVCpu->hm.s.Event.u64IntInfo);
7852 bool fErrorCodeValid = VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVCpu->hm.s.Event.u64IntInfo);
7853 uint32_t uErrorCode = pVCpu->hm.s.Event.u32ErrCode;
7854
7855 /* If a trap was already pending, we did something wrong! */
7856 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
7857
7858 /** @todo Use HMVmxEventToTrpmEventType() later. */
7859 TRPMEVENT enmTrapType;
7860 switch (uVectorType)
7861 {
7862 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
7863 enmTrapType = TRPM_HARDWARE_INT;
7864 break;
7865
7866 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
7867 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
7868 enmTrapType = TRPM_TRAP;
7869 break;
7870
7871 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT: /* #DB (INT1/ICEBP). */
7872 Assert(uVector == X86_XCPT_DB);
7873 enmTrapType = TRPM_SOFTWARE_INT;
7874 break;
7875
7876 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT: /* #BP (INT3) and #OF (INTO) */
7877 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
7878 enmTrapType = TRPM_SOFTWARE_INT;
7879 break;
7880
7881 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
7882 enmTrapType = TRPM_SOFTWARE_INT;
7883 break;
7884
7885 default:
7886 AssertMsgFailed(("Invalid trap type %#x\n", uVectorType));
7887 enmTrapType = TRPM_32BIT_HACK;
7888 break;
7889 }
7890
7891 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
7892
7893 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
7894 AssertRC(rc);
7895
7896 if (fErrorCodeValid)
7897 TRPMSetErrorCode(pVCpu, uErrorCode);
7898
7899 if ( uVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
7900 && uVector == X86_XCPT_PF)
7901 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
7902 else if (enmTrapType == TRPM_SOFTWARE_INT)
7903 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
7904
7905 /* We're now done converting the pending event. */
7906 pVCpu->hm.s.Event.fPending = false;
7907}
7908
7909
7910/**
7911 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
7912 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
7913 *
7914 * @param pVCpu The cross context virtual CPU structure.
7915 * @param pVmcsInfo The VMCS info. object.
7916 */
7917static void hmR0VmxSetIntWindowExitVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
7918{
7919 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
7920 {
7921 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
7922 {
7923 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
7924 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7925 AssertRC(rc);
7926 }
7927 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
7928}
7929
7930
7931/**
7932 * Clears the interrupt-window exiting control in the VMCS.
7933 *
7934 * @param pVmcsInfo The VMCS info. object.
7935 */
7936DECLINLINE(int) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
7937{
7938 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
7939 {
7940 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
7941 return VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7942 }
7943 return VINF_SUCCESS;
7944}
7945
7946
7947/**
7948 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
7949 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
7950 *
7951 * @param pVCpu The cross context virtual CPU structure.
7952 * @param pVmcsInfo The VMCS info. object.
7953 */
7954static void hmR0VmxSetNmiWindowExitVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
7955{
7956 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
7957 {
7958 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
7959 {
7960 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
7961 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7962 AssertRC(rc);
7963 Log4Func(("Setup NMI-window exiting\n"));
7964 }
7965 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
7966}
7967
7968
7969/**
7970 * Clears the NMI-window exiting control in the VMCS.
7971 *
7972 * @param pVmcsInfo The VMCS info. object.
7973 */
7974DECLINLINE(int) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
7975{
7976 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
7977 {
7978 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
7979 return VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7980 }
7981 return VINF_SUCCESS;
7982}
7983
7984
7985/**
7986 * Does the necessary state syncing before returning to ring-3 for any reason
7987 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
7988 *
7989 * @returns VBox status code.
7990 * @param pVCpu The cross context virtual CPU structure.
7991 * @param fImportState Whether to import the guest state from the VMCS back
7992 * to the guest-CPU context.
7993 *
7994 * @remarks No-long-jmp zone!!!
7995 */
7996static int hmR0VmxLeave(PVMCPU pVCpu, bool fImportState)
7997{
7998 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
7999 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8000
8001 RTCPUID idCpu = RTMpCpuId();
8002 Log4Func(("HostCpuId=%u\n", idCpu));
8003
8004 /*
8005 * !!! IMPORTANT !!!
8006 * If you modify code here, check whether hmR0VmxCallRing3Callback() needs to be updated too.
8007 */
8008
8009 /* Save the guest state if necessary. */
8010 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8011 if (fImportState)
8012 {
8013 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8014 AssertRCReturn(rc, rc);
8015 }
8016
8017 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
8018 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8019 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
8020
8021 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
8022#ifdef VBOX_STRICT
8023 if (CPUMIsHyperDebugStateActive(pVCpu))
8024 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
8025#endif
8026 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8027 Assert(!CPUMIsGuestDebugStateActive(pVCpu) && !CPUMIsGuestDebugStateActivePending(pVCpu));
8028 Assert(!CPUMIsHyperDebugStateActive(pVCpu) && !CPUMIsHyperDebugStateActivePending(pVCpu));
8029
8030#if HC_ARCH_BITS == 64
8031 /* Restore host-state bits that VT-x only restores partially. */
8032 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8033 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8034 {
8035 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags, idCpu));
8036 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8037 }
8038 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8039#endif
8040
8041 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8042 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8043 {
8044 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
8045 if (!fImportState)
8046 {
8047 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
8048 AssertRCReturn(rc, rc);
8049 }
8050 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8051 Assert(!pVCpu->hm.s.vmx.fLazyMsrs);
8052 }
8053 else
8054 pVCpu->hm.s.vmx.fLazyMsrs = 0;
8055
8056 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8057 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8058
8059 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
8060 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
8061 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
8062 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
8063 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
8064 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
8065 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
8066 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
8067 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8068
8069 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8070
8071 /** @todo This partially defeats the purpose of having preemption hooks.
8072 * The problem is, deregistering the hooks should be moved to a place that
8073 * lasts until the EMT is about to be destroyed not everytime while leaving HM
8074 * context.
8075 */
8076 int rc = hmR0VmxClearVmcs(pVmcsInfo);
8077 AssertRCReturn(rc, rc);
8078
8079 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
8080 NOREF(idCpu);
8081 return VINF_SUCCESS;
8082}
8083
8084
8085/**
8086 * Leaves the VT-x session.
8087 *
8088 * @returns VBox status code.
8089 * @param pVCpu The cross context virtual CPU structure.
8090 *
8091 * @remarks No-long-jmp zone!!!
8092 */
8093static int hmR0VmxLeaveSession(PVMCPU pVCpu)
8094{
8095 HM_DISABLE_PREEMPT(pVCpu);
8096 HMVMX_ASSERT_CPU_SAFE(pVCpu);
8097 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8098 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8099
8100 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
8101 and done this from the VMXR0ThreadCtxCallback(). */
8102 if (!pVCpu->hm.s.fLeaveDone)
8103 {
8104 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
8105 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
8106 pVCpu->hm.s.fLeaveDone = true;
8107 }
8108 Assert(!pVCpu->cpum.GstCtx.fExtrn);
8109
8110 /*
8111 * !!! IMPORTANT !!!
8112 * If you modify code here, make sure to check whether hmR0VmxCallRing3Callback() needs to be updated too.
8113 */
8114
8115 /* Deregister hook now that we've left HM context before re-enabling preemption. */
8116 /** @todo Deregistering here means we need to VMCLEAR always
8117 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
8118 * for calling VMMR0ThreadCtxHookDisable here! */
8119 VMMR0ThreadCtxHookDisable(pVCpu);
8120
8121 /* Leave HM context. This takes care of local init (term). */
8122 int rc = HMR0LeaveCpu(pVCpu);
8123
8124 HM_RESTORE_PREEMPT();
8125 return rc;
8126}
8127
8128
8129/**
8130 * Does the necessary state syncing before doing a longjmp to ring-3.
8131 *
8132 * @returns VBox status code.
8133 * @param pVCpu The cross context virtual CPU structure.
8134 *
8135 * @remarks No-long-jmp zone!!!
8136 */
8137DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPU pVCpu)
8138{
8139 return hmR0VmxLeaveSession(pVCpu);
8140}
8141
8142
8143/**
8144 * Take necessary actions before going back to ring-3.
8145 *
8146 * An action requires us to go back to ring-3. This function does the necessary
8147 * steps before we can safely return to ring-3. This is not the same as longjmps
8148 * to ring-3, this is voluntary and prepares the guest so it may continue
8149 * executing outside HM (recompiler/IEM).
8150 *
8151 * @returns VBox status code.
8152 * @param pVCpu The cross context virtual CPU structure.
8153 * @param rcExit The reason for exiting to ring-3. Can be
8154 * VINF_VMM_UNKNOWN_RING3_CALL.
8155 */
8156static int hmR0VmxExitToRing3(PVMCPU pVCpu, VBOXSTRICTRC rcExit)
8157{
8158 Assert(pVCpu);
8159 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8160
8161 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8162 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8163 {
8164 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8165 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8166 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
8167 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8168 }
8169
8170 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8171 VMMRZCallRing3Disable(pVCpu);
8172 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8173
8174 /*
8175 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8176 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8177 *
8178 * This is because execution may continue from ring-3 and we would need to inject
8179 * the event from there (hence place it back in TRPM).
8180 */
8181 if (pVCpu->hm.s.Event.fPending)
8182 {
8183 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8184 Assert(!pVCpu->hm.s.Event.fPending);
8185
8186 /* Clear the events from the VMCS. */
8187 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0);
8188 AssertRCReturn(rc, rc);
8189 }
8190#ifdef VBOX_STRICT
8191 else
8192 {
8193 /*
8194 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8195 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8196 * occasionally, see @bugref{9180#c42}.
8197 */
8198 uint32_t uEntryIntInfo;
8199 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8200 AssertRC(rc);
8201 Assert(!VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo));
8202 }
8203#endif
8204
8205 /*
8206 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8207 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8208 * (e.g. TPR below threshold).
8209 */
8210 int rc = hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8211 rc |= hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8212 AssertRCReturn(rc, rc);
8213
8214 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8215 and if we're injecting an event we should have a TRPM trap pending. */
8216 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8217#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8218 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8219#endif
8220
8221 /* Save guest state and restore host state bits. */
8222 rc = hmR0VmxLeaveSession(pVCpu);
8223 AssertRCReturn(rc, rc);
8224 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8225
8226 /* Thread-context hooks are unregistered at this point!!! */
8227
8228 /* Sync recompiler state. */
8229 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8230 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8231 | CPUM_CHANGED_LDTR
8232 | CPUM_CHANGED_GDTR
8233 | CPUM_CHANGED_IDTR
8234 | CPUM_CHANGED_TR
8235 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8236 if ( pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging
8237 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8238 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8239
8240 Assert(!pVCpu->hm.s.fClearTrapFlag);
8241
8242 /* Update the exit-to-ring 3 reason. */
8243 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8244
8245 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8246 if ( rcExit != VINF_EM_RAW_INTERRUPT
8247 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8248 {
8249 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8250 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8251 }
8252
8253 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8254
8255 /* We do -not- want any longjmp notifications after this! We must return to ring-3 ASAP. */
8256 VMMRZCallRing3RemoveNotification(pVCpu);
8257 VMMRZCallRing3Enable(pVCpu);
8258
8259 return rc;
8260}
8261
8262
8263/**
8264 * VMMRZCallRing3() callback wrapper which saves the guest state before we
8265 * longjump to ring-3 and possibly get preempted.
8266 *
8267 * @returns VBox status code.
8268 * @param pVCpu The cross context virtual CPU structure.
8269 * @param enmOperation The operation causing the ring-3 longjump.
8270 * @param pvUser User argument, currently unused, NULL.
8271 */
8272static DECLCALLBACK(int) hmR0VmxCallRing3Callback(PVMCPU pVCpu, VMMCALLRING3 enmOperation, void *pvUser)
8273{
8274 RT_NOREF(pvUser);
8275 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
8276 {
8277 /*
8278 * !!! IMPORTANT !!!
8279 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
8280 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
8281 */
8282 VMMRZCallRing3RemoveNotification(pVCpu);
8283 VMMRZCallRing3Disable(pVCpu);
8284 RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
8285 RTThreadPreemptDisable(&PreemptState);
8286
8287 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8288 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8289 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8290 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8291
8292#if HC_ARCH_BITS == 64
8293 /* Restore host-state bits that VT-x only restores partially. */
8294 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8295 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8296 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8297 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8298#endif
8299
8300 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8301 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8302 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8303
8304 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8305 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8306 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8307
8308 /* Clear the current VMCS data back to memory. */
8309 hmR0VmxClearVmcs(pVmcsInfo);
8310
8311 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
8312 VMMR0ThreadCtxHookDisable(pVCpu);
8313 HMR0LeaveCpu(pVCpu);
8314 RTThreadPreemptRestore(&PreemptState);
8315 return VINF_SUCCESS;
8316 }
8317
8318 Assert(pVCpu);
8319 Assert(pvUser);
8320 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8321 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8322
8323 VMMRZCallRing3Disable(pVCpu);
8324 Assert(VMMR0IsLogFlushDisabled(pVCpu));
8325
8326 Log4Func((" -> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
8327
8328 int rc = hmR0VmxLongJmpToRing3(pVCpu);
8329 AssertRCReturn(rc, rc);
8330
8331 VMMRZCallRing3Enable(pVCpu);
8332 return VINF_SUCCESS;
8333}
8334
8335
8336/**
8337 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
8338 * stack.
8339 *
8340 * @returns Strict VBox status code (i.e. informational status codes too).
8341 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
8342 * @param pVCpu The cross context virtual CPU structure.
8343 * @param uValue The value to push to the guest stack.
8344 */
8345static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPU pVCpu, uint16_t uValue)
8346{
8347 /*
8348 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
8349 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
8350 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
8351 */
8352 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8353 if (pCtx->sp == 1)
8354 return VINF_EM_RESET;
8355 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
8356 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
8357 AssertRC(rc);
8358 return rc;
8359}
8360
8361
8362/**
8363 * Injects an event into the guest upon VM-entry by updating the relevant fields
8364 * in the VM-entry area in the VMCS.
8365 *
8366 * @returns Strict VBox status code (i.e. informational status codes too).
8367 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
8368 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
8369 *
8370 * @param pVCpu The cross context virtual CPU structure.
8371 * @param pVmxTransient The VMX-transient structure.
8372 * @param pEvent The event being injected.
8373 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state.
8374 * This will be updated if necessary. This cannot not
8375 * be NULL.
8376 * @param fStepping Whether we're single-stepping guest execution and
8377 * should return VINF_EM_DBG_STEPPED if the event is
8378 * injected directly (registers modified by us, not by
8379 * hardware on VM-entry).
8380 */
8381static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
8382 uint32_t *pfIntrState)
8383{
8384 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
8385 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
8386 Assert(pfIntrState);
8387
8388 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8389 uint32_t u32IntInfo = pEvent->u64IntInfo;
8390 uint32_t const u32ErrCode = pEvent->u32ErrCode;
8391 uint32_t const cbInstr = pEvent->cbInstr;
8392 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
8393 uint32_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
8394 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
8395
8396#ifdef VBOX_STRICT
8397 /*
8398 * Validate the error-code-valid bit for hardware exceptions.
8399 * No error codes for exceptions in real-mode.
8400 *
8401 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8402 */
8403 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8404 && !CPUMIsGuestInRealModeEx(pCtx))
8405 {
8406 switch (uVector)
8407 {
8408 case X86_XCPT_PF:
8409 case X86_XCPT_DF:
8410 case X86_XCPT_TS:
8411 case X86_XCPT_NP:
8412 case X86_XCPT_SS:
8413 case X86_XCPT_GP:
8414 case X86_XCPT_AC:
8415 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
8416 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
8417 RT_FALL_THRU();
8418 default:
8419 break;
8420 }
8421 }
8422
8423 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
8424 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
8425 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8426#endif
8427
8428 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
8429
8430 /*
8431 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
8432 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
8433 * interrupt handler in the (real-mode) guest.
8434 *
8435 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
8436 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
8437 */
8438 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
8439 {
8440 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest)
8441 {
8442 /*
8443 * For CPUs with unrestricted guest execution enabled and with the guest
8444 * in real-mode, we must not set the deliver-error-code bit.
8445 *
8446 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
8447 */
8448 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
8449 }
8450 else
8451 {
8452 PVM pVM = pVCpu->CTX_SUFF(pVM);
8453 Assert(PDMVmmDevHeapIsEnabled(pVM));
8454 Assert(pVM->hm.s.vmx.pRealModeTSS);
8455 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
8456
8457 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
8458 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8459 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
8460 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
8461 AssertRCReturn(rc2, rc2);
8462
8463 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
8464 size_t const cbIdtEntry = sizeof(X86IDTR16);
8465 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
8466 {
8467 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
8468 if (uVector == X86_XCPT_DF)
8469 return VINF_EM_RESET;
8470
8471 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
8472 No error codes for exceptions in real-mode. */
8473 if (uVector == X86_XCPT_GP)
8474 {
8475 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
8476 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8477 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8478 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8479 HMEVENT EventXcptDf;
8480 RT_ZERO(EventXcptDf);
8481 EventXcptDf.u64IntInfo = uXcptDfInfo;
8482 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
8483 }
8484
8485 /*
8486 * If we're injecting an event with no valid IDT entry, inject a #GP.
8487 * No error codes for exceptions in real-mode.
8488 *
8489 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8490 */
8491 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
8492 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8493 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8494 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8495 HMEVENT EventXcptGp;
8496 RT_ZERO(EventXcptGp);
8497 EventXcptGp.u64IntInfo = uXcptGpInfo;
8498 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
8499 }
8500
8501 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
8502 uint16_t uGuestIp = pCtx->ip;
8503 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
8504 {
8505 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
8506 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
8507 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8508 }
8509 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
8510 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8511
8512 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
8513 X86IDTR16 IdtEntry;
8514 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
8515 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
8516 AssertRCReturn(rc2, rc2);
8517
8518 /* Construct the stack frame for the interrupt/exception handler. */
8519 VBOXSTRICTRC rcStrict;
8520 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
8521 if (rcStrict == VINF_SUCCESS)
8522 {
8523 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
8524 if (rcStrict == VINF_SUCCESS)
8525 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
8526 }
8527
8528 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
8529 if (rcStrict == VINF_SUCCESS)
8530 {
8531 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
8532 pCtx->rip = IdtEntry.offSel;
8533 pCtx->cs.Sel = IdtEntry.uSel;
8534 pCtx->cs.ValidSel = IdtEntry.uSel;
8535 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
8536 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
8537 && uVector == X86_XCPT_PF)
8538 pCtx->cr2 = GCPtrFault;
8539
8540 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
8541 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
8542 | HM_CHANGED_GUEST_RSP);
8543
8544 /*
8545 * If we delivered a hardware exception (other than an NMI) and if there was
8546 * block-by-STI in effect, we should clear it.
8547 */
8548 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
8549 {
8550 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
8551 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
8552 Log4Func(("Clearing inhibition due to STI\n"));
8553 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
8554 }
8555
8556 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
8557 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
8558
8559 /*
8560 * The event has been truly dispatched to the guest. Mark it as no longer pending so
8561 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
8562 */
8563 pVCpu->hm.s.Event.fPending = false;
8564
8565 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
8566 if (fStepping)
8567 rcStrict = VINF_EM_DBG_STEPPED;
8568 }
8569 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
8570 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
8571 return rcStrict;
8572 }
8573 }
8574
8575 /*
8576 * Validate.
8577 */
8578 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
8579 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
8580
8581 /*
8582 * Inject the event into the VMCS.
8583 */
8584 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
8585 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8586 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
8587 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
8588 AssertRCReturn(rc, rc);
8589
8590 /*
8591 * Update guest CR2 if this is a page-fault.
8592 */
8593 if ( VMX_ENTRY_INT_INFO_TYPE(u32IntInfo) == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8594 && uVector == X86_XCPT_PF)
8595 pCtx->cr2 = GCPtrFault;
8596
8597 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
8598 return VINF_SUCCESS;
8599}
8600
8601
8602/**
8603 * Evaluates the event to be delivered to the guest and sets it as the pending
8604 * event.
8605 *
8606 * @returns Strict VBox status code (i.e. informational status codes too).
8607 * @param pVCpu The cross context virtual CPU structure.
8608 * @param pVmxTransient The VMX-transient structure.
8609 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
8610 */
8611static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
8612{
8613 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8614 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8615
8616 /* Get the current interruptibility-state of the guest and then figure out what can be injected. */
8617 uint32_t const fIntrState = hmR0VmxGetGuestIntrState(pVCpu, pVmcsInfo);
8618 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
8619 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
8620 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
8621
8622 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_RFLAGS));
8623 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
8624 Assert(!fBlockSti || pCtx->eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
8625 Assert(!TRPMHasTrap(pVCpu));
8626 Assert(pfIntrState);
8627
8628 *pfIntrState = fIntrState;
8629
8630 /*
8631 * Toggling of interrupt force-flags here is safe since we update TRPM on premature exits
8632 * to ring-3 before executing guest code, see hmR0VmxExitToRing3(). We must NOT restore these force-flags.
8633 */
8634 /** @todo SMI. SMIs take priority over NMIs. */
8635 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI)) /* NMI. NMIs take priority over regular interrupts. */
8636 {
8637 /* On some CPUs block-by-STI also blocks NMIs. See Intel spec. 26.3.1.5 "Checks On Guest Non-Register State". */
8638 if ( !pVCpu->hm.s.Event.fPending
8639 && !fBlockNmi
8640 && !fBlockSti
8641 && !fBlockMovSS)
8642 {
8643#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8644 if ( pVmxTransient->fIsNestedGuest
8645 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_NMI_EXIT))
8646 return IEMExecVmxVmexitNmi(pVCpu);
8647#endif
8648 hmR0VmxSetPendingXcptNmi(pVCpu);
8649 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
8650 Log4Func(("Pending NMI\n"));
8651 }
8652 else
8653 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
8654 }
8655 /*
8656 * Check if the guest can receive external interrupts (PIC/APIC). Once PDMGetInterrupt() returns
8657 * a valid interrupt we -must- deliver the interrupt. We can no longer re-request it from the APIC.
8658 */
8659 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
8660 && !pVCpu->hm.s.fSingleInstruction)
8661 {
8662 Assert(!DBGFIsStepping(pVCpu));
8663 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
8664 AssertRCReturn(rc, rc);
8665 bool const fBlockInt = !(pCtx->eflags.u32 & X86_EFL_IF);
8666 if ( !pVCpu->hm.s.Event.fPending
8667 && !fBlockInt
8668 && !fBlockSti
8669 && !fBlockMovSS)
8670 {
8671#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8672 if ( pVmxTransient->fIsNestedGuest
8673 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT))
8674 {
8675 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0/* uVector */, true /* fIntPending */);
8676 if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
8677 return rcStrict;
8678 }
8679#endif
8680 uint8_t u8Interrupt;
8681 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
8682 if (RT_SUCCESS(rc))
8683 {
8684#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8685 if ( pVmxTransient->fIsNestedGuest
8686 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8687 && CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8688 {
8689 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
8690 if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
8691 return rcStrict;
8692 }
8693#endif
8694 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
8695 Log4Func(("Pending external interrupt vector %#x\n", u8Interrupt));
8696 }
8697 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
8698 {
8699 if ( !pVmxTransient->fIsNestedGuest
8700 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
8701 hmR0VmxApicSetTprThreshold(pVCpu, pVmcsInfo, u8Interrupt >> 4);
8702 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
8703
8704 /*
8705 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
8706 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
8707 * need to re-set this force-flag here.
8708 */
8709 }
8710 else
8711 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
8712 }
8713 else
8714 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
8715 }
8716
8717 return VINF_SUCCESS;
8718}
8719
8720
8721/**
8722 * Injects any pending events into the guest if the guest is in a state to
8723 * receive them.
8724 *
8725 * @returns Strict VBox status code (i.e. informational status codes too).
8726 * @param pVCpu The cross context virtual CPU structure.
8727 * @param pVmxTransient The VMX-transient structure.
8728 * @param fIntrState The VT-x guest-interruptibility state.
8729 * @param fStepping Whether we are single-stepping the guest using the
8730 * hypervisor debugger and should return
8731 * VINF_EM_DBG_STEPPED if the event was dispatched
8732 * directly.
8733 */
8734static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
8735{
8736 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8737 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8738
8739 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
8740 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
8741
8742 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
8743 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
8744 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
8745 Assert(!TRPMHasTrap(pVCpu));
8746
8747 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
8748 if (pVCpu->hm.s.Event.fPending)
8749 {
8750 /*
8751 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
8752 * pending even while injecting an event and in this case, we want a VM-exit as soon as
8753 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
8754 *
8755 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
8756 */
8757 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
8758#ifdef VBOX_STRICT
8759 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
8760 {
8761 bool const fBlockInt = !(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
8762 Assert(!fBlockInt);
8763 Assert(!fBlockSti);
8764 Assert(!fBlockMovSS);
8765 }
8766 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
8767 {
8768 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
8769 Assert(!fBlockSti);
8770 Assert(!fBlockMovSS);
8771 Assert(!fBlockNmi);
8772 }
8773#endif
8774 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
8775 uIntType));
8776
8777 /*
8778 * Inject the event and get any changes to the guest-interruptibility state.
8779 *
8780 * The guest-interruptibility state may need to be updated if we inject the event
8781 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
8782 */
8783 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
8784 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
8785
8786 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
8787 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
8788 else
8789 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
8790 }
8791
8792 /*
8793 * Update the guest-interruptibility state.
8794 *
8795 * This is required for the real-on-v86 software interrupt injection case above, as well as
8796 * updates to the guest state from ring-3 or IEM/REM.
8797 */
8798 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
8799 AssertRCReturn(rc, rc);
8800
8801 /*
8802 * There's no need to clear the VM-entry interruption-information field here if we're not
8803 * injecting anything. VT-x clears the valid bit on every VM-exit.
8804 *
8805 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
8806 */
8807
8808 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
8809 NOREF(fBlockMovSS); NOREF(fBlockSti);
8810 return rcStrict;
8811}
8812
8813
8814/**
8815 * Enters the VT-x session.
8816 *
8817 * @returns VBox status code.
8818 * @param pVCpu The cross context virtual CPU structure.
8819 */
8820VMMR0DECL(int) VMXR0Enter(PVMCPU pVCpu)
8821{
8822 AssertPtr(pVCpu);
8823 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
8824 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8825
8826 LogFlowFunc(("pVCpu=%p\n", pVCpu));
8827 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
8828 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
8829
8830#ifdef VBOX_STRICT
8831 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
8832 RTCCUINTREG uHostCR4 = ASMGetCR4();
8833 if (!(uHostCR4 & X86_CR4_VMXE))
8834 {
8835 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
8836 return VERR_VMX_X86_CR4_VMXE_CLEARED;
8837 }
8838#endif
8839
8840 /*
8841 * Load the appropriate VMCS as the current and active one.
8842 */
8843 PVMXVMCSINFO pVmcsInfo;
8844 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
8845 if (!fInNestedGuestMode)
8846 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
8847 else
8848 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
8849 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
8850 if (RT_SUCCESS(rc))
8851 {
8852 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
8853 pVCpu->hm.s.fLeaveDone = false;
8854 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
8855
8856 /*
8857 * Do the EMT scheduled L1D flush here if needed.
8858 */
8859 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
8860 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
8861 }
8862 return rc;
8863}
8864
8865
8866/**
8867 * The thread-context callback (only on platforms which support it).
8868 *
8869 * @param enmEvent The thread-context event.
8870 * @param pVCpu The cross context virtual CPU structure.
8871 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
8872 * @thread EMT(pVCpu)
8873 */
8874VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPU pVCpu, bool fGlobalInit)
8875{
8876 NOREF(fGlobalInit);
8877
8878 switch (enmEvent)
8879 {
8880 case RTTHREADCTXEVENT_OUT:
8881 {
8882 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8883 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
8884 VMCPU_ASSERT_EMT(pVCpu);
8885
8886 /* No longjmps (logger flushes, locks) in this fragile context. */
8887 VMMRZCallRing3Disable(pVCpu);
8888 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
8889
8890 /* Restore host-state (FPU, debug etc.) */
8891 if (!pVCpu->hm.s.fLeaveDone)
8892 {
8893 /*
8894 * Do -not- import the guest-state here as we might already be in the middle of importing
8895 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
8896 */
8897 hmR0VmxLeave(pVCpu, false /* fImportState */);
8898 pVCpu->hm.s.fLeaveDone = true;
8899 }
8900
8901 /* Leave HM context, takes care of local init (term). */
8902 int rc = HMR0LeaveCpu(pVCpu);
8903 AssertRC(rc);
8904
8905 /* Restore longjmp state. */
8906 VMMRZCallRing3Enable(pVCpu);
8907 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
8908 break;
8909 }
8910
8911 case RTTHREADCTXEVENT_IN:
8912 {
8913 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8914 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
8915 VMCPU_ASSERT_EMT(pVCpu);
8916
8917 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
8918 VMMRZCallRing3Disable(pVCpu);
8919 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
8920
8921 /* Initialize the bare minimum state required for HM. This takes care of
8922 initializing VT-x if necessary (onlined CPUs, local init etc.) */
8923 int rc = hmR0EnterCpu(pVCpu);
8924 AssertRC(rc);
8925 Assert( (pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
8926 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
8927
8928 /* Load the active VMCS as the current one. */
8929 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8930 rc = hmR0VmxLoadVmcs(pVmcsInfo);
8931 AssertRC(rc);
8932 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
8933 pVCpu->hm.s.fLeaveDone = false;
8934
8935 /* Do the EMT scheduled L1D flush if needed. */
8936 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
8937 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
8938
8939 /* Restore longjmp state. */
8940 VMMRZCallRing3Enable(pVCpu);
8941 break;
8942 }
8943
8944 default:
8945 break;
8946 }
8947}
8948
8949
8950/**
8951 * Exports the host state into the VMCS host-state area.
8952 * Sets up the VM-exit MSR-load area.
8953 *
8954 * The CPU state will be loaded from these fields on every successful VM-exit.
8955 *
8956 * @returns VBox status code.
8957 * @param pVCpu The cross context virtual CPU structure.
8958 *
8959 * @remarks No-long-jump zone!!!
8960 */
8961static int hmR0VmxExportHostState(PVMCPU pVCpu)
8962{
8963 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8964
8965 int rc = VINF_SUCCESS;
8966 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
8967 {
8968 rc = hmR0VmxExportHostControlRegs();
8969 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8970
8971 rc = hmR0VmxExportHostSegmentRegs(pVCpu);
8972 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8973
8974 rc = hmR0VmxExportHostMsrs(pVCpu);
8975 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8976
8977 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
8978 }
8979 return rc;
8980}
8981
8982
8983/**
8984 * Saves the host state in the VMCS host-state.
8985 *
8986 * @returns VBox status code.
8987 * @param pVCpu The cross context virtual CPU structure.
8988 *
8989 * @remarks No-long-jump zone!!!
8990 */
8991VMMR0DECL(int) VMXR0ExportHostState(PVMCPU pVCpu)
8992{
8993 AssertPtr(pVCpu);
8994 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8995
8996 /*
8997 * Export the host state here while entering HM context.
8998 * When thread-context hooks are used, we might get preempted and have to re-save the host
8999 * state but most of the time we won't be, so do it here before we disable interrupts.
9000 */
9001 return hmR0VmxExportHostState(pVCpu);
9002}
9003
9004
9005/**
9006 * Exports the guest state into the VMCS guest-state area.
9007 *
9008 * The will typically be done before VM-entry when the guest-CPU state and the
9009 * VMCS state may potentially be out of sync.
9010 *
9011 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
9012 * VM-entry controls.
9013 * Sets up the appropriate VMX non-root function to execute guest code based on
9014 * the guest CPU mode.
9015 *
9016 * @returns VBox strict status code.
9017 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9018 * without unrestricted guest execution and the VMMDev is not presently
9019 * mapped (e.g. EFI32).
9020 *
9021 * @param pVCpu The cross context virtual CPU structure.
9022 * @param pVmxTransient The VMX-transient structure.
9023 *
9024 * @remarks No-long-jump zone!!!
9025 */
9026static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9027{
9028 AssertPtr(pVCpu);
9029 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9030 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9031
9032 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9033
9034 /*
9035 * Determine real-on-v86 mode.
9036 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9037 */
9038 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9039 if ( pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
9040 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9041 pVmcsInfo->RealMode. fRealOnV86Active = false;
9042 else
9043 {
9044 Assert(!pVmxTransient->fIsNestedGuest);
9045 pVmcsInfo->RealMode.fRealOnV86Active = true;
9046 }
9047
9048 /*
9049 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9050 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9051 */
9052 /** @todo r=ramshankar: Move hmR0VmxSelectVMRunHandler inside
9053 * hmR0VmxExportGuestEntryExitCtls and do it conditionally. There shouldn't
9054 * be a need to evaluate this everytime since I'm pretty sure we intercept
9055 * all guest paging mode changes. */
9056 int rc = hmR0VmxSelectVMRunHandler(pVCpu, pVmxTransient);
9057 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9058
9059 rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9060 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9061
9062 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9063 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9064
9065 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9066 if (rcStrict == VINF_SUCCESS)
9067 { /* likely */ }
9068 else
9069 {
9070 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9071 return rcStrict;
9072 }
9073
9074 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9075 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9076
9077 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9078 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9079
9080 rc = hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9081 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9082
9083 rc = hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9084 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9085
9086 rc = hmR0VmxExportGuestRip(pVCpu);
9087 rc |= hmR0VmxExportGuestRsp(pVCpu);
9088 rc |= hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9089 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9090
9091 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9092 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9093 | HM_CHANGED_GUEST_CR2
9094 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9095 | HM_CHANGED_GUEST_X87
9096 | HM_CHANGED_GUEST_SSE_AVX
9097 | HM_CHANGED_GUEST_OTHER_XSAVE
9098 | HM_CHANGED_GUEST_XCRx
9099 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9100 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9101 | HM_CHANGED_GUEST_TSC_AUX
9102 | HM_CHANGED_GUEST_OTHER_MSRS
9103 | HM_CHANGED_GUEST_HWVIRT /* More accurate PLE handling someday? */
9104 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9105
9106 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9107 return rc;
9108}
9109
9110
9111/**
9112 * Exports the state shared between the host and guest into the VMCS.
9113 *
9114 * @param pVCpu The cross context virtual CPU structure.
9115 * @param pVmxTransient The VMX-transient structure.
9116 *
9117 * @remarks No-long-jump zone!!!
9118 */
9119static void hmR0VmxExportSharedState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9120{
9121 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9122 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9123
9124 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9125 {
9126 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9127 AssertRC(rc);
9128 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9129
9130 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9131 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9132 {
9133 rc = hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9134 AssertRC(rc);
9135 }
9136 }
9137
9138 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9139 {
9140 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9141 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9142 }
9143
9144 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9145 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9146}
9147
9148
9149/**
9150 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9151 *
9152 * @returns Strict VBox status code (i.e. informational status codes too).
9153 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9154 * without unrestricted guest execution and the VMMDev is not presently
9155 * mapped (e.g. EFI32).
9156 *
9157 * @param pVCpu The cross context virtual CPU structure.
9158 * @param pVmxTransient The VMX-transient structure.
9159 *
9160 * @remarks No-long-jump zone!!!
9161 */
9162static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9163{
9164 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9165 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9166 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9167
9168#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9169 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9170#endif
9171
9172 /*
9173 * For many exits it's only RIP that changes and hence try to export it first
9174 * without going through a lot of change flag checks.
9175 */
9176 VBOXSTRICTRC rcStrict;
9177 uint64_t fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9178 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
9179 if ((fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)) == HM_CHANGED_GUEST_RIP)
9180 {
9181 rcStrict = hmR0VmxExportGuestRip(pVCpu);
9182 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9183 { /* likely */}
9184 else
9185 AssertMsgFailedReturn(("Failed to export guest RIP! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)), rcStrict);
9186 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9187 }
9188 else if (fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9189 {
9190 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9191 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9192 { /* likely */}
9193 else
9194 {
9195 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9196 VBOXSTRICTRC_VAL(rcStrict)));
9197 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9198 return rcStrict;
9199 }
9200 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9201 }
9202 else
9203 rcStrict = VINF_SUCCESS;
9204
9205#ifdef VBOX_STRICT
9206 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9207 fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9208 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
9209 AssertMsg(!(fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)),
9210 ("fCtxChanged=%#RX64\n", fCtxChanged));
9211#endif
9212 return rcStrict;
9213}
9214
9215
9216/**
9217 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9218 * and update error record fields accordingly.
9219 *
9220 * @return VMX_IGS_* return codes.
9221 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9222 * wrong with the guest state.
9223 *
9224 * @param pVCpu The cross context virtual CPU structure.
9225 * @param pVmcsInfo The VMCS info. object.
9226 *
9227 * @remarks This function assumes our cache of the VMCS controls
9228 * are valid, i.e. hmR0VmxCheckVmcsCtls() succeeded.
9229 */
9230static uint32_t hmR0VmxCheckGuestState(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
9231{
9232#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9233#define HMVMX_CHECK_BREAK(expr, err) if (!(expr)) { \
9234 uError = (err); \
9235 break; \
9236 } else do { } while (0)
9237
9238 int rc;
9239 PVM pVM = pVCpu->CTX_SUFF(pVM);
9240 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9241 uint32_t uError = VMX_IGS_ERROR;
9242 uint32_t u32Val;
9243 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuest;
9244
9245 do
9246 {
9247 /*
9248 * CR0.
9249 */
9250 uint32_t fSetCr0 = (uint32_t)(pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9251 uint32_t const fZapCr0 = (uint32_t)(pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9252 /* Exceptions for unrestricted guest execution for fixed CR0 bits (PE, PG).
9253 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
9254 if (fUnrestrictedGuest)
9255 fSetCr0 &= ~(X86_CR0_PE | X86_CR0_PG);
9256
9257 uint32_t u32GuestCr0;
9258 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32GuestCr0);
9259 AssertRCBreak(rc);
9260 HMVMX_CHECK_BREAK((u32GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
9261 HMVMX_CHECK_BREAK(!(u32GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
9262 if ( !fUnrestrictedGuest
9263 && (u32GuestCr0 & X86_CR0_PG)
9264 && !(u32GuestCr0 & X86_CR0_PE))
9265 {
9266 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
9267 }
9268
9269 /*
9270 * CR4.
9271 */
9272 uint64_t const fSetCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9273 uint64_t const fZapCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9274
9275 uint32_t u32GuestCr4;
9276 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR4, &u32GuestCr4);
9277 AssertRCBreak(rc);
9278 HMVMX_CHECK_BREAK((u32GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
9279 HMVMX_CHECK_BREAK(!(u32GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
9280
9281 /*
9282 * IA32_DEBUGCTL MSR.
9283 */
9284 uint64_t u64Val;
9285 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
9286 AssertRCBreak(rc);
9287 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9288 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
9289 {
9290 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
9291 }
9292 uint64_t u64DebugCtlMsr = u64Val;
9293
9294#ifdef VBOX_STRICT
9295 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
9296 AssertRCBreak(rc);
9297 Assert(u32Val == pVmcsInfo->u32EntryCtls);
9298#endif
9299 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
9300
9301 /*
9302 * RIP and RFLAGS.
9303 */
9304 uint32_t u32Eflags;
9305#if HC_ARCH_BITS == 64
9306 rc = VMXReadVmcs64(VMX_VMCS_GUEST_RIP, &u64Val);
9307 AssertRCBreak(rc);
9308 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
9309 if ( !fLongModeGuest
9310 || !pCtx->cs.Attr.n.u1Long)
9311 {
9312 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
9313 }
9314 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
9315 * must be identical if the "IA-32e mode guest" VM-entry
9316 * control is 1 and CS.L is 1. No check applies if the
9317 * CPU supports 64 linear-address bits. */
9318
9319 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
9320 rc = VMXReadVmcs64(VMX_VMCS_GUEST_RFLAGS, &u64Val);
9321 AssertRCBreak(rc);
9322 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
9323 VMX_IGS_RFLAGS_RESERVED);
9324 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
9325 u32Eflags = u64Val;
9326#else
9327 rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &u32Eflags);
9328 AssertRCBreak(rc);
9329 HMVMX_CHECK_BREAK(!(u32Eflags & 0xffc08028), VMX_IGS_RFLAGS_RESERVED); /* Bit 31:22, Bit 15, 5, 3 MBZ. */
9330 HMVMX_CHECK_BREAK((u32Eflags & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
9331#endif
9332
9333 if ( fLongModeGuest
9334 || ( fUnrestrictedGuest
9335 && !(u32GuestCr0 & X86_CR0_PE)))
9336 {
9337 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
9338 }
9339
9340 uint32_t u32EntryInfo;
9341 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
9342 AssertRCBreak(rc);
9343 if ( VMX_ENTRY_INT_INFO_IS_VALID(u32EntryInfo)
9344 && VMX_ENTRY_INT_INFO_TYPE(u32EntryInfo) == VMX_EXIT_INT_INFO_TYPE_EXT_INT)
9345 {
9346 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
9347 }
9348
9349 /*
9350 * 64-bit checks.
9351 */
9352#if HC_ARCH_BITS == 64
9353 if (fLongModeGuest)
9354 {
9355 HMVMX_CHECK_BREAK(u32GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
9356 HMVMX_CHECK_BREAK(u32GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
9357 }
9358
9359 if ( !fLongModeGuest
9360 && (u32GuestCr4 & X86_CR4_PCIDE))
9361 {
9362 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
9363 }
9364
9365 /** @todo CR3 field must be such that bits 63:52 and bits in the range
9366 * 51:32 beyond the processor's physical-address width are 0. */
9367
9368 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9369 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
9370 {
9371 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
9372 }
9373
9374 rc = VMXReadVmcs64(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
9375 AssertRCBreak(rc);
9376 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
9377
9378 rc = VMXReadVmcs64(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
9379 AssertRCBreak(rc);
9380 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
9381#endif
9382
9383 /*
9384 * PERF_GLOBAL MSR.
9385 */
9386 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
9387 {
9388 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
9389 AssertRCBreak(rc);
9390 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
9391 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
9392 }
9393
9394 /*
9395 * PAT MSR.
9396 */
9397 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
9398 {
9399 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
9400 AssertRCBreak(rc);
9401 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
9402 for (unsigned i = 0; i < 8; i++)
9403 {
9404 uint8_t u8Val = (u64Val & 0xff);
9405 if ( u8Val != 0 /* UC */
9406 && u8Val != 1 /* WC */
9407 && u8Val != 4 /* WT */
9408 && u8Val != 5 /* WP */
9409 && u8Val != 6 /* WB */
9410 && u8Val != 7 /* UC- */)
9411 {
9412 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
9413 }
9414 u64Val >>= 8;
9415 }
9416 }
9417
9418 /*
9419 * EFER MSR.
9420 */
9421 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
9422 {
9423 Assert(pVM->hm.s.vmx.fSupportsVmcsEfer);
9424 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
9425 AssertRCBreak(rc);
9426 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
9427 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
9428 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
9429 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
9430 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
9431 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
9432 * iemVmxVmentryCheckGuestState(). */
9433 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9434 || !(u32GuestCr0 & X86_CR0_PG)
9435 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
9436 VMX_IGS_EFER_LMA_LME_MISMATCH);
9437 }
9438
9439 /*
9440 * Segment registers.
9441 */
9442 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9443 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
9444 if (!(u32Eflags & X86_EFL_VM))
9445 {
9446 /* CS */
9447 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
9448 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
9449 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
9450 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
9451 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9452 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
9453 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9454 /* CS cannot be loaded with NULL in protected mode. */
9455 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
9456 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
9457 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
9458 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
9459 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
9460 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
9461 else if (pVM->hm.s.vmx.fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
9462 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
9463 else
9464 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
9465
9466 /* SS */
9467 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9468 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
9469 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
9470 if ( !(pCtx->cr0 & X86_CR0_PE)
9471 || pCtx->cs.Attr.n.u4Type == 3)
9472 {
9473 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
9474 }
9475 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
9476 {
9477 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
9478 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
9479 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
9480 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
9481 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
9482 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9483 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
9484 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9485 }
9486
9487 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
9488 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
9489 {
9490 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
9491 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
9492 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9493 || pCtx->ds.Attr.n.u4Type > 11
9494 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9495 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
9496 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
9497 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
9498 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9499 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
9500 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9501 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9502 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
9503 }
9504 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
9505 {
9506 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
9507 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
9508 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9509 || pCtx->es.Attr.n.u4Type > 11
9510 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9511 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
9512 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
9513 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
9514 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9515 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
9516 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9517 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9518 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
9519 }
9520 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
9521 {
9522 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
9523 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
9524 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9525 || pCtx->fs.Attr.n.u4Type > 11
9526 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
9527 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
9528 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
9529 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
9530 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9531 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
9532 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9533 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9534 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
9535 }
9536 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
9537 {
9538 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
9539 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
9540 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9541 || pCtx->gs.Attr.n.u4Type > 11
9542 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
9543 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
9544 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
9545 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
9546 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9547 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
9548 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9549 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9550 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
9551 }
9552 /* 64-bit capable CPUs. */
9553#if HC_ARCH_BITS == 64
9554 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9555 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9556 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9557 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9558 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9559 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9560 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9561 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9562 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9563 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9564 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9565#endif
9566 }
9567 else
9568 {
9569 /* V86 mode checks. */
9570 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
9571 if (pVmcsInfo->RealMode.fRealOnV86Active)
9572 {
9573 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
9574 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
9575 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
9576 }
9577 else
9578 {
9579 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
9580 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
9581 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
9582 }
9583
9584 /* CS */
9585 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
9586 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
9587 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
9588 /* SS */
9589 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
9590 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
9591 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
9592 /* DS */
9593 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
9594 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
9595 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
9596 /* ES */
9597 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
9598 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
9599 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
9600 /* FS */
9601 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
9602 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
9603 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
9604 /* GS */
9605 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
9606 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
9607 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
9608 /* 64-bit capable CPUs. */
9609#if HC_ARCH_BITS == 64
9610 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9611 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9612 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9613 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9614 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9615 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9616 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9617 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9618 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9619 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9620 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9621#endif
9622 }
9623
9624 /*
9625 * TR.
9626 */
9627 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
9628 /* 64-bit capable CPUs. */
9629#if HC_ARCH_BITS == 64
9630 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
9631#endif
9632 if (fLongModeGuest)
9633 {
9634 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
9635 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
9636 }
9637 else
9638 {
9639 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
9640 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
9641 VMX_IGS_TR_ATTR_TYPE_INVALID);
9642 }
9643 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
9644 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
9645 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
9646 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
9647 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9648 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
9649 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9650 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
9651
9652 /*
9653 * GDTR and IDTR.
9654 */
9655#if HC_ARCH_BITS == 64
9656 rc = VMXReadVmcs64(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
9657 AssertRCBreak(rc);
9658 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
9659
9660 rc = VMXReadVmcs64(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
9661 AssertRCBreak(rc);
9662 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
9663#endif
9664
9665 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
9666 AssertRCBreak(rc);
9667 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9668
9669 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
9670 AssertRCBreak(rc);
9671 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9672
9673 /*
9674 * Guest Non-Register State.
9675 */
9676 /* Activity State. */
9677 uint32_t u32ActivityState;
9678 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
9679 AssertRCBreak(rc);
9680 HMVMX_CHECK_BREAK( !u32ActivityState
9681 || (u32ActivityState & RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
9682 VMX_IGS_ACTIVITY_STATE_INVALID);
9683 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
9684 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
9685 uint32_t u32IntrState;
9686 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
9687 AssertRCBreak(rc);
9688 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
9689 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9690 {
9691 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
9692 }
9693
9694 /** @todo Activity state and injecting interrupts. Left as a todo since we
9695 * currently don't use activity states but ACTIVE. */
9696
9697 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9698 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
9699
9700 /* Guest interruptibility-state. */
9701 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
9702 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
9703 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9704 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
9705 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
9706 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9707 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
9708 if (VMX_ENTRY_INT_INFO_IS_VALID(u32EntryInfo))
9709 {
9710 if (VMX_ENTRY_INT_INFO_TYPE(u32EntryInfo) == VMX_EXIT_INT_INFO_TYPE_EXT_INT)
9711 {
9712 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9713 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9714 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
9715 }
9716 else if (VMX_ENTRY_INT_INFO_TYPE(u32EntryInfo) == VMX_EXIT_INT_INFO_TYPE_NMI)
9717 {
9718 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9719 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
9720 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9721 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
9722 }
9723 }
9724 /** @todo Assumes the processor is not in SMM. */
9725 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9726 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
9727 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9728 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9729 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
9730 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
9731 && VMX_ENTRY_INT_INFO_IS_VALID(u32EntryInfo)
9732 && VMX_ENTRY_INT_INFO_TYPE(u32EntryInfo) == VMX_EXIT_INT_INFO_TYPE_NMI)
9733 {
9734 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI),
9735 VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
9736 }
9737
9738 /* Pending debug exceptions. */
9739#if HC_ARCH_BITS == 64
9740 rc = VMXReadVmcs64(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
9741 AssertRCBreak(rc);
9742 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
9743 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
9744 u32Val = u64Val; /* For pending debug exceptions checks below. */
9745#else
9746 rc = VMXReadVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u32Val);
9747 AssertRCBreak(rc);
9748 /* Bits 31:15, Bit 13, Bits 11:4 MBZ. */
9749 HMVMX_CHECK_BREAK(!(u32Val & 0xffffaff0), VMX_IGS_PENDING_DEBUG_RESERVED);
9750#endif
9751
9752 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9753 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
9754 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
9755 {
9756 if ( (u32Eflags & X86_EFL_TF)
9757 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
9758 {
9759 /* Bit 14 is PendingDebug.BS. */
9760 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
9761 }
9762 if ( !(u32Eflags & X86_EFL_TF)
9763 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
9764 {
9765 /* Bit 14 is PendingDebug.BS. */
9766 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
9767 }
9768 }
9769
9770 /* VMCS link pointer. */
9771 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
9772 AssertRCBreak(rc);
9773 if (u64Val != UINT64_C(0xffffffffffffffff))
9774 {
9775 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
9776 /** @todo Bits beyond the processor's physical-address width MBZ. */
9777 /** @todo 32-bit located in memory referenced by value of this field (as a
9778 * physical address) must contain the processor's VMCS revision ID. */
9779 /** @todo SMM checks. */
9780 }
9781
9782 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
9783 * not using nested paging? */
9784 if ( pVM->hm.s.fNestedPaging
9785 && !fLongModeGuest
9786 && CPUMIsGuestInPAEModeEx(pCtx))
9787 {
9788 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
9789 AssertRCBreak(rc);
9790 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9791
9792 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
9793 AssertRCBreak(rc);
9794 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9795
9796 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
9797 AssertRCBreak(rc);
9798 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9799
9800 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
9801 AssertRCBreak(rc);
9802 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9803 }
9804
9805 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
9806 if (uError == VMX_IGS_ERROR)
9807 uError = VMX_IGS_REASON_NOT_FOUND;
9808 } while (0);
9809
9810 pVCpu->hm.s.u32HMError = uError;
9811 return uError;
9812
9813#undef HMVMX_ERROR_BREAK
9814#undef HMVMX_CHECK_BREAK
9815}
9816
9817
9818/**
9819 * Setup the APIC-access page for virtualizing APIC access.
9820 *
9821 * This can cause a longjumps to R3 due to the acquisition of the PGM lock, hence
9822 * this not done as part of exporting guest state, see @bugref{8721}.
9823 *
9824 * @returns VBox status code.
9825 * @param pVCpu The cross context virtual CPU structure.
9826 */
9827static int hmR0VmxMapHCApicAccessPage(PVMCPU pVCpu)
9828{
9829 PVM pVM = pVCpu->CTX_SUFF(pVM);
9830 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
9831
9832 Assert(PDMHasApic(pVM));
9833 Assert(u64MsrApicBase);
9834
9835 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
9836 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
9837
9838 /* Unalias any existing mapping. */
9839 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
9840 AssertRCReturn(rc, rc);
9841
9842 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
9843 Assert(pVM->hm.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
9844 rc = IOMMMIOMapMMIOHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hm.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
9845 AssertRCReturn(rc, rc);
9846
9847 /* Update the per-VCPU cache of the APIC base MSR. */
9848 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
9849 return VINF_SUCCESS;
9850}
9851
9852
9853#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9854/**
9855 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
9856 * nested-guest using hardware-assisted VMX.
9857 *
9858 * @param pVCpu The cross context virtual CPU structure.
9859 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
9860 * @param pVmcsInfoGst The guest VMCS info. object.
9861 */
9862static void hmR0VmxMergeMsrBitmapNested(PCVMCPU pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
9863{
9864 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
9865 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
9866 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
9867 Assert(pu64MsrBitmapNstGst);
9868 Assert(pu64MsrBitmapGst);
9869 Assert(pu64MsrBitmap);
9870
9871 /*
9872 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
9873 * MSR that is intercepted by the guest is also intercepted while executing the
9874 * nested-guest using hardware-assisted VMX.
9875 */
9876 uint32_t const cbFrag = sizeof(uint64_t);
9877 uint32_t const cFrags = X86_PAGE_4K_SIZE / cbFrag;
9878 for (uint32_t i = 0; i <= cFrags; i++)
9879 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
9880}
9881
9882
9883/**
9884 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
9885 * hardware-assisted VMX execution of the nested-guest.
9886 *
9887 * For a guest, we don't modify these controls once we set up the VMCS.
9888 *
9889 * For nested-guests since the guest hypervisor provides these controls on every
9890 * nested-guest VM-entry and could potentially change them everytime we need to
9891 * merge them before every nested-guest VM-entry.
9892 *
9893 * @returns VBox status code.
9894 * @param pVCpu The cross context virtual CPU structure.
9895 */
9896static int hmR0VmxMergeVmcsNested(PVMCPU pVCpu)
9897{
9898 PVM pVM = pVCpu->CTX_SUFF(pVM);
9899 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
9900 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
9901 Assert(pVmcsNstGst);
9902
9903 /*
9904 * Merge the controls with the requirements of the guest VMCS.
9905 *
9906 * We do not need to validate the nested-guest VMX features specified in the
9907 * nested-guest VMCS with the features supported by the physical CPU as it's
9908 * already done by the VMLAUNCH/VMRESUME instruction emulation.
9909 *
9910 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the
9911 * guest are derived from the VMX features supported by the physical CPU.
9912 */
9913
9914 /* Pin-based VM-execution controls. */
9915 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
9916
9917 /* Processor-based VM-execution controls. */
9918 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
9919 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
9920 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
9921 | VMX_PROC_CTLS_USE_TPR_SHADOW
9922 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
9923
9924 /* Secondary processor-based VM-execution controls. */
9925 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
9926 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
9927 | VMX_PROC_CTLS2_INVPCID
9928 | VMX_PROC_CTLS2_RDTSCP
9929 | VMX_PROC_CTLS2_XSAVES_XRSTORS
9930 | VMX_PROC_CTLS2_APIC_REG_VIRT
9931 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
9932 | VMX_PROC_CTLS2_VMFUNC));
9933
9934 /*
9935 * VM-entry controls:
9936 * These controls contains state that depends on the nested-guest state (primarily
9937 * EFER MSR) and is thus not constant through VMLAUNCH/VMRESUME and the nested-guest
9938 * VM-exit. Although the nested-hypervisor cannot change it, we need to in order to
9939 * properly continue executing the nested-guest if the EFER MSR changes but does not
9940 * cause a nested-guest VM-exits.
9941 *
9942 * VM-exit controls:
9943 * These controls specify the host state on return. We cannot use the controls from
9944 * the nested-hypervisor state as is as it would contain the guest state rather than
9945 * the host state. Since the host state is subject to change (e.g. preemption, trips
9946 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
9947 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
9948 *
9949 * VM-entry MSR-load:
9950 * The guest MSRs from the VM-entry MSR-load area are already loaded into the
9951 * guest-CPU context by the VMLAUNCH/VMRESUME instruction emulation.
9952 *
9953 * VM-exit MSR-store:
9954 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU
9955 * context back into the VM-exit MSR-store area.
9956 *
9957 * VM-exit MSR-load areas:
9958 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence,
9959 * we can entirely ignore what the nested-hypervisor wants to load here.
9960 */
9961
9962 /*
9963 * Exception bitmap.
9964 *
9965 * We could remove #UD from the guest bitmap and merge it with the nested-guest
9966 * bitmap here (and avoid doing anything while exporting nested-guest state), but to
9967 * keep the code more flexible if intercepting exceptions become more dynamic in
9968 * the future we do it as part of exporting the nested-guest state.
9969 */
9970 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
9971
9972 /*
9973 * CR0/CR4 guest/host mask.
9974 *
9975 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest
9976 * must cause VM-exits, so we need to merge them here.
9977 */
9978 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
9979 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
9980
9981 /*
9982 * Page-fault error-code mask and match.
9983 *
9984 * Although we require unrestricted guest execution (and thereby nested-paging) for
9985 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
9986 * normally intercept #PFs, it might intercept them for debugging purposes.
9987 *
9988 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF
9989 * filters. If the outer guest is intercepting #PFs we must intercept all #PFs.
9990 */
9991 uint32_t u32XcptPFMask;
9992 uint32_t u32XcptPFMatch;
9993 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
9994 {
9995 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
9996 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
9997 }
9998 else
9999 {
10000 u32XcptPFMask = 0;
10001 u32XcptPFMatch = 0;
10002 }
10003
10004 /*
10005 * Pause-Loop exiting.
10006 */
10007 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10008 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10009
10010 /*
10011 * I/O Bitmap.
10012 *
10013 * We do not use the I/O bitmap that may be provided by the guest hypervisor as we
10014 * always intercept all I/O port accesses.
10015 */
10016 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10017
10018 /*
10019 * APIC-access page.
10020 *
10021 * The APIC-access page address has already been initialized while setting up the
10022 * nested-guest VMCS. In theory, even if the guest-physical address is invalid, it
10023 * should not be on any consequence to the host or to the guest for that matter, but
10024 * we only accept valid addresses verified by the VMLAUNCH/VMRESUME instruction
10025 * emulation to keep it simple.
10026 */
10027
10028 /*
10029 * Virtual-APIC page and TPR threshold.
10030 *
10031 * We shall use the host-physical address of the virtual-APIC page in guest memory directly.
10032 * For this reason, we can access the virtual-APIC page of the nested-guest only using
10033 * PGM physical handlers as we must not assume a kernel virtual-address mapping exists and
10034 * requesting PGM for a mapping could be expensive/resource intensive (PGM mapping cache).
10035 */
10036 RTHCPHYS HCPhysVirtApic = NIL_RTHCPHYS;
10037 uint32_t const u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10038 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10039 {
10040 int rc = PGMPhysGCPhys2HCPhys(pVM, pVmcsNstGst->u64AddrVirtApic.u, &HCPhysVirtApic);
10041
10042 /*
10043 * If the guest hypervisor has loaded crap into the virtual-APIC page field
10044 * we would fail to obtain a valid host-physical address for its guest-physical
10045 * address.
10046 *
10047 * We currently do not support this scenario. Maybe in the future if there is a
10048 * pressing need we can explore making this particular set of conditions work.
10049 * Right now we just cause a VM-entry failure.
10050 *
10051 * This has already been checked by VMLAUNCH/VMRESUME instruction emulation,
10052 * so should not really failure at the moment.
10053 */
10054 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
10055 }
10056 else
10057 {
10058 /*
10059 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10060 * used by the guest hypervisor. Preventing MMIO accesses to the physical APIC will
10061 * be taken care of by EPT/shadow paging.
10062 */
10063 if (pVM->hm.s.fAllow64BitGuests)
10064 {
10065 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10066 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10067 }
10068 }
10069
10070 /*
10071 * Validate basic assumptions.
10072 */
10073 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
10074 Assert(pVM->hm.s.vmx.fAllowUnrestricted);
10075 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10076 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10077
10078 /*
10079 * Commit it to the nested-guest VMCS.
10080 */
10081 int rc = VINF_SUCCESS;
10082 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10083 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10084 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10085 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10086 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10087 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10088 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10089 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10090 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10091 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10092 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10093 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10094 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10095 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10096 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10097 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10098 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10099 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10100 {
10101 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10102 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10103 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10104 }
10105 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10106 {
10107 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10108 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
10109 }
10110 AssertRCReturn(rc, rc);
10111
10112 /*
10113 * Update the nested-guest VMCS cache.
10114 */
10115 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10116 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10117 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10118 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10119 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10120 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10121 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10122 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10123 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10124
10125 /*
10126 * MSR bitmap.
10127 *
10128 * The MSR bitmap address has already been initialized while setting up the
10129 * nested-guest VMCS, here we need to merge the MSR bitmaps.
10130 */
10131 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10132 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10133
10134 return VINF_SUCCESS;
10135}
10136#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10137
10138
10139/**
10140 * Does the preparations before executing guest code in VT-x.
10141 *
10142 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10143 * recompiler/IEM. We must be cautious what we do here regarding committing
10144 * guest-state information into the VMCS assuming we assuredly execute the
10145 * guest in VT-x mode.
10146 *
10147 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10148 * the common-state (TRPM/forceflags), we must undo those changes so that the
10149 * recompiler/IEM can (and should) use them when it resumes guest execution.
10150 * Otherwise such operations must be done when we can no longer exit to ring-3.
10151 *
10152 * @returns Strict VBox status code (i.e. informational status codes too).
10153 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10154 * have been disabled.
10155 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10156 * double-fault into the guest.
10157 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10158 * dispatched directly.
10159 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10160 *
10161 * @param pVCpu The cross context virtual CPU structure.
10162 * @param pVmxTransient The VMX-transient structure.
10163 * @param fStepping Whether we are single-stepping the guest in the
10164 * hypervisor debugger. Makes us ignore some of the reasons
10165 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
10166 * if event dispatching took place.
10167 */
10168static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
10169{
10170 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10171
10172#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
10173 if (pVmxTransient->fIsNestedGuest)
10174 {
10175 RT_NOREF2(pVCpu, fStepping);
10176 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
10177 return VINF_EM_RESCHEDULE_REM;
10178 }
10179#endif
10180
10181#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
10182 PGMRZDynMapFlushAutoSet(pVCpu);
10183#endif
10184
10185 /*
10186 * Check and process force flag actions, some of which might require us to go back to ring-3.
10187 */
10188 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, fStepping);
10189 if (rcStrict == VINF_SUCCESS)
10190 { /* FFs don't get set all the time. */ }
10191 else
10192 return rcStrict;
10193
10194#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10195 /*
10196 * Switch to the nested-guest VMCS as we may have transitioned into executing
10197 * the nested-guest without leaving ring-0. Otherwise, if we came from ring-3
10198 * we would load the nested-guest VMCS while entering the VMX ring-0 session.
10199 *
10200 * We do this as late as possible to minimize (though not completely remove)
10201 * clearing/loading VMCS again due to premature trips to ring-3 above.
10202 */
10203 if (pVmxTransient->fIsNestedGuest)
10204 {
10205 if (!pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
10206 {
10207 /*
10208 * Ensure we have synced everything from the guest VMCS and also flag that
10209 * that we need to export the full (nested) guest-CPU context to the
10210 * nested-guest VMCS.
10211 */
10212 HMVMX_CPUMCTX_ASSERT(pVCpu, HMVMX_CPUMCTX_EXTRN_ALL);
10213 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_HOST_CONTEXT | HM_CHANGED_ALL_GUEST);
10214
10215 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
10216 int rc = hmR0VmxSwitchVmcs(&pVCpu->hm.s.vmx.VmcsInfo, &pVCpu->hm.s.vmx.VmcsInfoNstGst);
10217 if (RT_LIKELY(rc == VINF_SUCCESS))
10218 {
10219 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = true;
10220 ASMSetFlags(fEFlags);
10221 pVmxTransient->pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
10222
10223 /*
10224 * We use a different VM-exit MSR-store area for the nested-guest. Hence,
10225 * flag that we need to update the host MSR values there. Even if we decide
10226 * in the future to share the VM-exit MSR-store area page with the guest,
10227 * if its content differs, we would have to update the host MSRs anyway.
10228 */
10229 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
10230 Assert(!pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer); /** @todo NSTVMX: Paranoia remove later. */
10231 }
10232 else
10233 {
10234 ASMSetFlags(fEFlags);
10235 return rc;
10236 }
10237 }
10238
10239 /*
10240 * Merge guest VMCS controls with the nested-guest VMCS controls.
10241 *
10242 * Even if we have not executed the guest prior to this (e.g. when resuming
10243 * from a saved state), we should be okay with merging controls as we
10244 * initialize the guest VMCS controls as part of VM setup phase.
10245 */
10246 if (!pVCpu->hm.s.vmx.fMergedNstGstCtls)
10247 {
10248 int rc = hmR0VmxMergeVmcsNested(pVCpu);
10249 AssertRCReturn(rc, rc);
10250 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
10251 }
10252 }
10253#endif
10254
10255 /*
10256 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
10257 * We look at the guest VMCS control here as we always set it when supported by
10258 * the physical CPU. Looking at the nested-guest control here would not be
10259 * possible because they are not merged yet.
10260 */
10261 PVM pVM = pVCpu->CTX_SUFF(pVM);
10262 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10263 Assert(pVmcsInfo);
10264 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
10265 && (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10266 && PDMHasApic(pVM))
10267 {
10268 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
10269 AssertRCReturn(rc, rc);
10270 }
10271
10272 /*
10273 * Evaluate events to be injected into the guest.
10274 *
10275 * Events in TRPM can be injected without inspecting the guest state.
10276 * If any new events (interrupts/NMI) are pending currently, we try to set up the
10277 * guest to cause a VM-exit the next time they are ready to receive the event.
10278 */
10279 if (TRPMHasTrap(pVCpu))
10280 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
10281
10282 uint32_t fIntrState;
10283 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
10284
10285#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10286 /*
10287 * While evaluating pending events if something failed (unlikely) or if we were
10288 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
10289 */
10290 if ( rcStrict != VINF_SUCCESS
10291 || ( pVmxTransient->fIsNestedGuest
10292 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)))
10293 return rcStrict;
10294#endif
10295
10296 /*
10297 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
10298 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
10299 * also result in triple-faulting the VM.
10300 *
10301 * The above does not apply when executing a nested-guest (since unrestricted guest execution
10302 * is a requirement) regardless doing it avoid duplicating code elsewhere.
10303 */
10304 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
10305 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10306 { /* likely */ }
10307 else
10308 {
10309 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
10310 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
10311 return rcStrict;
10312 }
10313
10314 /*
10315 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
10316 * import CR3 themselves. We will need to update them here, as even as late as the above
10317 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
10318 * the below force flags to be set.
10319 */
10320 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
10321 {
10322 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
10323 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
10324 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
10325 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
10326 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10327 }
10328 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
10329 {
10330 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
10331 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10332 }
10333
10334#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10335 /* Paranoia. */
10336 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10337#endif
10338
10339 /*
10340 * No longjmps to ring-3 from this point on!!!
10341 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
10342 * This also disables flushing of the R0-logger instance (if any).
10343 */
10344 VMMRZCallRing3Disable(pVCpu);
10345
10346 /*
10347 * Export the guest state bits.
10348 *
10349 * We cannot perform longjmps while loading the guest state because we do not preserve the
10350 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
10351 * CPU migration.
10352 *
10353 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
10354 * registers. Hence, loading of the guest state needs to be done -after- injection of events.
10355 */
10356 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
10357 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10358 { /* likely */ }
10359 else
10360 {
10361 VMMRZCallRing3Enable(pVCpu);
10362 return rcStrict;
10363 }
10364
10365 /*
10366 * We disable interrupts so that we don't miss any interrupts that would flag preemption
10367 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
10368 * preemption disabled for a while. Since this is purely to aid the
10369 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
10370 * disable interrupt on NT.
10371 *
10372 * We need to check for force-flags that could've possible been altered since we last
10373 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
10374 * see @bugref{6398}).
10375 *
10376 * We also check a couple of other force-flags as a last opportunity to get the EMT back
10377 * to ring-3 before executing guest code.
10378 */
10379 pVmxTransient->fEFlags = ASMIntDisableFlags();
10380
10381 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
10382 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
10383 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
10384 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
10385 {
10386 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
10387 {
10388 pVCpu->hm.s.Event.fPending = false;
10389
10390 /*
10391 * We've injected any pending events. This is really the point of no return (to ring-3).
10392 *
10393 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
10394 * returns from this function, so don't enable them here.
10395 */
10396 return VINF_SUCCESS;
10397 }
10398
10399 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
10400 rcStrict = VINF_EM_RAW_INTERRUPT;
10401 }
10402 else
10403 {
10404 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
10405 rcStrict = VINF_EM_RAW_TO_R3;
10406 }
10407
10408 ASMSetFlags(pVmxTransient->fEFlags);
10409 VMMRZCallRing3Enable(pVCpu);
10410
10411 return rcStrict;
10412}
10413
10414
10415/**
10416 * Final preparations before executing guest code using hardware-assisted VMX.
10417 *
10418 * We can no longer get preempted to a different host CPU and there are no returns
10419 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
10420 * failures), this function is not intended to fail sans unrecoverable hardware
10421 * errors.
10422 *
10423 * @param pVCpu The cross context virtual CPU structure.
10424 * @param pVmxTransient The VMX-transient structure.
10425 *
10426 * @remarks Called with preemption disabled.
10427 * @remarks No-long-jump zone!!!
10428 */
10429static void hmR0VmxPreRunGuestCommitted(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
10430{
10431 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10432 Assert(VMMR0IsLogFlushDisabled(pVCpu));
10433 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
10434 Assert(!pVCpu->hm.s.Event.fPending);
10435
10436 /*
10437 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
10438 */
10439 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10440 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
10441
10442 PVM pVM = pVCpu->CTX_SUFF(pVM);
10443 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10444
10445 if (!CPUMIsGuestFPUStateActive(pVCpu))
10446 {
10447 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10448 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
10449 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
10450 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10451 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
10452 }
10453
10454 /*
10455 * Re-save the host state bits as we may've been preempted (only happens when
10456 * thread-context hooks are used or when the VM start function changes).
10457 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
10458 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
10459 * see @bugref{8432}.
10460 *
10461 * This may also happen when switching to/from a nested-guest VMCS without leaving
10462 * ring-0.
10463 */
10464 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
10465 {
10466 int rc = hmR0VmxExportHostState(pVCpu);
10467 AssertRC(rc);
10468 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreemptExportHostState);
10469 }
10470 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
10471
10472 /*
10473 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
10474 */
10475 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
10476 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
10477 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
10478
10479 /*
10480 * Store status of the shared guest/host debug state at the time of VM-entry.
10481 */
10482#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
10483 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
10484 {
10485 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActivePending(pVCpu);
10486 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActivePending(pVCpu);
10487 }
10488 else
10489#endif
10490 {
10491 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
10492 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
10493 }
10494
10495 /*
10496 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
10497 * more than one conditional check. The post-run side of our code shall determine
10498 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
10499 */
10500 if (pVmcsInfo->pbVirtApic)
10501 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
10502
10503 /*
10504 * Update the host MSRs values in the VM-exit MSR-load area.
10505 */
10506 if (!pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs)
10507 {
10508 if (pVmcsInfo->cExitMsrLoad > 0)
10509 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
10510 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = true;
10511 }
10512
10513 /*
10514 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
10515 * VMX-preemption timer based on the next virtual sync clock deadline.
10516 */
10517 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
10518 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
10519 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
10520 || idCurrentCpu != pVCpu->hm.s.idLastCpu)
10521 {
10522 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
10523 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
10524 }
10525
10526 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
10527 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
10528 Assert(idCurrentCpu == pVCpu->hm.s.idLastCpu);
10529 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Update the error reporting info. with the current host CPU. */
10530
10531 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
10532
10533 TMNotifyStartOfExecution(pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
10534 as we're about to start executing the guest . */
10535
10536 /*
10537 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
10538 *
10539 * This is done this late as updating the TSC offsetting/preemption timer above
10540 * figures out if we can skip intercepting RDTSCP by calculating the number of
10541 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
10542 */
10543 if (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
10544 {
10545 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
10546 {
10547 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
10548 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
10549 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
10550 AssertRC(rc);
10551 }
10552 else
10553 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
10554 }
10555
10556#ifdef VBOX_STRICT
10557 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo);
10558 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo);
10559 AssertRC(hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo));
10560#endif
10561
10562#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
10563 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
10564 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs. */
10565 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
10566 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
10567 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
10568#endif
10569}
10570
10571
10572/**
10573 * First C routine invoked after running guest code using hardware-assisted VMX.
10574 *
10575 * @param pVCpu The cross context virtual CPU structure.
10576 * @param pVmxTransient The VMX-transient structure.
10577 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
10578 *
10579 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
10580 *
10581 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
10582 * unconditionally when it is safe to do so.
10583 */
10584static void hmR0VmxPostRunGuest(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
10585{
10586 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
10587
10588 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
10589 ASMAtomicIncU32(&pVCpu->hm.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
10590 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
10591 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
10592 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
10593 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
10594
10595 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10596 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
10597 {
10598 uint64_t uGstTsc;
10599 if (!pVmxTransient->fIsNestedGuest)
10600 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10601 else
10602 {
10603 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10604 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
10605 }
10606 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
10607 }
10608
10609 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
10610 TMNotifyEndOfExecution(pVCpu); /* Notify TM that the guest is no longer running. */
10611 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10612
10613#if HC_ARCH_BITS == 64
10614 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
10615#endif
10616#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
10617 /* The 64-on-32 switcher maintains VMCS-launch state on its own
10618 and we need to leave it alone here. */
10619 if (pVmcsInfo->pfnStartVM != VMXR0SwitcherStartVM64)
10620 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
10621#else
10622 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
10623#endif
10624#ifdef VBOX_STRICT
10625 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
10626#endif
10627 Assert(!ASMIntAreEnabled());
10628 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
10629 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10630
10631 /*
10632 * Save the basic VM-exit reason and check if the VM-entry failed.
10633 * See Intel spec. 24.9.1 "Basic VM-exit Information".
10634 */
10635 uint32_t uExitReason;
10636 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
10637 AssertRC(rc);
10638 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
10639 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
10640
10641 /*
10642 * Check if VMLAUNCH/VMRESUME succeeded.
10643 * If this failed, we cause a guru meditation and cease further execution.
10644 */
10645 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
10646 {
10647 /*
10648 * Update the VM-exit history array here even if the VM-entry failed due to:
10649 * - Invalid guest state.
10650 * - MSR loading.
10651 * - Machine-check event.
10652 *
10653 * In any of the above cases we will still have a "valid" VM-exit reason
10654 * despite @a fVMEntryFailed being false.
10655 *
10656 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
10657 *
10658 * Note! We don't have CS or RIP at this point. Will probably address that later
10659 * by amending the history entry added here.
10660 */
10661 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
10662 UINT64_MAX, uHostTsc);
10663
10664 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
10665 {
10666 VMMRZCallRing3Enable(pVCpu);
10667
10668 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10669 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10670
10671#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
10672 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
10673 AssertRC(rc);
10674#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
10675 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_RFLAGS);
10676 AssertRC(rc);
10677#else
10678 /*
10679 * Import the guest-interruptibility state always as we need it while evaluating
10680 * injecting events on re-entry.
10681 *
10682 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
10683 * checking for real-mode while exporting the state because all bits that cause
10684 * mode changes wrt CR0 are intercepted.
10685 */
10686 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_HM_VMX_INT_STATE);
10687 AssertRC(rc);
10688#endif
10689
10690 /*
10691 * Sync the TPR shadow with our APIC state.
10692 */
10693 if ( !pVmxTransient->fIsNestedGuest
10694 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
10695 {
10696 Assert(pVmcsInfo->pbVirtApic);
10697 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
10698 {
10699 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
10700 AssertRC(rc);
10701 ASMAtomicOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
10702 }
10703 }
10704
10705 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10706 return;
10707 }
10708 }
10709 else
10710 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
10711
10712 VMMRZCallRing3Enable(pVCpu);
10713}
10714
10715
10716/**
10717 * Runs the guest code using hardware-assisted VMX the normal way.
10718 *
10719 * @returns VBox status code.
10720 * @param pVCpu The cross context virtual CPU structure.
10721 * @param pcLoops Pointer to the number of executed loops.
10722 */
10723static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPU pVCpu, uint32_t *pcLoops)
10724{
10725 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
10726 Assert(pcLoops);
10727 Assert(*pcLoops <= cMaxResumeLoops);
10728
10729 VMXTRANSIENT VmxTransient;
10730 RT_ZERO(VmxTransient);
10731 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
10732
10733 /* Paranoia. */
10734 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfo);
10735 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10736
10737 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
10738 for (;;)
10739 {
10740 Assert(!HMR0SuspendPending());
10741 HMVMX_ASSERT_CPU_SAFE(pVCpu);
10742 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
10743
10744 /*
10745 * Preparatory work for running nested-guest code, this may force us to
10746 * return to ring-3.
10747 *
10748 * Warning! This bugger disables interrupts on VINF_SUCCESS!
10749 */
10750 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
10751 if (rcStrict != VINF_SUCCESS)
10752 break;
10753
10754 /* Interrupts are disabled at this point! */
10755 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
10756 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
10757 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
10758 /* Interrupts are re-enabled at this point! */
10759
10760 /*
10761 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
10762 */
10763 if (RT_SUCCESS(rcRun))
10764 { /* very likely */ }
10765 else
10766 {
10767 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
10768 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
10769 return rcRun;
10770 }
10771
10772 /*
10773 * Profile the VM-exit.
10774 */
10775 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
10776 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
10777 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
10778 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
10779 HMVMX_START_EXIT_DISPATCH_PROF();
10780
10781 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
10782
10783 /*
10784 * Handle the VM-exit.
10785 */
10786#ifdef HMVMX_USE_FUNCTION_TABLE
10787 rcStrict = g_apfnVMExitHandlers[VmxTransient.uExitReason](pVCpu, &VmxTransient);
10788#else
10789 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
10790#endif
10791 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
10792 if (rcStrict == VINF_SUCCESS)
10793 {
10794 if (++(*pcLoops) <= cMaxResumeLoops)
10795 continue;
10796 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
10797 rcStrict = VINF_EM_RAW_INTERRUPT;
10798 }
10799 break;
10800 }
10801
10802 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
10803 return rcStrict;
10804}
10805
10806#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10807/**
10808 * Runs the nested-guest code using hardware-assisted VMX.
10809 *
10810 * @returns VBox status code.
10811 * @param pVCpu The cross context virtual CPU structure.
10812 * @param pcLoops Pointer to the number of executed loops.
10813 *
10814 * @sa hmR0VmxRunGuestCodeNormal().
10815 */
10816static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPU pVCpu, uint32_t *pcLoops)
10817{
10818 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
10819 Assert(pcLoops);
10820 Assert(*pcLoops <= cMaxResumeLoops);
10821
10822 VMXTRANSIENT VmxTransient;
10823 RT_ZERO(VmxTransient);
10824 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
10825 VmxTransient.fIsNestedGuest = true;
10826
10827 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
10828 for (;;)
10829 {
10830 Assert(!HMR0SuspendPending());
10831 HMVMX_ASSERT_CPU_SAFE(pVCpu);
10832 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
10833
10834 /*
10835 * Preparatory work for running guest code, this may force us to
10836 * return to ring-3.
10837 *
10838 * Warning! This bugger disables interrupts on VINF_SUCCESS!
10839 */
10840 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
10841 if (rcStrict != VINF_SUCCESS)
10842 break;
10843
10844 /* Interrupts are disabled at this point! */
10845 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
10846 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
10847 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
10848 /* Interrupts are re-enabled at this point! */
10849
10850 /*
10851 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
10852 */
10853 if (RT_SUCCESS(rcRun))
10854 { /* very likely */ }
10855 else
10856 {
10857 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
10858 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
10859 return rcRun;
10860 }
10861
10862 /*
10863 * Profile the VM-exit.
10864 */
10865 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
10866 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
10867 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
10868 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
10869 HMVMX_START_EXIT_DISPATCH_PROF();
10870
10871 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
10872
10873 /*
10874 * Handle the VM-exit.
10875 */
10876 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
10877 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
10878 if ( rcStrict == VINF_SUCCESS
10879 && CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10880 {
10881 if (++(*pcLoops) <= cMaxResumeLoops)
10882 continue;
10883 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
10884 rcStrict = VINF_EM_RAW_INTERRUPT;
10885 }
10886 break;
10887 }
10888
10889 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
10890 return rcStrict;
10891}
10892#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10893
10894
10895/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
10896 * probes.
10897 *
10898 * The following few functions and associated structure contains the bloat
10899 * necessary for providing detailed debug events and dtrace probes as well as
10900 * reliable host side single stepping. This works on the principle of
10901 * "subclassing" the normal execution loop and workers. We replace the loop
10902 * method completely and override selected helpers to add necessary adjustments
10903 * to their core operation.
10904 *
10905 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
10906 * any performance for debug and analysis features.
10907 *
10908 * @{
10909 */
10910
10911/**
10912 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
10913 * the debug run loop.
10914 */
10915typedef struct VMXRUNDBGSTATE
10916{
10917 /** The RIP we started executing at. This is for detecting that we stepped. */
10918 uint64_t uRipStart;
10919 /** The CS we started executing with. */
10920 uint16_t uCsStart;
10921
10922 /** Whether we've actually modified the 1st execution control field. */
10923 bool fModifiedProcCtls : 1;
10924 /** Whether we've actually modified the 2nd execution control field. */
10925 bool fModifiedProcCtls2 : 1;
10926 /** Whether we've actually modified the exception bitmap. */
10927 bool fModifiedXcptBitmap : 1;
10928
10929 /** We desire the modified the CR0 mask to be cleared. */
10930 bool fClearCr0Mask : 1;
10931 /** We desire the modified the CR4 mask to be cleared. */
10932 bool fClearCr4Mask : 1;
10933 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
10934 uint32_t fCpe1Extra;
10935 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
10936 uint32_t fCpe1Unwanted;
10937 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
10938 uint32_t fCpe2Extra;
10939 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
10940 uint32_t bmXcptExtra;
10941 /** The sequence number of the Dtrace provider settings the state was
10942 * configured against. */
10943 uint32_t uDtraceSettingsSeqNo;
10944 /** VM-exits to check (one bit per VM-exit). */
10945 uint32_t bmExitsToCheck[3];
10946
10947 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
10948 uint32_t fProcCtlsInitial;
10949 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
10950 uint32_t fProcCtls2Initial;
10951 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
10952 uint32_t bmXcptInitial;
10953} VMXRUNDBGSTATE;
10954AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
10955typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
10956
10957
10958/**
10959 * Initializes the VMXRUNDBGSTATE structure.
10960 *
10961 * @param pVCpu The cross context virtual CPU structure of the
10962 * calling EMT.
10963 * @param pVmxTransient The VMX-transient structure.
10964 * @param pDbgState The debug state to initialize.
10965 */
10966static void hmR0VmxRunDebugStateInit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
10967{
10968 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
10969 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
10970
10971 pDbgState->fModifiedProcCtls = false;
10972 pDbgState->fModifiedProcCtls2 = false;
10973 pDbgState->fModifiedXcptBitmap = false;
10974 pDbgState->fClearCr0Mask = false;
10975 pDbgState->fClearCr4Mask = false;
10976 pDbgState->fCpe1Extra = 0;
10977 pDbgState->fCpe1Unwanted = 0;
10978 pDbgState->fCpe2Extra = 0;
10979 pDbgState->bmXcptExtra = 0;
10980 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
10981 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
10982 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
10983}
10984
10985
10986/**
10987 * Updates the VMSC fields with changes requested by @a pDbgState.
10988 *
10989 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
10990 * immediately before executing guest code, i.e. when interrupts are disabled.
10991 * We don't check status codes here as we cannot easily assert or return in the
10992 * latter case.
10993 *
10994 * @param pVCpu The cross context virtual CPU structure.
10995 * @param pVmxTransient The VMX-transient structure.
10996 * @param pDbgState The debug state.
10997 */
10998static void hmR0VmxPreRunGuestDebugStateApply(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
10999{
11000 /*
11001 * Ensure desired flags in VMCS control fields are set.
11002 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11003 *
11004 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11005 * there should be no stale data in pCtx at this point.
11006 */
11007 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11008 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11009 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11010 {
11011 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11012 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11013 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11014 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11015 pDbgState->fModifiedProcCtls = true;
11016 }
11017
11018 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11019 {
11020 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11021 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11022 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11023 pDbgState->fModifiedProcCtls2 = true;
11024 }
11025
11026 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11027 {
11028 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11029 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11030 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11031 pDbgState->fModifiedXcptBitmap = true;
11032 }
11033
11034 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11035 {
11036 pVmcsInfo->u64Cr0Mask = 0;
11037 VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, 0);
11038 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11039 }
11040
11041 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11042 {
11043 pVmcsInfo->u64Cr4Mask = 0;
11044 VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, 0);
11045 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11046 }
11047
11048 NOREF(pVCpu);
11049}
11050
11051
11052/**
11053 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11054 * re-entry next time around.
11055 *
11056 * @returns Strict VBox status code (i.e. informational status codes too).
11057 * @param pVCpu The cross context virtual CPU structure.
11058 * @param pVmxTransient The VMX-transient structure.
11059 * @param pDbgState The debug state.
11060 * @param rcStrict The return code from executing the guest using single
11061 * stepping.
11062 */
11063static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11064 VBOXSTRICTRC rcStrict)
11065{
11066 /*
11067 * Restore VM-exit control settings as we may not reenter this function the
11068 * next time around.
11069 */
11070 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11071
11072 /* We reload the initial value, trigger what we can of recalculations the
11073 next time around. From the looks of things, that's all that's required atm. */
11074 if (pDbgState->fModifiedProcCtls)
11075 {
11076 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11077 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11078 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
11079 AssertRCReturn(rc2, rc2);
11080 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
11081 }
11082
11083 /* We're currently the only ones messing with this one, so just restore the
11084 cached value and reload the field. */
11085 if ( pDbgState->fModifiedProcCtls2
11086 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
11087 {
11088 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
11089 AssertRCReturn(rc2, rc2);
11090 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
11091 }
11092
11093 /* If we've modified the exception bitmap, we restore it and trigger
11094 reloading and partial recalculation the next time around. */
11095 if (pDbgState->fModifiedXcptBitmap)
11096 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
11097
11098 return rcStrict;
11099}
11100
11101
11102/**
11103 * Configures VM-exit controls for current DBGF and DTrace settings.
11104 *
11105 * This updates @a pDbgState and the VMCS execution control fields to reflect
11106 * the necessary VM-exits demanded by DBGF and DTrace.
11107 *
11108 * @param pVCpu The cross context virtual CPU structure.
11109 * @param pVmxTransient The VMX-transient structure. May update
11110 * fUpdatedTscOffsettingAndPreemptTimer.
11111 * @param pDbgState The debug state.
11112 */
11113static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11114{
11115 /*
11116 * Take down the dtrace serial number so we can spot changes.
11117 */
11118 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
11119 ASMCompilerBarrier();
11120
11121 /*
11122 * We'll rebuild most of the middle block of data members (holding the
11123 * current settings) as we go along here, so start by clearing it all.
11124 */
11125 pDbgState->bmXcptExtra = 0;
11126 pDbgState->fCpe1Extra = 0;
11127 pDbgState->fCpe1Unwanted = 0;
11128 pDbgState->fCpe2Extra = 0;
11129 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
11130 pDbgState->bmExitsToCheck[i] = 0;
11131
11132 /*
11133 * Software interrupts (INT XXh) - no idea how to trigger these...
11134 */
11135 PVM pVM = pVCpu->CTX_SUFF(pVM);
11136 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
11137 || VBOXVMM_INT_SOFTWARE_ENABLED())
11138 {
11139 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11140 }
11141
11142 /*
11143 * INT3 breakpoints - triggered by #BP exceptions.
11144 */
11145 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
11146 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11147
11148 /*
11149 * Exception bitmap and XCPT events+probes.
11150 */
11151 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
11152 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
11153 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
11154
11155 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
11156 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
11157 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11158 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
11159 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
11160 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
11161 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
11162 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
11163 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
11164 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
11165 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
11166 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
11167 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
11168 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
11169 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
11170 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
11171 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
11172 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
11173
11174 if (pDbgState->bmXcptExtra)
11175 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11176
11177 /*
11178 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
11179 *
11180 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
11181 * So, when adding/changing/removing please don't forget to update it.
11182 *
11183 * Some of the macros are picking up local variables to save horizontal space,
11184 * (being able to see it in a table is the lesser evil here).
11185 */
11186#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
11187 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
11188 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
11189#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
11190 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11191 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11192 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11193 } else do { } while (0)
11194#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
11195 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11196 { \
11197 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
11198 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11199 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11200 } else do { } while (0)
11201#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
11202 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11203 { \
11204 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
11205 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11206 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11207 } else do { } while (0)
11208#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
11209 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11210 { \
11211 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
11212 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11213 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11214 } else do { } while (0)
11215
11216 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
11217 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
11218 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
11219 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
11220 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
11221
11222 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
11223 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
11224 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
11225 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
11226 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
11227 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
11228 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
11229 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
11230 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
11231 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
11232 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
11233 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
11234 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
11235 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
11236 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
11237 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
11238 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
11239 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
11240 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
11241 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
11242 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
11243 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
11244 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
11245 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
11246 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
11247 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
11248 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
11249 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
11250 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
11251 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
11252 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
11253 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
11254 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
11255 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
11256 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
11257 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
11258
11259 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
11260 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11261 {
11262 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
11263 | CPUMCTX_EXTRN_APIC_TPR);
11264 AssertRC(rc);
11265
11266#if 0 /** @todo fix me */
11267 pDbgState->fClearCr0Mask = true;
11268 pDbgState->fClearCr4Mask = true;
11269#endif
11270 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
11271 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
11272 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11273 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
11274 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
11275 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
11276 require clearing here and in the loop if we start using it. */
11277 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
11278 }
11279 else
11280 {
11281 if (pDbgState->fClearCr0Mask)
11282 {
11283 pDbgState->fClearCr0Mask = false;
11284 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
11285 }
11286 if (pDbgState->fClearCr4Mask)
11287 {
11288 pDbgState->fClearCr4Mask = false;
11289 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
11290 }
11291 }
11292 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
11293 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
11294
11295 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
11296 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
11297 {
11298 /** @todo later, need to fix handler as it assumes this won't usually happen. */
11299 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
11300 }
11301 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
11302 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
11303
11304 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
11305 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
11306 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
11307 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
11308 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
11309 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
11310 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
11311 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
11312#if 0 /** @todo too slow, fix handler. */
11313 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
11314#endif
11315 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
11316
11317 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
11318 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
11319 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
11320 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
11321 {
11322 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11323 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
11324 }
11325 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11326 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11327 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11328 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11329
11330 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
11331 || IS_EITHER_ENABLED(pVM, INSTR_STR)
11332 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
11333 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
11334 {
11335 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11336 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
11337 }
11338 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
11339 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
11340 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
11341 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
11342
11343 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
11344 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
11345 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
11346 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
11347 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
11348 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
11349 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
11350 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
11351 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
11352 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
11353 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
11354 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
11355 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
11356 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
11357 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
11358 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
11359 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
11360 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
11361 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
11362 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
11363 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
11364 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
11365
11366#undef IS_EITHER_ENABLED
11367#undef SET_ONLY_XBM_IF_EITHER_EN
11368#undef SET_CPE1_XBM_IF_EITHER_EN
11369#undef SET_CPEU_XBM_IF_EITHER_EN
11370#undef SET_CPE2_XBM_IF_EITHER_EN
11371
11372 /*
11373 * Sanitize the control stuff.
11374 */
11375 pDbgState->fCpe2Extra &= pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1;
11376 if (pDbgState->fCpe2Extra)
11377 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
11378 pDbgState->fCpe1Extra &= pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1;
11379 pDbgState->fCpe1Unwanted &= ~pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0;
11380 if (pVCpu->hm.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
11381 {
11382 pVCpu->hm.s.fDebugWantRdTscExit ^= true;
11383 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
11384 }
11385
11386 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
11387 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
11388 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
11389 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
11390}
11391
11392
11393/**
11394 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
11395 * appropriate.
11396 *
11397 * The caller has checked the VM-exit against the
11398 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
11399 * already, so we don't have to do that either.
11400 *
11401 * @returns Strict VBox status code (i.e. informational status codes too).
11402 * @param pVCpu The cross context virtual CPU structure.
11403 * @param pVmxTransient The VMX-transient structure.
11404 * @param uExitReason The VM-exit reason.
11405 *
11406 * @remarks The name of this function is displayed by dtrace, so keep it short
11407 * and to the point. No longer than 33 chars long, please.
11408 */
11409static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
11410{
11411 /*
11412 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
11413 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
11414 *
11415 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
11416 * does. Must add/change/remove both places. Same ordering, please.
11417 *
11418 * Added/removed events must also be reflected in the next section
11419 * where we dispatch dtrace events.
11420 */
11421 bool fDtrace1 = false;
11422 bool fDtrace2 = false;
11423 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
11424 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
11425 uint32_t uEventArg = 0;
11426#define SET_EXIT(a_EventSubName) \
11427 do { \
11428 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11429 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11430 } while (0)
11431#define SET_BOTH(a_EventSubName) \
11432 do { \
11433 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
11434 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11435 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
11436 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11437 } while (0)
11438 switch (uExitReason)
11439 {
11440 case VMX_EXIT_MTF:
11441 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
11442
11443 case VMX_EXIT_XCPT_OR_NMI:
11444 {
11445 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
11446 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
11447 {
11448 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
11449 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
11450 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
11451 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
11452 {
11453 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
11454 {
11455 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
11456 uEventArg = pVmxTransient->uExitIntErrorCode;
11457 }
11458 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
11459 switch (enmEvent1)
11460 {
11461 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
11462 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
11463 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
11464 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
11465 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
11466 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
11467 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
11468 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
11469 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
11470 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
11471 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
11472 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
11473 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
11474 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
11475 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
11476 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
11477 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
11478 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
11479 default: break;
11480 }
11481 }
11482 else
11483 AssertFailed();
11484 break;
11485
11486 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
11487 uEventArg = idxVector;
11488 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
11489 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
11490 break;
11491 }
11492 break;
11493 }
11494
11495 case VMX_EXIT_TRIPLE_FAULT:
11496 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
11497 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
11498 break;
11499 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
11500 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
11501 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
11502 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
11503 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
11504
11505 /* Instruction specific VM-exits: */
11506 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
11507 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
11508 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
11509 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
11510 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
11511 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
11512 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
11513 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
11514 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
11515 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
11516 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
11517 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
11518 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
11519 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
11520 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
11521 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
11522 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
11523 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
11524 case VMX_EXIT_MOV_CRX:
11525 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
11526 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
11527 SET_BOTH(CRX_READ);
11528 else
11529 SET_BOTH(CRX_WRITE);
11530 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
11531 break;
11532 case VMX_EXIT_MOV_DRX:
11533 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
11534 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
11535 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
11536 SET_BOTH(DRX_READ);
11537 else
11538 SET_BOTH(DRX_WRITE);
11539 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
11540 break;
11541 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
11542 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
11543 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
11544 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
11545 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
11546 case VMX_EXIT_GDTR_IDTR_ACCESS:
11547 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
11548 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
11549 {
11550 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
11551 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
11552 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
11553 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
11554 }
11555 break;
11556
11557 case VMX_EXIT_LDTR_TR_ACCESS:
11558 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
11559 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
11560 {
11561 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
11562 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
11563 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
11564 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
11565 }
11566 break;
11567
11568 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
11569 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
11570 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
11571 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
11572 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
11573 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
11574 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
11575 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
11576 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
11577 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
11578 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
11579
11580 /* Events that aren't relevant at this point. */
11581 case VMX_EXIT_EXT_INT:
11582 case VMX_EXIT_INT_WINDOW:
11583 case VMX_EXIT_NMI_WINDOW:
11584 case VMX_EXIT_TPR_BELOW_THRESHOLD:
11585 case VMX_EXIT_PREEMPT_TIMER:
11586 case VMX_EXIT_IO_INSTR:
11587 break;
11588
11589 /* Errors and unexpected events. */
11590 case VMX_EXIT_INIT_SIGNAL:
11591 case VMX_EXIT_SIPI:
11592 case VMX_EXIT_IO_SMI:
11593 case VMX_EXIT_SMI:
11594 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
11595 case VMX_EXIT_ERR_MSR_LOAD:
11596 case VMX_EXIT_ERR_MACHINE_CHECK:
11597 break;
11598
11599 default:
11600 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
11601 break;
11602 }
11603#undef SET_BOTH
11604#undef SET_EXIT
11605
11606 /*
11607 * Dtrace tracepoints go first. We do them here at once so we don't
11608 * have to copy the guest state saving and stuff a few dozen times.
11609 * Down side is that we've got to repeat the switch, though this time
11610 * we use enmEvent since the probes are a subset of what DBGF does.
11611 */
11612 if (fDtrace1 || fDtrace2)
11613 {
11614 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
11615 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11616 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
11617 switch (enmEvent1)
11618 {
11619 /** @todo consider which extra parameters would be helpful for each probe. */
11620 case DBGFEVENT_END: break;
11621 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
11622 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
11623 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
11624 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
11625 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
11626 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
11627 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
11628 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
11629 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
11630 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
11631 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
11632 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
11633 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
11634 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
11635 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
11636 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
11637 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
11638 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
11639 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11640 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
11641 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
11642 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
11643 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
11644 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
11645 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
11646 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
11647 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
11648 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11649 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11650 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11651 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11652 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
11653 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
11654 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
11655 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
11656 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
11657 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
11658 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
11659 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
11660 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
11661 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
11662 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
11663 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
11664 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
11665 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
11666 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
11667 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
11668 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
11669 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
11670 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
11671 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
11672 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
11673 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
11674 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
11675 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
11676 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
11677 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
11678 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
11679 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
11680 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
11681 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
11682 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
11683 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
11684 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
11685 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
11686 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
11687 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
11688 }
11689 switch (enmEvent2)
11690 {
11691 /** @todo consider which extra parameters would be helpful for each probe. */
11692 case DBGFEVENT_END: break;
11693 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
11694 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
11695 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
11696 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
11697 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
11698 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
11699 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
11700 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
11701 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
11702 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11703 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11704 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11705 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11706 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
11707 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
11708 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
11709 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
11710 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
11711 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
11712 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
11713 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
11714 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
11715 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
11716 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
11717 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
11718 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
11719 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
11720 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
11721 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
11722 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
11723 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
11724 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
11725 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
11726 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
11727 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
11728 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
11729 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
11730 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
11731 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
11732 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
11733 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
11734 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
11735 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
11736 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
11737 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
11738 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
11739 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
11740 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
11741 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
11742 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
11743 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
11744 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
11745 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
11746 }
11747 }
11748
11749 /*
11750 * Fire of the DBGF event, if enabled (our check here is just a quick one,
11751 * the DBGF call will do a full check).
11752 *
11753 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
11754 * Note! If we have to events, we prioritize the first, i.e. the instruction
11755 * one, in order to avoid event nesting.
11756 */
11757 PVM pVM = pVCpu->CTX_SUFF(pVM);
11758 if ( enmEvent1 != DBGFEVENT_END
11759 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
11760 {
11761 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
11762 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
11763 if (rcStrict != VINF_SUCCESS)
11764 return rcStrict;
11765 }
11766 else if ( enmEvent2 != DBGFEVENT_END
11767 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
11768 {
11769 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
11770 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
11771 if (rcStrict != VINF_SUCCESS)
11772 return rcStrict;
11773 }
11774
11775 return VINF_SUCCESS;
11776}
11777
11778
11779/**
11780 * Single-stepping VM-exit filtering.
11781 *
11782 * This is preprocessing the VM-exits and deciding whether we've gotten far
11783 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
11784 * handling is performed.
11785 *
11786 * @returns Strict VBox status code (i.e. informational status codes too).
11787 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
11788 * @param pVmxTransient The VMX-transient structure.
11789 * @param pDbgState The debug state.
11790 */
11791DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11792{
11793 /*
11794 * Expensive (saves context) generic dtrace VM-exit probe.
11795 */
11796 uint32_t const uExitReason = pVmxTransient->uExitReason;
11797 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
11798 { /* more likely */ }
11799 else
11800 {
11801 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
11802 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11803 AssertRC(rc);
11804 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
11805 }
11806
11807 /*
11808 * Check for host NMI, just to get that out of the way.
11809 */
11810 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
11811 { /* normally likely */ }
11812 else
11813 {
11814 int rc2 = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
11815 AssertRCReturn(rc2, rc2);
11816 uint32_t uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
11817 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
11818 return hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient);
11819 }
11820
11821 /*
11822 * Check for single stepping event if we're stepping.
11823 */
11824 if (pVCpu->hm.s.fSingleInstruction)
11825 {
11826 switch (uExitReason)
11827 {
11828 case VMX_EXIT_MTF:
11829 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
11830
11831 /* Various events: */
11832 case VMX_EXIT_XCPT_OR_NMI:
11833 case VMX_EXIT_EXT_INT:
11834 case VMX_EXIT_TRIPLE_FAULT:
11835 case VMX_EXIT_INT_WINDOW:
11836 case VMX_EXIT_NMI_WINDOW:
11837 case VMX_EXIT_TASK_SWITCH:
11838 case VMX_EXIT_TPR_BELOW_THRESHOLD:
11839 case VMX_EXIT_APIC_ACCESS:
11840 case VMX_EXIT_EPT_VIOLATION:
11841 case VMX_EXIT_EPT_MISCONFIG:
11842 case VMX_EXIT_PREEMPT_TIMER:
11843
11844 /* Instruction specific VM-exits: */
11845 case VMX_EXIT_CPUID:
11846 case VMX_EXIT_GETSEC:
11847 case VMX_EXIT_HLT:
11848 case VMX_EXIT_INVD:
11849 case VMX_EXIT_INVLPG:
11850 case VMX_EXIT_RDPMC:
11851 case VMX_EXIT_RDTSC:
11852 case VMX_EXIT_RSM:
11853 case VMX_EXIT_VMCALL:
11854 case VMX_EXIT_VMCLEAR:
11855 case VMX_EXIT_VMLAUNCH:
11856 case VMX_EXIT_VMPTRLD:
11857 case VMX_EXIT_VMPTRST:
11858 case VMX_EXIT_VMREAD:
11859 case VMX_EXIT_VMRESUME:
11860 case VMX_EXIT_VMWRITE:
11861 case VMX_EXIT_VMXOFF:
11862 case VMX_EXIT_VMXON:
11863 case VMX_EXIT_MOV_CRX:
11864 case VMX_EXIT_MOV_DRX:
11865 case VMX_EXIT_IO_INSTR:
11866 case VMX_EXIT_RDMSR:
11867 case VMX_EXIT_WRMSR:
11868 case VMX_EXIT_MWAIT:
11869 case VMX_EXIT_MONITOR:
11870 case VMX_EXIT_PAUSE:
11871 case VMX_EXIT_GDTR_IDTR_ACCESS:
11872 case VMX_EXIT_LDTR_TR_ACCESS:
11873 case VMX_EXIT_INVEPT:
11874 case VMX_EXIT_RDTSCP:
11875 case VMX_EXIT_INVVPID:
11876 case VMX_EXIT_WBINVD:
11877 case VMX_EXIT_XSETBV:
11878 case VMX_EXIT_RDRAND:
11879 case VMX_EXIT_INVPCID:
11880 case VMX_EXIT_VMFUNC:
11881 case VMX_EXIT_RDSEED:
11882 case VMX_EXIT_XSAVES:
11883 case VMX_EXIT_XRSTORS:
11884 {
11885 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
11886 AssertRCReturn(rc, rc);
11887 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
11888 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
11889 return VINF_EM_DBG_STEPPED;
11890 break;
11891 }
11892
11893 /* Errors and unexpected events: */
11894 case VMX_EXIT_INIT_SIGNAL:
11895 case VMX_EXIT_SIPI:
11896 case VMX_EXIT_IO_SMI:
11897 case VMX_EXIT_SMI:
11898 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
11899 case VMX_EXIT_ERR_MSR_LOAD:
11900 case VMX_EXIT_ERR_MACHINE_CHECK:
11901 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
11902 break;
11903
11904 default:
11905 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
11906 break;
11907 }
11908 }
11909
11910 /*
11911 * Check for debugger event breakpoints and dtrace probes.
11912 */
11913 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
11914 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
11915 {
11916 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
11917 if (rcStrict != VINF_SUCCESS)
11918 return rcStrict;
11919 }
11920
11921 /*
11922 * Normal processing.
11923 */
11924#ifdef HMVMX_USE_FUNCTION_TABLE
11925 return g_apfnVMExitHandlers[uExitReason](pVCpu, pVmxTransient);
11926#else
11927 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
11928#endif
11929}
11930
11931
11932/**
11933 * Single steps guest code using hardware-assisted VMX.
11934 *
11935 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
11936 * but single-stepping through the hypervisor debugger.
11937 *
11938 * @returns Strict VBox status code (i.e. informational status codes too).
11939 * @param pVCpu The cross context virtual CPU structure.
11940 * @param pcLoops Pointer to the number of executed loops.
11941 *
11942 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
11943 */
11944static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPU pVCpu, uint32_t *pcLoops)
11945{
11946 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11947 Assert(pcLoops);
11948 Assert(*pcLoops <= cMaxResumeLoops);
11949
11950 VMXTRANSIENT VmxTransient;
11951 RT_ZERO(VmxTransient);
11952 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11953
11954 /* Set HMCPU indicators. */
11955 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
11956 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
11957 pVCpu->hm.s.fDebugWantRdTscExit = false;
11958 pVCpu->hm.s.fUsingDebugLoop = true;
11959
11960 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
11961 VMXRUNDBGSTATE DbgState;
11962 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
11963 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
11964
11965 /*
11966 * The loop.
11967 */
11968 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11969 for (;;)
11970 {
11971 Assert(!HMR0SuspendPending());
11972 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11973 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11974 bool fStepping = pVCpu->hm.s.fSingleInstruction;
11975
11976 /* Set up VM-execution controls the next two can respond to. */
11977 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
11978
11979 /*
11980 * Preparatory work for running guest code, this may force us to
11981 * return to ring-3.
11982 *
11983 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11984 */
11985 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
11986 if (rcStrict != VINF_SUCCESS)
11987 break;
11988
11989 /* Interrupts are disabled at this point! */
11990 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11991
11992 /* Override any obnoxious code in the above two calls. */
11993 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
11994
11995 /*
11996 * Finally execute the guest.
11997 */
11998 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11999
12000 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12001 /* Interrupts are re-enabled at this point! */
12002
12003 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12004 if (RT_SUCCESS(rcRun))
12005 { /* very likely */ }
12006 else
12007 {
12008 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12009 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12010 return rcRun;
12011 }
12012
12013 /* Profile the VM-exit. */
12014 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12015 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12016 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12017 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12018 HMVMX_START_EXIT_DISPATCH_PROF();
12019
12020 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12021
12022 /*
12023 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12024 */
12025 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12026 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12027 if (rcStrict != VINF_SUCCESS)
12028 break;
12029 if (++(*pcLoops) > cMaxResumeLoops)
12030 {
12031 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12032 rcStrict = VINF_EM_RAW_INTERRUPT;
12033 break;
12034 }
12035
12036 /*
12037 * Stepping: Did the RIP change, if so, consider it a single step.
12038 * Otherwise, make sure one of the TFs gets set.
12039 */
12040 if (fStepping)
12041 {
12042 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12043 AssertRC(rc);
12044 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12045 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12046 {
12047 rcStrict = VINF_EM_DBG_STEPPED;
12048 break;
12049 }
12050 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12051 }
12052
12053 /*
12054 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12055 */
12056 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12057 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12058 }
12059
12060 /*
12061 * Clear the X86_EFL_TF if necessary.
12062 */
12063 if (pVCpu->hm.s.fClearTrapFlag)
12064 {
12065 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12066 AssertRC(rc);
12067 pVCpu->hm.s.fClearTrapFlag = false;
12068 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12069 }
12070 /** @todo there seems to be issues with the resume flag when the monitor trap
12071 * flag is pending without being used. Seen early in bios init when
12072 * accessing APIC page in protected mode. */
12073
12074 /*
12075 * Restore VM-exit control settings as we may not re-enter this function the
12076 * next time around.
12077 */
12078 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
12079
12080 /* Restore HMCPU indicators. */
12081 pVCpu->hm.s.fUsingDebugLoop = false;
12082 pVCpu->hm.s.fDebugWantRdTscExit = false;
12083 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
12084
12085 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
12086 return rcStrict;
12087}
12088
12089
12090/** @} */
12091
12092
12093/**
12094 * Checks if any expensive dtrace probes are enabled and we should go to the
12095 * debug loop.
12096 *
12097 * @returns true if we should use debug loop, false if not.
12098 */
12099static bool hmR0VmxAnyExpensiveProbesEnabled(void)
12100{
12101 /* It's probably faster to OR the raw 32-bit counter variables together.
12102 Since the variables are in an array and the probes are next to one
12103 another (more or less), we have good locality. So, better read
12104 eight-nine cache lines ever time and only have one conditional, than
12105 128+ conditionals, right? */
12106 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
12107 | VBOXVMM_XCPT_DE_ENABLED_RAW()
12108 | VBOXVMM_XCPT_DB_ENABLED_RAW()
12109 | VBOXVMM_XCPT_BP_ENABLED_RAW()
12110 | VBOXVMM_XCPT_OF_ENABLED_RAW()
12111 | VBOXVMM_XCPT_BR_ENABLED_RAW()
12112 | VBOXVMM_XCPT_UD_ENABLED_RAW()
12113 | VBOXVMM_XCPT_NM_ENABLED_RAW()
12114 | VBOXVMM_XCPT_DF_ENABLED_RAW()
12115 | VBOXVMM_XCPT_TS_ENABLED_RAW()
12116 | VBOXVMM_XCPT_NP_ENABLED_RAW()
12117 | VBOXVMM_XCPT_SS_ENABLED_RAW()
12118 | VBOXVMM_XCPT_GP_ENABLED_RAW()
12119 | VBOXVMM_XCPT_PF_ENABLED_RAW()
12120 | VBOXVMM_XCPT_MF_ENABLED_RAW()
12121 | VBOXVMM_XCPT_AC_ENABLED_RAW()
12122 | VBOXVMM_XCPT_XF_ENABLED_RAW()
12123 | VBOXVMM_XCPT_VE_ENABLED_RAW()
12124 | VBOXVMM_XCPT_SX_ENABLED_RAW()
12125 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
12126 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
12127 ) != 0
12128 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
12129 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
12130 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
12131 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
12132 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
12133 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
12134 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
12135 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
12136 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
12137 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
12138 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
12139 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
12140 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
12141 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
12142 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
12143 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
12144 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
12145 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
12146 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
12147 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
12148 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
12149 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
12150 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
12151 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
12152 | VBOXVMM_INSTR_STR_ENABLED_RAW()
12153 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
12154 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
12155 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
12156 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
12157 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
12158 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
12159 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
12160 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
12161 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
12162 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
12163 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
12164 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
12165 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
12166 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
12167 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
12168 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
12169 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
12170 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
12171 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
12172 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
12173 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
12174 ) != 0
12175 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
12176 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
12177 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
12178 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
12179 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
12180 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
12181 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
12182 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
12183 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
12184 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
12185 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
12186 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
12187 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
12188 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
12189 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
12190 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
12191 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
12192 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
12193 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
12194 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
12195 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
12196 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
12197 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
12198 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
12199 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
12200 | VBOXVMM_EXIT_STR_ENABLED_RAW()
12201 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
12202 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
12203 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
12204 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
12205 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
12206 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
12207 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
12208 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
12209 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
12210 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
12211 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
12212 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
12213 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
12214 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
12215 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
12216 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
12217 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
12218 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
12219 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
12220 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
12221 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
12222 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
12223 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
12224 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
12225 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
12226 ) != 0;
12227}
12228
12229
12230/**
12231 * Runs the guest using hardware-assisted VMX.
12232 *
12233 * @returns Strict VBox status code (i.e. informational status codes too).
12234 * @param pVCpu The cross context virtual CPU structure.
12235 */
12236VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPU pVCpu)
12237{
12238 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12239 Assert(VMMRZCallRing3IsEnabled(pVCpu));
12240 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12241 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
12242
12243 VMMRZCallRing3SetNotification(pVCpu, hmR0VmxCallRing3Callback, pCtx);
12244
12245 VBOXSTRICTRC rcStrict;
12246 uint32_t cLoops = 0;
12247#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12248 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
12249#else
12250 bool const fInNestedGuestMode = false;
12251#endif
12252 if (!fInNestedGuestMode)
12253 {
12254 if ( !pVCpu->hm.s.fUseDebugLoop
12255 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
12256 && !DBGFIsStepping(pVCpu)
12257 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
12258 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
12259 else
12260 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
12261 }
12262#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12263 else
12264 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
12265
12266 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
12267 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
12268#endif
12269
12270 if (rcStrict == VERR_EM_INTERPRETER)
12271 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
12272 else if (rcStrict == VINF_EM_RESET)
12273 rcStrict = VINF_EM_TRIPLE_FAULT;
12274
12275 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
12276 if (RT_FAILURE(rc2))
12277 {
12278 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
12279 rcStrict = rc2;
12280 }
12281 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12282 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
12283 return rcStrict;
12284}
12285
12286
12287#ifndef HMVMX_USE_FUNCTION_TABLE
12288/**
12289 * Handles a guest VM-exit from hardware-assisted VMX execution.
12290 *
12291 * @returns Strict VBox status code (i.e. informational status codes too).
12292 * @param pVCpu The cross context virtual CPU structure.
12293 * @param pVmxTransient The VMX-transient structure.
12294 */
12295DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
12296{
12297#ifdef DEBUG_ramshankar
12298#define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
12299 do { \
12300 if (a_fSave != 0) \
12301 hmR0VmxImportGuestState(pVCpu, HMVMX_CPUMCTX_EXTRN_ALL); \
12302 VBOXSTRICTRC rcStrict = a_CallExpr; \
12303 if (a_fSave != 0) \
12304 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
12305 return rcStrict; \
12306 } while (0)
12307#else
12308# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
12309#endif
12310 uint32_t const rcReason = pVmxTransient->uExitReason;
12311 switch (rcReason)
12312 {
12313 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
12314 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
12315 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
12316 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
12317 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
12318 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
12319 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
12320 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
12321 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
12322 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
12323 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
12324 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
12325 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
12326 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
12327 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
12328 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
12329 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
12330 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
12331 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
12332 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
12333 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
12334 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
12335 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
12336 case VMX_EXIT_RSM: VMEXIT_CALL_RET(0, hmR0VmxExitRsm(pVCpu, pVmxTransient));
12337 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
12338 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
12339 case VMX_EXIT_GDTR_IDTR_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitXdtrAccess(pVCpu, pVmxTransient));
12340 case VMX_EXIT_LDTR_TR_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitXdtrAccess(pVCpu, pVmxTransient));
12341 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
12342 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
12343 case VMX_EXIT_RDRAND: VMEXIT_CALL_RET(0, hmR0VmxExitRdrand(pVCpu, pVmxTransient));
12344 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
12345 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
12346 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
12347#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12348 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
12349 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
12350 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
12351 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
12352 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
12353 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
12354 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
12355 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
12356 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
12357#else
12358 case VMX_EXIT_VMCLEAR:
12359 case VMX_EXIT_VMLAUNCH:
12360 case VMX_EXIT_VMPTRLD:
12361 case VMX_EXIT_VMPTRST:
12362 case VMX_EXIT_VMREAD:
12363 case VMX_EXIT_VMRESUME:
12364 case VMX_EXIT_VMWRITE:
12365 case VMX_EXIT_VMXOFF:
12366 case VMX_EXIT_VMXON:
12367 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
12368#endif
12369
12370 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
12371 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
12372 case VMX_EXIT_INIT_SIGNAL: return hmR0VmxExitInitSignal(pVCpu, pVmxTransient);
12373 case VMX_EXIT_SIPI: return hmR0VmxExitSipi(pVCpu, pVmxTransient);
12374 case VMX_EXIT_IO_SMI: return hmR0VmxExitIoSmi(pVCpu, pVmxTransient);
12375 case VMX_EXIT_SMI: return hmR0VmxExitSmi(pVCpu, pVmxTransient);
12376 case VMX_EXIT_ERR_MSR_LOAD: return hmR0VmxExitErrMsrLoad(pVCpu, pVmxTransient);
12377 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
12378 case VMX_EXIT_ERR_MACHINE_CHECK: return hmR0VmxExitErrMachineCheck(pVCpu, pVmxTransient);
12379
12380 case VMX_EXIT_INVEPT:
12381 case VMX_EXIT_INVVPID:
12382 case VMX_EXIT_VMFUNC:
12383 case VMX_EXIT_XSAVES:
12384 case VMX_EXIT_XRSTORS:
12385 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
12386
12387 case VMX_EXIT_ENCLS:
12388 case VMX_EXIT_RDSEED:
12389 case VMX_EXIT_PML_FULL:
12390 default:
12391 return hmR0VmxExitErrUndefined(pVCpu, pVmxTransient);
12392 }
12393#undef VMEXIT_CALL_RET
12394}
12395#endif /* !HMVMX_USE_FUNCTION_TABLE */
12396
12397
12398#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12399/**
12400 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
12401 *
12402 * @returns Strict VBox status code (i.e. informational status codes too).
12403 * @param pVCpu The cross context virtual CPU structure.
12404 * @param pVmxTransient The VMX-transient structure.
12405 */
12406DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
12407{
12408 uint32_t const rcReason = pVmxTransient->uExitReason;
12409 switch (rcReason)
12410 {
12411 case VMX_EXIT_EPT_MISCONFIG:
12412 case VMX_EXIT_EPT_VIOLATION:
12413 case VMX_EXIT_IO_INSTR:
12414 case VMX_EXIT_CPUID:
12415 case VMX_EXIT_RDTSC:
12416 case VMX_EXIT_RDTSCP:
12417 case VMX_EXIT_APIC_ACCESS:
12418 case VMX_EXIT_XCPT_OR_NMI:
12419 case VMX_EXIT_MOV_CRX:
12420 case VMX_EXIT_EXT_INT:
12421 case VMX_EXIT_INT_WINDOW:
12422 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12423 case VMX_EXIT_MWAIT:
12424 case VMX_EXIT_MONITOR:
12425 case VMX_EXIT_TASK_SWITCH:
12426 case VMX_EXIT_PREEMPT_TIMER:
12427 case VMX_EXIT_RDMSR:
12428 case VMX_EXIT_WRMSR:
12429 case VMX_EXIT_VMCALL:
12430 case VMX_EXIT_MOV_DRX:
12431 case VMX_EXIT_HLT:
12432 case VMX_EXIT_INVD:
12433 case VMX_EXIT_INVLPG:
12434 case VMX_EXIT_RSM:
12435 case VMX_EXIT_MTF:
12436 case VMX_EXIT_PAUSE:
12437 case VMX_EXIT_GDTR_IDTR_ACCESS:
12438 case VMX_EXIT_LDTR_TR_ACCESS:
12439 case VMX_EXIT_WBINVD:
12440 case VMX_EXIT_XSETBV:
12441 case VMX_EXIT_RDRAND:
12442 case VMX_EXIT_INVPCID:
12443 case VMX_EXIT_GETSEC:
12444 case VMX_EXIT_RDPMC:
12445#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12446 case VMX_EXIT_VMCLEAR:
12447 case VMX_EXIT_VMLAUNCH:
12448 case VMX_EXIT_VMPTRLD:
12449 case VMX_EXIT_VMPTRST:
12450 case VMX_EXIT_VMREAD:
12451 case VMX_EXIT_VMRESUME:
12452 case VMX_EXIT_VMWRITE:
12453 case VMX_EXIT_VMXOFF:
12454 case VMX_EXIT_VMXON:
12455#endif
12456 case VMX_EXIT_TRIPLE_FAULT:
12457 case VMX_EXIT_NMI_WINDOW:
12458 case VMX_EXIT_INIT_SIGNAL:
12459 case VMX_EXIT_SIPI:
12460 case VMX_EXIT_IO_SMI:
12461 case VMX_EXIT_SMI:
12462 case VMX_EXIT_ERR_MSR_LOAD:
12463 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12464 case VMX_EXIT_ERR_MACHINE_CHECK:
12465
12466 case VMX_EXIT_INVEPT:
12467 case VMX_EXIT_INVVPID:
12468 case VMX_EXIT_VMFUNC:
12469 case VMX_EXIT_XSAVES:
12470 case VMX_EXIT_XRSTORS:
12471
12472 case VMX_EXIT_ENCLS:
12473 case VMX_EXIT_RDSEED:
12474 case VMX_EXIT_PML_FULL:
12475 default:
12476 return hmR0VmxExitErrUndefined(pVCpu, pVmxTransient);
12477 }
12478#undef VMEXIT_CALL_RET
12479}
12480#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
12481
12482
12483#ifdef VBOX_STRICT
12484/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
12485# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
12486 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
12487
12488# define HMVMX_ASSERT_PREEMPT_CPUID() \
12489 do { \
12490 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
12491 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
12492 } while (0)
12493
12494# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12495 do { \
12496 AssertPtr((a_pVCpu)); \
12497 AssertPtr((a_pVmxTransient)); \
12498 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
12499 Assert((a_pVmxTransient)->pVmcsInfo); \
12500 Assert(ASMIntAreEnabled()); \
12501 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
12502 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
12503 Log4Func(("vcpu[%RU32] -v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v\n", (a_pVCpu)->idCpu)); \
12504 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
12505 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
12506 HMVMX_ASSERT_PREEMPT_CPUID(); \
12507 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
12508 } while (0)
12509
12510# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12511 do { \
12512 Log4Func(("\n")); \
12513 } while (0)
12514#else
12515# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12516 do { \
12517 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
12518 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
12519 } while (0)
12520# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
12521#endif
12522
12523
12524/**
12525 * Advances the guest RIP by the specified number of bytes.
12526 *
12527 * @param pVCpu The cross context virtual CPU structure.
12528 * @param cbInstr Number of bytes to advance the RIP by.
12529 *
12530 * @remarks No-long-jump zone!!!
12531 */
12532DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPU pVCpu, uint32_t cbInstr)
12533{
12534 /* Advance the RIP. */
12535 pVCpu->cpum.GstCtx.rip += cbInstr;
12536 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
12537
12538 /* Update interrupt inhibition. */
12539 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
12540 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
12541 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
12542}
12543
12544
12545/**
12546 * Advances the guest RIP after reading it from the VMCS.
12547 *
12548 * @returns VBox status code, no informational status codes.
12549 * @param pVCpu The cross context virtual CPU structure.
12550 * @param pVmxTransient The VMX-transient structure.
12551 *
12552 * @remarks No-long-jump zone!!!
12553 */
12554static int hmR0VmxAdvanceGuestRip(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
12555{
12556 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
12557 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
12558 AssertRCReturn(rc, rc);
12559
12560 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbInstr);
12561 return VINF_SUCCESS;
12562}
12563
12564
12565/**
12566 * Handle a condition that occurred while delivering an event through the guest
12567 * IDT.
12568 *
12569 * @returns Strict VBox status code (i.e. informational status codes too).
12570 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
12571 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
12572 * to continue execution of the guest which will delivery the \#DF.
12573 * @retval VINF_EM_RESET if we detected a triple-fault condition.
12574 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
12575 *
12576 * @param pVCpu The cross context virtual CPU structure.
12577 * @param pVmxTransient The VMX-transient structure.
12578 *
12579 * @remarks No-long-jump zone!!!
12580 */
12581static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
12582{
12583 uint32_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
12584
12585 int rc2 = hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
12586 rc2 |= hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
12587 AssertRCReturn(rc2, rc2);
12588
12589 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
12590 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
12591 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
12592 {
12593 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo);
12594 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo);
12595
12596 /*
12597 * If the event was a software interrupt (generated with INT n) or a software exception
12598 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
12599 * can handle the VM-exit and continue guest execution which will re-execute the
12600 * instruction rather than re-injecting the exception, as that can cause premature
12601 * trips to ring-3 before injection and involve TRPM which currently has no way of
12602 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
12603 * the problem).
12604 */
12605 IEMXCPTRAISE enmRaise;
12606 IEMXCPTRAISEINFO fRaiseInfo;
12607 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
12608 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
12609 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
12610 {
12611 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
12612 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
12613 }
12614 else if (VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo))
12615 {
12616 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
12617 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
12618 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
12619 /** @todo Make AssertMsgReturn as just AssertMsg later. */
12620 AssertMsgReturn(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT,
12621 ("Unexpected VM-exit interruption vector type %#x!\n", uExitVectorType), VERR_VMX_IPE_5);
12622
12623 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
12624
12625 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
12626 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
12627 {
12628 pVmxTransient->fVectoringPF = true;
12629 enmRaise = IEMXCPTRAISE_PREV_EVENT;
12630 }
12631 }
12632 else
12633 {
12634 /*
12635 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
12636 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
12637 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
12638 */
12639 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
12640 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
12641 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
12642 enmRaise = IEMXCPTRAISE_PREV_EVENT;
12643 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
12644 }
12645
12646 /*
12647 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
12648 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
12649 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
12650 * subsequent VM-entry would fail.
12651 *
12652 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception". See @bugref{7445}.
12653 */
12654 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS)
12655 && uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
12656 && ( enmRaise == IEMXCPTRAISE_PREV_EVENT
12657 || (fRaiseInfo & IEMXCPTRAISEINFO_NMI_PF))
12658 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI))
12659 {
12660 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_BLOCK_NMIS);
12661 }
12662
12663 switch (enmRaise)
12664 {
12665 case IEMXCPTRAISE_CURRENT_XCPT:
12666 {
12667 Log4Func(("IDT: Pending secondary Xcpt: uIdtVectoringInfo=%#RX64 uExitIntInfo=%#RX64\n",
12668 pVmxTransient->uIdtVectoringInfo, pVmxTransient->uExitIntInfo));
12669 Assert(rcStrict == VINF_SUCCESS);
12670 break;
12671 }
12672
12673 case IEMXCPTRAISE_PREV_EVENT:
12674 {
12675 uint32_t u32ErrCode;
12676 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
12677 {
12678 rc2 = hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
12679 AssertRCReturn(rc2, rc2);
12680 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
12681 }
12682 else
12683 u32ErrCode = 0;
12684
12685 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
12686 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectPendingReflect);
12687 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
12688 0 /* cbInstr */, u32ErrCode, pVCpu->cpum.GstCtx.cr2);
12689
12690 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
12691 pVCpu->hm.s.Event.u32ErrCode));
12692 Assert(rcStrict == VINF_SUCCESS);
12693 break;
12694 }
12695
12696 case IEMXCPTRAISE_REEXEC_INSTR:
12697 Assert(rcStrict == VINF_SUCCESS);
12698 break;
12699
12700 case IEMXCPTRAISE_DOUBLE_FAULT:
12701 {
12702 /*
12703 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
12704 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
12705 */
12706 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
12707 {
12708 pVmxTransient->fVectoringDoublePF = true;
12709 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
12710 pVCpu->cpum.GstCtx.cr2));
12711 rcStrict = VINF_SUCCESS;
12712 }
12713 else
12714 {
12715 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectPendingReflect);
12716 hmR0VmxSetPendingXcptDF(pVCpu);
12717 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
12718 uIdtVector, uExitVector));
12719 rcStrict = VINF_HM_DOUBLE_FAULT;
12720 }
12721 break;
12722 }
12723
12724 case IEMXCPTRAISE_TRIPLE_FAULT:
12725 {
12726 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector, uExitVector));
12727 rcStrict = VINF_EM_RESET;
12728 break;
12729 }
12730
12731 case IEMXCPTRAISE_CPU_HANG:
12732 {
12733 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
12734 rcStrict = VERR_EM_GUEST_CPU_HANG;
12735 break;
12736 }
12737
12738 default:
12739 {
12740 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
12741 rcStrict = VERR_VMX_IPE_2;
12742 break;
12743 }
12744 }
12745 }
12746 else if ( VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo)
12747 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitIntInfo)
12748 && uExitVector != X86_XCPT_DF
12749 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI))
12750 {
12751 /*
12752 * Execution of IRET caused this fault when NMI blocking was in effect (i.e we're in the guest NMI handler).
12753 * We need to set the block-by-NMI field so that NMIs remain blocked until the IRET execution is restarted.
12754 * See Intel spec. 30.7.1.2 "Resuming guest software after handling an exception".
12755 */
12756 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
12757 {
12758 Log4Func(("Setting VMCPU_FF_BLOCK_NMIS. fValid=%RTbool uExitReason=%u\n",
12759 VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo), pVmxTransient->uExitReason));
12760 VMCPU_FF_SET(pVCpu, VMCPU_FF_BLOCK_NMIS);
12761 }
12762 }
12763
12764 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
12765 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
12766 return rcStrict;
12767}
12768
12769
12770/** @name VM-exit handlers.
12771 * @{
12772 */
12773/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
12774/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
12775/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
12776
12777/**
12778 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
12779 */
12780HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
12781{
12782 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
12783 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
12784 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
12785 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
12786 return VINF_SUCCESS;
12787 return VINF_EM_RAW_INTERRUPT;
12788}
12789
12790
12791/**
12792 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
12793 */
12794HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
12795{
12796 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
12797 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
12798
12799 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
12800 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
12801 AssertRCReturn(rc, rc);
12802
12803 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
12804 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
12805 && uIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
12806 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
12807
12808 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
12809 {
12810 /*
12811 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
12812 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
12813 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
12814 *
12815 * [1] -- See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
12816 * [2] -- See Intel spec. 27.5.5 "Updating Non-Register State".
12817 */
12818 VMXDispatchHostNmi();
12819 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
12820 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
12821 return VINF_SUCCESS;
12822 }
12823
12824 /* If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. */
12825 VBOXSTRICTRC rcStrictRc1 = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
12826 if (RT_UNLIKELY(rcStrictRc1 == VINF_SUCCESS))
12827 { /* likely */ }
12828 else
12829 {
12830 if (rcStrictRc1 == VINF_HM_DOUBLE_FAULT)
12831 rcStrictRc1 = VINF_SUCCESS;
12832 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
12833 return rcStrictRc1;
12834 }
12835
12836 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
12837 uint32_t const uVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
12838 switch (uIntType)
12839 {
12840 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT: /* Privileged software exception. (#DB from ICEBP) */
12841 Assert(uVector == X86_XCPT_DB);
12842 RT_FALL_THRU();
12843 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT: /* Software exception. (#BP or #OF) */
12844 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
12845 RT_FALL_THRU();
12846 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
12847 {
12848 /*
12849 * If there's any exception caused as a result of event injection, the resulting
12850 * secondary/final execption will be pending, we shall continue guest execution
12851 * after injecting the event. The page-fault case is complicated and we manually
12852 * handle any currently pending event in hmR0VmxExitXcptPF.
12853 */
12854 if (!pVCpu->hm.s.Event.fPending)
12855 { /* likely */ }
12856 else if (uVector != X86_XCPT_PF)
12857 {
12858 rc = VINF_SUCCESS;
12859 break;
12860 }
12861
12862 switch (uVector)
12863 {
12864 case X86_XCPT_PF: rc = hmR0VmxExitXcptPF(pVCpu, pVmxTransient); break;
12865 case X86_XCPT_GP: rc = hmR0VmxExitXcptGP(pVCpu, pVmxTransient); break;
12866 case X86_XCPT_MF: rc = hmR0VmxExitXcptMF(pVCpu, pVmxTransient); break;
12867 case X86_XCPT_DB: rc = hmR0VmxExitXcptDB(pVCpu, pVmxTransient); break;
12868 case X86_XCPT_BP: rc = hmR0VmxExitXcptBP(pVCpu, pVmxTransient); break;
12869 case X86_XCPT_AC: rc = hmR0VmxExitXcptAC(pVCpu, pVmxTransient); break;
12870
12871 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNM);
12872 rc = hmR0VmxExitXcptGeneric(pVCpu, pVmxTransient); break;
12873 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF);
12874 rc = hmR0VmxExitXcptGeneric(pVCpu, pVmxTransient); break;
12875 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE);
12876 rc = hmR0VmxExitXcptGeneric(pVCpu, pVmxTransient); break;
12877 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD);
12878 rc = hmR0VmxExitXcptGeneric(pVCpu, pVmxTransient); break;
12879 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS);
12880 rc = hmR0VmxExitXcptGeneric(pVCpu, pVmxTransient); break;
12881 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP);
12882 rc = hmR0VmxExitXcptGeneric(pVCpu, pVmxTransient); break;
12883 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS);
12884 rc = hmR0VmxExitXcptGeneric(pVCpu, pVmxTransient); break;
12885 default:
12886 {
12887 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
12888 if (pVmcsInfo->RealMode.fRealOnV86Active)
12889 {
12890 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
12891 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
12892 Assert(CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx));
12893
12894 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
12895 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
12896 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
12897 AssertRCReturn(rc, rc);
12898 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(uExitIntInfo),
12899 pVmxTransient->cbInstr, pVmxTransient->uExitIntErrorCode,
12900 0 /* GCPtrFaultAddress */);
12901 }
12902 else
12903 {
12904 AssertMsgFailed(("Unexpected VM-exit caused by exception %#x\n", uVector));
12905 pVCpu->hm.s.u32HMError = uVector;
12906 rc = VERR_VMX_UNEXPECTED_EXCEPTION;
12907 }
12908 break;
12909 }
12910 }
12911 break;
12912 }
12913
12914 default:
12915 {
12916 pVCpu->hm.s.u32HMError = uExitIntInfo;
12917 rc = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
12918 AssertMsgFailed(("Unexpected interruption info %#x\n", VMX_EXIT_INT_INFO_TYPE(uExitIntInfo)));
12919 break;
12920 }
12921 }
12922 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
12923 return rc;
12924}
12925
12926
12927/**
12928 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
12929 */
12930HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
12931{
12932 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
12933
12934 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
12935 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
12936 int rc = hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
12937 AssertRCReturn(rc, rc);
12938
12939 /* Evaluate and deliver pending events and resume guest execution. */
12940 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
12941 return VINF_SUCCESS;
12942}
12943
12944
12945/**
12946 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
12947 */
12948HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
12949{
12950 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
12951
12952 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
12953 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
12954 {
12955 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
12956 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient);
12957 }
12958
12959 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS));
12960
12961 /*
12962 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
12963 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
12964 */
12965 uint32_t fIntrState;
12966 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
12967 AssertRCReturn(rc, rc);
12968 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
12969 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
12970 {
12971 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
12972 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
12973
12974 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
12975 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
12976 AssertRCReturn(rc, rc);
12977 }
12978
12979 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
12980 rc = hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
12981 AssertRCReturn(rc, rc);
12982
12983 /* Evaluate and deliver pending events and resume guest execution. */
12984 return VINF_SUCCESS;
12985}
12986
12987
12988/**
12989 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
12990 */
12991HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
12992{
12993 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
12994 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
12995}
12996
12997
12998/**
12999 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
13000 */
13001HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13002{
13003 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13004 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13005}
13006
13007
13008/**
13009 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
13010 */
13011HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13012{
13013 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13014
13015 /*
13016 * Get the state we need and update the exit history entry.
13017 */
13018 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13019 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13020 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
13021 AssertRCReturn(rc, rc);
13022
13023 VBOXSTRICTRC rcStrict;
13024 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
13025 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
13026 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
13027 if (!pExitRec)
13028 {
13029 /*
13030 * Regular CPUID instruction execution.
13031 */
13032 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbInstr);
13033 if (rcStrict == VINF_SUCCESS)
13034 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13035 else if (rcStrict == VINF_IEM_RAISED_XCPT)
13036 {
13037 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13038 rcStrict = VINF_SUCCESS;
13039 }
13040 }
13041 else
13042 {
13043 /*
13044 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
13045 */
13046 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13047 AssertRCReturn(rc2, rc2);
13048
13049 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
13050 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
13051
13052 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
13053 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13054
13055 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
13056 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
13057 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
13058 }
13059 return rcStrict;
13060}
13061
13062
13063/**
13064 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
13065 */
13066HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13067{
13068 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13069
13070 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13071 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
13072 AssertRCReturn(rc, rc);
13073
13074 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
13075 return VINF_EM_RAW_EMULATE_INSTR;
13076
13077 AssertMsgFailed(("hmR0VmxExitGetsec: unexpected VM-exit when CR4.SMXE is 0.\n"));
13078 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient);
13079}
13080
13081
13082/**
13083 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
13084 */
13085HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13086{
13087 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13088
13089 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13090 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13091 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13092 AssertRCReturn(rc, rc);
13093
13094 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbInstr);
13095 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
13096 {
13097 /* If we get a spurious VM-exit when TSC offsetting is enabled,
13098 we must reset offsetting on VM-entry. See @bugref{6634}. */
13099 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
13100 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
13101 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13102 }
13103 else if (rcStrict == VINF_IEM_RAISED_XCPT)
13104 {
13105 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13106 rcStrict = VINF_SUCCESS;
13107 }
13108 return rcStrict;
13109}
13110
13111
13112/**
13113 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
13114 */
13115HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13116{
13117 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13118
13119 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13120 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
13121 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13122 AssertRCReturn(rc, rc);
13123
13124 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbInstr);
13125 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
13126 {
13127 /* If we get a spurious VM-exit when TSC offsetting is enabled,
13128 we must reset offsetting on VM-reentry. See @bugref{6634}. */
13129 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
13130 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
13131 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13132 }
13133 else if (rcStrict == VINF_IEM_RAISED_XCPT)
13134 {
13135 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13136 rcStrict = VINF_SUCCESS;
13137 }
13138 return rcStrict;
13139}
13140
13141
13142/**
13143 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
13144 */
13145HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13146{
13147 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13148
13149 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13150 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
13151 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
13152 AssertRCReturn(rc, rc);
13153
13154 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13155 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
13156 if (RT_LIKELY(rc == VINF_SUCCESS))
13157 {
13158 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13159 Assert(pVmxTransient->cbInstr == 2);
13160 }
13161 else
13162 {
13163 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
13164 rc = VERR_EM_INTERPRETER;
13165 }
13166 return rc;
13167}
13168
13169
13170/**
13171 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
13172 */
13173HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13174{
13175 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13176
13177 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
13178 if (EMAreHypercallInstructionsEnabled(pVCpu))
13179 {
13180 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13181 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
13182 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13183 AssertRCReturn(rc, rc);
13184
13185 /* Perform the hypercall. */
13186 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
13187 if (rcStrict == VINF_SUCCESS)
13188 {
13189 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13190 AssertRCReturn(rc, rc);
13191 }
13192 else
13193 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
13194 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
13195 || RT_FAILURE(rcStrict));
13196
13197 /* If the hypercall changes anything other than guest's general-purpose registers,
13198 we would need to reload the guest changed bits here before VM-entry. */
13199 }
13200 else
13201 Log4Func(("Hypercalls not enabled\n"));
13202
13203 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
13204 if (RT_FAILURE(rcStrict))
13205 {
13206 hmR0VmxSetPendingXcptUD(pVCpu);
13207 rcStrict = VINF_SUCCESS;
13208 }
13209
13210 return rcStrict;
13211}
13212
13213
13214/**
13215 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
13216 */
13217HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13218{
13219 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13220 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || pVCpu->hm.s.fUsingDebugLoop);
13221
13222 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13223 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
13224 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13225 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
13226 AssertRCReturn(rc, rc);
13227
13228 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbInstr, pVmxTransient->uExitQual);
13229
13230 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
13231 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13232 else if (rcStrict == VINF_IEM_RAISED_XCPT)
13233 {
13234 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13235 rcStrict = VINF_SUCCESS;
13236 }
13237 else
13238 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) sttus: %Rrc\n", pVmxTransient->uExitQual,
13239 VBOXSTRICTRC_VAL(rcStrict)));
13240 return rcStrict;
13241}
13242
13243
13244/**
13245 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
13246 */
13247HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13248{
13249 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13250
13251 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13252 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
13253 AssertRCReturn(rc, rc);
13254
13255 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13256 rc = EMInterpretMonitor(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
13257 if (RT_LIKELY(rc == VINF_SUCCESS))
13258 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13259 else
13260 {
13261 AssertMsg(rc == VERR_EM_INTERPRETER, ("hmR0VmxExitMonitor: EMInterpretMonitor failed with %Rrc\n", rc));
13262 rc = VERR_EM_INTERPRETER;
13263 }
13264 return rc;
13265}
13266
13267
13268/**
13269 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
13270 */
13271HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13272{
13273 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13274
13275 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13276 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
13277 AssertRCReturn(rc, rc);
13278
13279 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13280 VBOXSTRICTRC rc2 = EMInterpretMWait(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
13281 rc = VBOXSTRICTRC_VAL(rc2);
13282 if (RT_LIKELY( rc == VINF_SUCCESS
13283 || rc == VINF_EM_HALT))
13284 {
13285 int rc3 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13286 AssertRCReturn(rc3, rc3);
13287
13288 if ( rc == VINF_EM_HALT
13289 && EMMonitorWaitShouldContinue(pVCpu, pCtx))
13290 rc = VINF_SUCCESS;
13291 }
13292 else
13293 {
13294 AssertMsg(rc == VERR_EM_INTERPRETER, ("hmR0VmxExitMwait: EMInterpretMWait failed with %Rrc\n", rc));
13295 rc = VERR_EM_INTERPRETER;
13296 }
13297 AssertMsg(rc == VINF_SUCCESS || rc == VINF_EM_HALT || rc == VERR_EM_INTERPRETER,
13298 ("hmR0VmxExitMwait: failed, invalid error code %Rrc\n", rc));
13299 return rc;
13300}
13301
13302
13303/**
13304 * VM-exit handler for RSM (VMX_EXIT_RSM). Unconditional VM-exit.
13305 */
13306HMVMX_EXIT_NSRC_DECL hmR0VmxExitRsm(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13307{
13308 /*
13309 * Execution of RSM outside of SMM mode causes #UD regardless of VMX root or VMX non-root
13310 * mode. In theory, we should never get this VM-exit. This can happen only if dual-monitor
13311 * treatment of SMI and VMX is enabled, which can (only?) be done by executing VMCALL in
13312 * VMX root operation. If we get here, something funny is going on.
13313 *
13314 * See Intel spec. 33.15.5 "Enabling the Dual-Monitor Treatment".
13315 */
13316 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13317 AssertMsgFailed(("Unexpected RSM VM-exit\n"));
13318 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient);
13319}
13320
13321
13322/**
13323 * VM-exit handler for SMI (VMX_EXIT_SMI). Unconditional VM-exit.
13324 */
13325HMVMX_EXIT_NSRC_DECL hmR0VmxExitSmi(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13326{
13327 /*
13328 * This can only happen if we support dual-monitor treatment of SMI, which can be activated
13329 * by executing VMCALL in VMX root operation. Only an STM (SMM transfer monitor) would get
13330 * this VM-exit when we (the executive monitor) execute a VMCALL in VMX root mode or receive
13331 * an SMI. If we get here, something funny is going on.
13332 *
13333 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
13334 * See Intel spec. 25.3 "Other Causes of VM-Exits"
13335 */
13336 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13337 AssertMsgFailed(("Unexpected SMI VM-exit\n"));
13338 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient);
13339}
13340
13341
13342/**
13343 * VM-exit handler for IO SMI (VMX_EXIT_IO_SMI). Unconditional VM-exit.
13344 */
13345HMVMX_EXIT_NSRC_DECL hmR0VmxExitIoSmi(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13346{
13347 /* Same treatment as VMX_EXIT_SMI. See comment in hmR0VmxExitSmi(). */
13348 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13349 AssertMsgFailed(("Unexpected IO SMI VM-exit\n"));
13350 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient);
13351}
13352
13353
13354/**
13355 * VM-exit handler for SIPI (VMX_EXIT_SIPI). Conditional VM-exit.
13356 */
13357HMVMX_EXIT_NSRC_DECL hmR0VmxExitSipi(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13358{
13359 /*
13360 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest activity state is used.
13361 * We don't make use of it as our guests don't have direct access to the host LAPIC.
13362 * See Intel spec. 25.3 "Other Causes of VM-exits".
13363 */
13364 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13365 AssertMsgFailed(("Unexpected SIPI VM-exit\n"));
13366 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient);
13367}
13368
13369
13370/**
13371 * VM-exit handler for INIT signal (VMX_EXIT_INIT_SIGNAL). Unconditional
13372 * VM-exit.
13373 */
13374HMVMX_EXIT_NSRC_DECL hmR0VmxExitInitSignal(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13375{
13376 /*
13377 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
13378 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery" and Intel spec. 29.3 "VMX Instructions" for "VMXON".
13379 *
13380 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these VM-exits.
13381 * See Intel spec. "23.8 Restrictions on VMX operation".
13382 */
13383 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13384 return VINF_SUCCESS;
13385}
13386
13387
13388/**
13389 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
13390 * VM-exit.
13391 */
13392HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13393{
13394 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13395 return VINF_EM_RESET;
13396}
13397
13398
13399/**
13400 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
13401 */
13402HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13403{
13404 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13405
13406 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13407 AssertRCReturn(rc, rc);
13408
13409 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
13410 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
13411 rc = VINF_SUCCESS;
13412 else
13413 rc = VINF_EM_HALT;
13414
13415 if (rc != VINF_SUCCESS)
13416 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
13417 return rc;
13418}
13419
13420
13421/**
13422 * VM-exit handler for instructions that result in a \#UD exception delivered to
13423 * the guest.
13424 */
13425HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13426{
13427 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13428 hmR0VmxSetPendingXcptUD(pVCpu);
13429 return VINF_SUCCESS;
13430}
13431
13432
13433/**
13434 * VM-exit handler for expiry of the VMX-preemption timer.
13435 */
13436HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13437{
13438 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13439
13440 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
13441 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
13442
13443 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
13444 PVM pVM = pVCpu->CTX_SUFF(pVM);
13445 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
13446 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
13447 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
13448}
13449
13450
13451/**
13452 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
13453 */
13454HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13455{
13456 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13457
13458 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13459 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13460 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
13461 AssertRCReturn(rc, rc);
13462
13463 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbInstr);
13464 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
13465 : HM_CHANGED_RAISED_XCPT_MASK);
13466
13467 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13468 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
13469
13470 return rcStrict;
13471}
13472
13473
13474/**
13475 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
13476 */
13477HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13478{
13479 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13480 /** @todo Use VM-exit instruction information. */
13481 return VERR_EM_INTERPRETER;
13482}
13483
13484
13485/**
13486 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE).
13487 * Error VM-exit.
13488 */
13489HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13490{
13491 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13492 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13493 AssertRCReturn(rc, rc);
13494
13495 rc = hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo);
13496 if (RT_FAILURE(rc))
13497 return rc;
13498
13499 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
13500 NOREF(uInvalidReason);
13501
13502#ifdef VBOX_STRICT
13503 uint32_t fIntrState;
13504 RTHCUINTREG uHCReg;
13505 uint64_t u64Val;
13506 uint32_t u32Val;
13507 rc = hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
13508 rc |= hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
13509 rc |= hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
13510 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
13511 AssertRCReturn(rc, rc);
13512
13513 Log4(("uInvalidReason %u\n", uInvalidReason));
13514 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
13515 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
13516 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
13517 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
13518
13519 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32Val); AssertRC(rc);
13520 Log4(("VMX_VMCS_GUEST_CR0 %#RX32\n", u32Val));
13521 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, &uHCReg); AssertRC(rc);
13522 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RHr\n", uHCReg));
13523 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, &uHCReg); AssertRC(rc);
13524 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
13525 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, &uHCReg); AssertRC(rc);
13526 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RHr\n", uHCReg));
13527 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_READ_SHADOW, &uHCReg); AssertRC(rc);
13528 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
13529 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
13530 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
13531
13532 hmR0DumpRegs(pVCpu);
13533#endif
13534
13535 return VERR_VMX_INVALID_GUEST_STATE;
13536}
13537
13538
13539/**
13540 * VM-exit handler for VM-entry failure due to an MSR-load
13541 * (VMX_EXIT_ERR_MSR_LOAD). Error VM-exit.
13542 */
13543HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrMsrLoad(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13544{
13545 AssertMsgFailed(("Unexpected MSR-load exit\n"));
13546 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient);
13547}
13548
13549
13550/**
13551 * VM-exit handler for VM-entry failure due to a machine-check event
13552 * (VMX_EXIT_ERR_MACHINE_CHECK). Error VM-exit.
13553 */
13554HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrMachineCheck(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13555{
13556 AssertMsgFailed(("Unexpected machine-check event exit\n"));
13557 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient);
13558}
13559
13560
13561/**
13562 * VM-exit handler for all undefined reasons. Should never ever happen.. in
13563 * theory.
13564 */
13565HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUndefined(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13566{
13567 RT_NOREF2(pVCpu, pVmxTransient);
13568 AssertMsgFailed(("Huh!? Undefined VM-exit reason %d\n", pVmxTransient->uExitReason));
13569 return VERR_VMX_UNDEFINED_EXIT_CODE;
13570}
13571
13572
13573/**
13574 * VM-exit handler for XDTR (LGDT, SGDT, LIDT, SIDT) accesses
13575 * (VMX_EXIT_GDTR_IDTR_ACCESS) and LDT and TR access (LLDT, LTR, SLDT, STR).
13576 * Conditional VM-exit.
13577 */
13578HMVMX_EXIT_DECL hmR0VmxExitXdtrAccess(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13579{
13580 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13581
13582 /* By default, we don't enable VMX_PROC_CTLS2_DESCRIPTOR_TABLE_EXIT. */
13583 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitXdtrAccess);
13584 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13585 if (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_DESC_TABLE_EXIT)
13586 return VERR_EM_INTERPRETER;
13587 AssertMsgFailed(("Unexpected XDTR access\n"));
13588 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient);
13589}
13590
13591
13592/**
13593 * VM-exit handler for RDRAND (VMX_EXIT_RDRAND). Conditional VM-exit.
13594 */
13595HMVMX_EXIT_DECL hmR0VmxExitRdrand(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13596{
13597 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13598
13599 /* By default, we don't enable VMX_PROC_CTLS2_RDRAND_EXIT. */
13600 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13601 if (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDRAND_EXIT)
13602 return VERR_EM_INTERPRETER;
13603 AssertMsgFailed(("Unexpected RDRAND exit\n"));
13604 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient);
13605}
13606
13607
13608/**
13609 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
13610 */
13611HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13612{
13613 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13614
13615 /** @todo Optimize this: We currently drag in in the whole MSR state
13616 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
13617 * MSRs required. That would require changes to IEM and possibly CPUM too.
13618 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
13619 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13620 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
13621 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
13622 switch (idMsr)
13623 {
13624 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
13625 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
13626 }
13627
13628 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13629 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
13630 AssertRCReturn(rc, rc);
13631
13632 Log4Func(("ecx=%#RX32\n", idMsr));
13633
13634#ifdef VBOX_STRICT
13635 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
13636 {
13637 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
13638 && idMsr != MSR_K6_EFER)
13639 {
13640 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
13641 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient);
13642 }
13643 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
13644 {
13645 Assert(pVmcsInfo->pvMsrBitmap);
13646 uint32_t fMsrpm = HMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
13647 if (fMsrpm & VMXMSRPM_ALLOW_RD)
13648 {
13649 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
13650 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient);
13651 }
13652 }
13653 }
13654#endif
13655
13656 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbInstr);
13657 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
13658 if (rcStrict == VINF_SUCCESS)
13659 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
13660 | HM_CHANGED_GUEST_RAX | HM_CHANGED_GUEST_RDX);
13661 else if (rcStrict == VINF_IEM_RAISED_XCPT)
13662 {
13663 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13664 rcStrict = VINF_SUCCESS;
13665 }
13666 else
13667 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ, ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
13668
13669 return rcStrict;
13670}
13671
13672
13673/**
13674 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
13675 */
13676HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13677{
13678 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13679
13680 /** @todo Optimize this: We currently drag in in the whole MSR state
13681 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
13682 * MSRs required. That would require changes to IEM and possibly CPUM too.
13683 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
13684 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
13685 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
13686
13687 /*
13688 * The FS and GS base MSRs are not part of the above all-MSRs mask.
13689 * Although we don't need to fetch the base as it will be overwritten shortly, while
13690 * loading guest-state we would also load the entire segment register including limit
13691 * and attributes and thus we need to load them here.
13692 */
13693 switch (idMsr)
13694 {
13695 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
13696 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
13697 }
13698
13699 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13700 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13701 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
13702 AssertRCReturn(rc, rc);
13703
13704 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
13705
13706 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbInstr);
13707 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
13708
13709 if (rcStrict == VINF_SUCCESS)
13710 {
13711 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13712
13713 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
13714 if ( idMsr == MSR_IA32_APICBASE
13715 || ( idMsr >= MSR_IA32_X2APIC_START
13716 && idMsr <= MSR_IA32_X2APIC_END))
13717 {
13718 /*
13719 * We've already saved the APIC related guest-state (TPR) in post-run phase.
13720 * When full APIC register virtualization is implemented we'll have to make
13721 * sure APIC state is saved from the VMCS before IEM changes it.
13722 */
13723 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
13724 }
13725 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
13726 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
13727 else if (idMsr == MSR_K6_EFER)
13728 {
13729 /*
13730 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
13731 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
13732 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
13733 */
13734 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
13735 }
13736
13737 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not supported. */
13738 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
13739 {
13740 switch (idMsr)
13741 {
13742 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
13743 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
13744 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
13745 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
13746 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
13747 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
13748 default:
13749 {
13750 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
13751 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
13752 else if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
13753 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
13754 break;
13755 }
13756 }
13757 }
13758#ifdef VBOX_STRICT
13759 else
13760 {
13761 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
13762 switch (idMsr)
13763 {
13764 case MSR_IA32_SYSENTER_CS:
13765 case MSR_IA32_SYSENTER_EIP:
13766 case MSR_IA32_SYSENTER_ESP:
13767 case MSR_K8_FS_BASE:
13768 case MSR_K8_GS_BASE:
13769 {
13770 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
13771 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient);
13772 }
13773
13774 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
13775 default:
13776 {
13777 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
13778 {
13779 /* EFER MSR writes are always intercepted. */
13780 if (idMsr != MSR_K6_EFER)
13781 {
13782 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
13783 idMsr));
13784 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient);
13785 }
13786 }
13787
13788 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
13789 {
13790 Assert(pVmcsInfo->pvMsrBitmap);
13791 uint32_t fMsrpm = HMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
13792 if (fMsrpm & VMXMSRPM_ALLOW_WR)
13793 {
13794 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
13795 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient);
13796 }
13797 }
13798 break;
13799 }
13800 }
13801 }
13802#endif /* VBOX_STRICT */
13803 }
13804 else if (rcStrict == VINF_IEM_RAISED_XCPT)
13805 {
13806 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13807 rcStrict = VINF_SUCCESS;
13808 }
13809 else
13810 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE, ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
13811
13812 return rcStrict;
13813}
13814
13815
13816/**
13817 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
13818 */
13819HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13820{
13821 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13822 /** @todo The guest has likely hit a contended spinlock. We might want to
13823 * poke a schedule different guest VCPU. */
13824 return VINF_EM_RAW_INTERRUPT;
13825}
13826
13827
13828/**
13829 * VM-exit handler for when the TPR value is lowered below the specified
13830 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
13831 */
13832HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13833{
13834 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13835 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
13836
13837 /*
13838 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
13839 * We'll re-evaluate pending interrupts and inject them before the next VM
13840 * entry so we can just continue execution here.
13841 */
13842 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
13843 return VINF_SUCCESS;
13844}
13845
13846
13847/**
13848 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
13849 * VM-exit.
13850 *
13851 * @retval VINF_SUCCESS when guest execution can continue.
13852 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
13853 * @retval VERR_EM_INTERPRETER when something unexpected happened, fallback to
13854 * interpreter.
13855 */
13856HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13857{
13858 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13859 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
13860
13861 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13862 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
13863 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13864 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13865 AssertRCReturn(rc, rc);
13866
13867 VBOXSTRICTRC rcStrict;
13868 PVM pVM = pVCpu->CTX_SUFF(pVM);
13869 RTGCUINTPTR const uExitQual = pVmxTransient->uExitQual;
13870 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
13871 switch (uAccessType)
13872 {
13873 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE: /* MOV to CRx */
13874 {
13875 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
13876 rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, pVmxTransient->cbInstr, VMX_EXIT_QUAL_CRX_REGISTER(uExitQual),
13877 VMX_EXIT_QUAL_CRX_GENREG(uExitQual));
13878 AssertMsg( rcStrict == VINF_SUCCESS
13879 || rcStrict == VINF_IEM_RAISED_XCPT
13880 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13881
13882 switch (VMX_EXIT_QUAL_CRX_REGISTER(uExitQual))
13883 {
13884 case 0:
13885 {
13886 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
13887 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13888 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
13889 Log4Func(("CR0 write rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
13890
13891 /*
13892 * This is a kludge for handling switches back to real mode when we try to use
13893 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
13894 * deal with special selector values, so we have to return to ring-3 and run
13895 * there till the selector values are V86 mode compatible.
13896 *
13897 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
13898 * latter is an alias for VINF_IEM_RAISED_XCPT which is converted to VINF_SUCCESs
13899 * at the end of this function.
13900 */
13901 if ( rc == VINF_SUCCESS
13902 && !pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
13903 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
13904 && (uOldCr0 & X86_CR0_PE)
13905 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE) )
13906 {
13907 /** @todo check selectors rather than returning all the time. */
13908 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
13909 rcStrict = VINF_EM_RESCHEDULE_REM;
13910 }
13911 break;
13912 }
13913
13914 case 2:
13915 {
13916 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
13917 /* Nothing to do here, CR2 it's not part of the VMCS. */
13918 break;
13919 }
13920
13921 case 3:
13922 {
13923 Assert( !pVM->hm.s.fNestedPaging
13924 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
13925 || pVCpu->hm.s.fUsingDebugLoop);
13926 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
13927 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
13928 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
13929 Log4Func(("CR3 write rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
13930 break;
13931 }
13932
13933 case 4:
13934 {
13935 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
13936 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
13937 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
13938 Log4Func(("CR4 write rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
13939 pVCpu->cpum.GstCtx.cr4, pVCpu->hm.s.fLoadSaveGuestXcr0));
13940 break;
13941 }
13942
13943 case 8:
13944 {
13945 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
13946 Assert(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
13947 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
13948 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
13949 break;
13950 }
13951 default:
13952 AssertMsgFailed(("Invalid CRx register %#x\n", VMX_EXIT_QUAL_CRX_REGISTER(uExitQual)));
13953 break;
13954 }
13955 break;
13956 }
13957
13958 case VMX_EXIT_QUAL_CRX_ACCESS_READ: /* MOV from CRx */
13959 {
13960 Assert( !pVM->hm.s.fNestedPaging
13961 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
13962 || pVCpu->hm.s.fUsingDebugLoop
13963 || VMX_EXIT_QUAL_CRX_REGISTER(uExitQual) != 3);
13964 /* CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
13965 Assert( VMX_EXIT_QUAL_CRX_REGISTER(uExitQual) != 8
13966 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
13967
13968 rcStrict = IEMExecDecodedMovCRxRead(pVCpu, pVmxTransient->cbInstr, VMX_EXIT_QUAL_CRX_GENREG(uExitQual),
13969 VMX_EXIT_QUAL_CRX_REGISTER(uExitQual));
13970 AssertMsg( rcStrict == VINF_SUCCESS
13971 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13972#ifdef VBOX_WITH_STATISTICS
13973 switch (VMX_EXIT_QUAL_CRX_REGISTER(uExitQual))
13974 {
13975 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
13976 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
13977 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
13978 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
13979 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
13980 }
13981#endif
13982 Log4Func(("CR%d Read access rcStrict=%Rrc\n", VMX_EXIT_QUAL_CRX_REGISTER(uExitQual),
13983 VBOXSTRICTRC_VAL(rcStrict)));
13984 if (VMX_EXIT_QUAL_CRX_GENREG(uExitQual) == X86_GREG_xSP)
13985 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
13986 else
13987 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13988 break;
13989 }
13990
13991 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS: /* CLTS (Clear Task-Switch Flag in CR0) */
13992 {
13993 rcStrict = IEMExecDecodedClts(pVCpu, pVmxTransient->cbInstr);
13994 AssertMsg( rcStrict == VINF_SUCCESS
13995 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13996
13997 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13998 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
13999 Log4Func(("CLTS rcStrict=%d\n", VBOXSTRICTRC_VAL(rcStrict)));
14000 break;
14001 }
14002
14003 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
14004 {
14005 /* Note! LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here. */
14006 rc = hmR0VmxReadGuestLinearAddrVmcs(pVCpu, pVmxTransient);
14007 AssertRCReturn(rc, rc);
14008 rcStrict = IEMExecDecodedLmsw(pVCpu, pVmxTransient->cbInstr, VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual),
14009 pVmxTransient->uGuestLinearAddr);
14010 AssertMsg( rcStrict == VINF_SUCCESS
14011 || rcStrict == VINF_IEM_RAISED_XCPT
14012 , ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14013
14014 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
14015 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
14016 Log4Func(("LMSW rcStrict=%d\n", VBOXSTRICTRC_VAL(rcStrict)));
14017 break;
14018 }
14019
14020 default:
14021 AssertMsgFailedReturn(("Invalid access-type in Mov CRx VM-exit qualification %#x\n", uAccessType),
14022 VERR_VMX_UNEXPECTED_EXCEPTION);
14023 }
14024
14025 Assert( (pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
14026 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
14027 if (rcStrict == VINF_IEM_RAISED_XCPT)
14028 {
14029 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14030 rcStrict = VINF_SUCCESS;
14031 }
14032
14033 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
14034 NOREF(pVM);
14035 return rcStrict;
14036}
14037
14038
14039/**
14040 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
14041 * VM-exit.
14042 */
14043HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14044{
14045 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14046 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
14047
14048 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14049 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14050 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
14051 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14052 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
14053 | CPUMCTX_EXTRN_EFER);
14054 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
14055 AssertRCReturn(rc, rc);
14056
14057 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
14058 uint32_t uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
14059 uint8_t uIOWidth = VMX_EXIT_QUAL_IO_WIDTH(pVmxTransient->uExitQual);
14060 bool fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
14061 bool fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
14062 bool fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
14063 bool fDbgStepping = pVCpu->hm.s.fSingleInstruction;
14064 AssertReturn(uIOWidth <= 3 && uIOWidth != 2, VERR_VMX_IPE_1);
14065
14066 /*
14067 * Update exit history to see if this exit can be optimized.
14068 */
14069 VBOXSTRICTRC rcStrict;
14070 PCEMEXITREC pExitRec = NULL;
14071 if ( !fGstStepping
14072 && !fDbgStepping)
14073 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14074 !fIOString
14075 ? !fIOWrite
14076 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
14077 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
14078 : !fIOWrite
14079 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
14080 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
14081 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14082 if (!pExitRec)
14083 {
14084 /* I/O operation lookup arrays. */
14085 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses. */
14086 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
14087 uint32_t const cbValue = s_aIOSizes[uIOWidth];
14088 uint32_t const cbInstr = pVmxTransient->cbInstr;
14089 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
14090 PVM pVM = pVCpu->CTX_SUFF(pVM);
14091 if (fIOString)
14092 {
14093 /*
14094 * INS/OUTS - I/O String instruction.
14095 *
14096 * Use instruction-information if available, otherwise fall back on
14097 * interpreting the instruction.
14098 */
14099 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
14100 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
14101 bool const fInsOutsInfo = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
14102 if (fInsOutsInfo)
14103 {
14104 int rc2 = hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
14105 AssertRCReturn(rc2, rc2);
14106 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
14107 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
14108 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
14109 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
14110 if (fIOWrite)
14111 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
14112 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
14113 else
14114 {
14115 /*
14116 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
14117 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
14118 * See Intel Instruction spec. for "INS".
14119 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
14120 */
14121 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
14122 }
14123 }
14124 else
14125 rcStrict = IEMExecOne(pVCpu);
14126
14127 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
14128 fUpdateRipAlready = true;
14129 }
14130 else
14131 {
14132 /*
14133 * IN/OUT - I/O instruction.
14134 */
14135 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
14136 uint32_t const uAndVal = s_aIOOpAnd[uIOWidth];
14137 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
14138 if (fIOWrite)
14139 {
14140 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
14141 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
14142 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
14143 && !pCtx->eflags.Bits.u1TF)
14144 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
14145 }
14146 else
14147 {
14148 uint32_t u32Result = 0;
14149 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
14150 if (IOM_SUCCESS(rcStrict))
14151 {
14152 /* Save result of I/O IN instr. in AL/AX/EAX. */
14153 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
14154 }
14155 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
14156 && !pCtx->eflags.Bits.u1TF)
14157 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
14158 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
14159 }
14160 }
14161
14162 if (IOM_SUCCESS(rcStrict))
14163 {
14164 if (!fUpdateRipAlready)
14165 {
14166 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
14167 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
14168 }
14169
14170 /*
14171 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
14172 * while booting Fedora 17 64-bit guest.
14173 *
14174 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
14175 */
14176 if (fIOString)
14177 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
14178
14179 /*
14180 * If any I/O breakpoints are armed, we need to check if one triggered
14181 * and take appropriate action.
14182 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
14183 */
14184 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
14185 AssertRCReturn(rc, rc);
14186
14187 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
14188 * execution engines about whether hyper BPs and such are pending. */
14189 uint32_t const uDr7 = pCtx->dr[7];
14190 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
14191 && X86_DR7_ANY_RW_IO(uDr7)
14192 && (pCtx->cr4 & X86_CR4_DE))
14193 || DBGFBpIsHwIoArmed(pVM)))
14194 {
14195 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
14196
14197 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
14198 VMMRZCallRing3Disable(pVCpu);
14199 HM_DISABLE_PREEMPT(pVCpu);
14200
14201 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
14202
14203 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
14204 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
14205 {
14206 /* Raise #DB. */
14207 if (fIsGuestDbgActive)
14208 ASMSetDR6(pCtx->dr[6]);
14209 if (pCtx->dr[7] != uDr7)
14210 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
14211
14212 hmR0VmxSetPendingXcptDB(pVCpu);
14213 }
14214 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
14215 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
14216 else if ( rcStrict2 != VINF_SUCCESS
14217 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
14218 rcStrict = rcStrict2;
14219 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
14220
14221 HM_RESTORE_PREEMPT();
14222 VMMRZCallRing3Enable(pVCpu);
14223 }
14224 }
14225
14226#ifdef VBOX_STRICT
14227 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
14228 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
14229 Assert(!fIOWrite);
14230 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
14231 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
14232 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
14233 Assert(fIOWrite);
14234 else
14235 {
14236# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
14237 * statuses, that the VMM device and some others may return. See
14238 * IOM_SUCCESS() for guidance. */
14239 AssertMsg( RT_FAILURE(rcStrict)
14240 || rcStrict == VINF_SUCCESS
14241 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
14242 || rcStrict == VINF_EM_DBG_BREAKPOINT
14243 || rcStrict == VINF_EM_RAW_GUEST_TRAP
14244 || rcStrict == VINF_EM_RAW_TO_R3
14245 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14246# endif
14247 }
14248#endif
14249 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
14250 }
14251 else
14252 {
14253 /*
14254 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14255 */
14256 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14257 AssertRCReturn(rc2, rc2);
14258 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
14259 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
14260 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
14261 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14262 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
14263 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOWidth));
14264
14265 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14266 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14267
14268 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14269 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14270 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14271 }
14272 return rcStrict;
14273}
14274
14275
14276/**
14277 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
14278 * VM-exit.
14279 */
14280HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14281{
14282 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14283
14284 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
14285 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
14286 AssertRCReturn(rc, rc);
14287 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
14288 {
14289 rc = hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14290 AssertRCReturn(rc, rc);
14291 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
14292 {
14293 uint32_t uErrCode;
14294 RTGCUINTPTR GCPtrFaultAddress;
14295 uint32_t const uIntType = VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo);
14296 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo);
14297 bool const fErrorCodeValid = VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo);
14298 if (fErrorCodeValid)
14299 {
14300 rc = hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14301 AssertRCReturn(rc, rc);
14302 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
14303 }
14304 else
14305 uErrCode = 0;
14306
14307 if ( uIntType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
14308 && uVector == X86_XCPT_PF)
14309 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
14310 else
14311 GCPtrFaultAddress = 0;
14312
14313 rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14314 AssertRCReturn(rc, rc);
14315
14316 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
14317 pVmxTransient->cbInstr, uErrCode, GCPtrFaultAddress);
14318
14319 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", uIntType, uVector));
14320 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
14321 return VINF_EM_RAW_INJECT_TRPM_EVENT;
14322 }
14323 }
14324
14325 /* Fall back to the interpreter to emulate the task-switch. */
14326 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
14327 return VERR_EM_INTERPRETER;
14328}
14329
14330
14331/**
14332 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
14333 */
14334HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14335{
14336 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14337
14338 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14339 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
14340 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
14341 AssertRCReturn(rc, rc);
14342 return VINF_EM_DBG_STEPPED;
14343}
14344
14345
14346/**
14347 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
14348 */
14349HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14350{
14351 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14352 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
14353
14354 /* If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. */
14355 VBOXSTRICTRC rcStrict1 = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14356 if (RT_LIKELY(rcStrict1 == VINF_SUCCESS))
14357 {
14358 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
14359 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
14360 {
14361 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectPendingInterpret);
14362 return VINF_EM_RAW_INJECT_TRPM_EVENT;
14363 }
14364 }
14365 else
14366 {
14367 if (rcStrict1 == VINF_HM_DOUBLE_FAULT)
14368 rcStrict1 = VINF_SUCCESS;
14369 return rcStrict1;
14370 }
14371
14372 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
14373 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14374 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14375 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
14376 AssertRCReturn(rc, rc);
14377
14378 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
14379 uint32_t uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
14380 VBOXSTRICTRC rcStrict2;
14381 switch (uAccessType)
14382 {
14383 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
14384 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
14385 {
14386 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
14387 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
14388 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
14389
14390 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
14391 GCPhys &= PAGE_BASE_GC_MASK;
14392 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
14393 PVM pVM = pVCpu->CTX_SUFF(pVM);
14394 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
14395 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
14396
14397 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14398 rcStrict2 = IOMMMIOPhysHandler(pVM, pVCpu,
14399 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW,
14400 CPUMCTX2CORE(pCtx), GCPhys);
14401 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict2)));
14402 if ( rcStrict2 == VINF_SUCCESS
14403 || rcStrict2 == VERR_PAGE_TABLE_NOT_PRESENT
14404 || rcStrict2 == VERR_PAGE_NOT_PRESENT)
14405 {
14406 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
14407 | HM_CHANGED_GUEST_APIC_TPR);
14408 rcStrict2 = VINF_SUCCESS;
14409 }
14410 break;
14411 }
14412
14413 default:
14414 Log4Func(("uAccessType=%#x\n", uAccessType));
14415 rcStrict2 = VINF_EM_RAW_EMULATE_INSTR;
14416 break;
14417 }
14418
14419 if (rcStrict2 != VINF_SUCCESS)
14420 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
14421 return rcStrict2;
14422}
14423
14424
14425/**
14426 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
14427 * VM-exit.
14428 */
14429HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14430{
14431 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14432
14433 /* We should -not- get this VM-exit if the guest's debug registers were active. */
14434 if (pVmxTransient->fWasGuestDebugStateActive)
14435 {
14436 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
14437 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient);
14438 }
14439
14440 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14441 if ( !pVCpu->hm.s.fSingleInstruction
14442 && !pVmxTransient->fWasHyperDebugStateActive)
14443 {
14444 Assert(!DBGFIsStepping(pVCpu));
14445 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
14446
14447 /* Don't intercept MOV DRx any more. */
14448 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
14449 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
14450 AssertRCReturn(rc, rc);
14451
14452 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
14453 VMMRZCallRing3Disable(pVCpu);
14454 HM_DISABLE_PREEMPT(pVCpu);
14455
14456 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
14457 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
14458 Assert(CPUMIsGuestDebugStateActive(pVCpu) || HC_ARCH_BITS == 32);
14459
14460 HM_RESTORE_PREEMPT();
14461 VMMRZCallRing3Enable(pVCpu);
14462
14463#ifdef VBOX_WITH_STATISTICS
14464 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
14465 AssertRCReturn(rc, rc);
14466 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
14467 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
14468 else
14469 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
14470#endif
14471 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
14472 return VINF_SUCCESS;
14473 }
14474
14475 /*
14476 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
14477 * The EFER MSR is always up-to-date.
14478 * Update the segment registers and DR7 from the CPU.
14479 */
14480 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14481 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
14482 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
14483 AssertRCReturn(rc, rc);
14484 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
14485
14486 PVM pVM = pVCpu->CTX_SUFF(pVM);
14487 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
14488 {
14489 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
14490 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
14491 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
14492 if (RT_SUCCESS(rc))
14493 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
14494 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
14495 }
14496 else
14497 {
14498 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
14499 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
14500 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
14501 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
14502 }
14503
14504 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
14505 if (RT_SUCCESS(rc))
14506 {
14507 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14508 AssertRCReturn(rc2, rc2);
14509 return VINF_SUCCESS;
14510 }
14511 return rc;
14512}
14513
14514
14515/**
14516 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
14517 * Conditional VM-exit.
14518 */
14519HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14520{
14521 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14522 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
14523
14524 /* If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. */
14525 VBOXSTRICTRC rcStrict1 = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14526 if (RT_LIKELY(rcStrict1 == VINF_SUCCESS))
14527 {
14528 /* If event delivery causes an EPT misconfig (MMIO), go back to instruction emulation as otherwise
14529 injecting the original pending event would most likely cause the same EPT misconfig VM-exit. */
14530 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
14531 {
14532 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectPendingInterpret);
14533 return VINF_EM_RAW_INJECT_TRPM_EVENT;
14534 }
14535 }
14536 else
14537 {
14538 if (rcStrict1 == VINF_HM_DOUBLE_FAULT)
14539 rcStrict1 = VINF_SUCCESS;
14540 return rcStrict1;
14541 }
14542
14543 /*
14544 * Get sufficent state and update the exit history entry.
14545 */
14546 RTGCPHYS GCPhys;
14547 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14548 int rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &GCPhys);
14549 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14550 AssertRCReturn(rc, rc);
14551
14552 VBOXSTRICTRC rcStrict;
14553 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14554 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
14555 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14556 if (!pExitRec)
14557 {
14558 /*
14559 * If we succeed, resume guest execution.
14560 * If we fail in interpreting the instruction because we couldn't get the guest physical address
14561 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
14562 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
14563 * weird case. See @bugref{6043}.
14564 */
14565 PVM pVM = pVCpu->CTX_SUFF(pVM);
14566 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14567 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
14568 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
14569 if ( rcStrict == VINF_SUCCESS
14570 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
14571 || rcStrict == VERR_PAGE_NOT_PRESENT)
14572 {
14573 /* Successfully handled MMIO operation. */
14574 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
14575 | HM_CHANGED_GUEST_APIC_TPR);
14576 rcStrict = VINF_SUCCESS;
14577 }
14578 }
14579 else
14580 {
14581 /*
14582 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14583 */
14584 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14585 AssertRCReturn(rc2, rc2);
14586
14587 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
14588 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
14589
14590 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14591 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14592
14593 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14594 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14595 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14596 }
14597 return VBOXSTRICTRC_TODO(rcStrict);
14598}
14599
14600
14601/**
14602 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
14603 * VM-exit.
14604 */
14605HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14606{
14607 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14608 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
14609
14610 /* If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. */
14611 VBOXSTRICTRC rcStrict1 = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14612 if (RT_LIKELY(rcStrict1 == VINF_SUCCESS))
14613 {
14614 /* In the unlikely case that the EPT violation happened as a result of delivering an event, log it. */
14615 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
14616 Log4Func(("EPT violation with an event pending u64IntInfo=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo));
14617 }
14618 else
14619 {
14620 if (rcStrict1 == VINF_HM_DOUBLE_FAULT)
14621 rcStrict1 = VINF_SUCCESS;
14622 return rcStrict1;
14623 }
14624
14625 RTGCPHYS GCPhys;
14626 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14627 int rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &GCPhys);
14628 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
14629 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14630 AssertRCReturn(rc, rc);
14631
14632 /* Intel spec. Table 27-7 "Exit Qualifications for EPT violations". */
14633 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", pVmxTransient->uExitQual));
14634
14635 RTGCUINT uErrorCode = 0;
14636 if (pVmxTransient->uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
14637 uErrorCode |= X86_TRAP_PF_ID;
14638 if (pVmxTransient->uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
14639 uErrorCode |= X86_TRAP_PF_RW;
14640 if (pVmxTransient->uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
14641 uErrorCode |= X86_TRAP_PF_P;
14642
14643 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
14644
14645
14646 /* Handle the pagefault trap for the nested shadow table. */
14647 PVM pVM = pVCpu->CTX_SUFF(pVM);
14648 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14649
14650 Log4Func(("EPT violation %#x at %#RX64 ErrorCode %#x cs:rip=%#04x:%#RX64\n", pVmxTransient->uExitQual, GCPhys, uErrorCode,
14651 pCtx->cs.Sel, pCtx->rip));
14652
14653 VBOXSTRICTRC rcStrict2 = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
14654 TRPMResetTrap(pVCpu);
14655
14656 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
14657 if ( rcStrict2 == VINF_SUCCESS
14658 || rcStrict2 == VERR_PAGE_TABLE_NOT_PRESENT
14659 || rcStrict2 == VERR_PAGE_NOT_PRESENT)
14660 {
14661 /* Successfully synced our nested page tables. */
14662 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
14663 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
14664 return VINF_SUCCESS;
14665 }
14666
14667 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict2)));
14668 return rcStrict2;
14669}
14670
14671/** @} */
14672
14673/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14674/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit exception handlers =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14675/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14676
14677/**
14678 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
14679 */
14680static int hmR0VmxExitXcptMF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14681{
14682 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14683 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
14684
14685 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
14686 AssertRCReturn(rc, rc);
14687
14688 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
14689 {
14690 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
14691 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
14692
14693 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
14694 * provides VM-exit instruction length. If this causes problem later,
14695 * disassemble the instruction like it's done on AMD-V. */
14696 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14697 AssertRCReturn(rc2, rc2);
14698 return rc;
14699 }
14700
14701 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14702 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14703 return rc;
14704}
14705
14706
14707/**
14708 * VM-exit exception handler for \#BP (Breakpoint exception).
14709 */
14710static int hmR0VmxExitXcptBP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14711{
14712 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14713 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
14714
14715 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14716 AssertRCReturn(rc, rc);
14717
14718 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14719 rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
14720 if (rc == VINF_EM_RAW_GUEST_TRAP)
14721 {
14722 rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14723 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14724 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14725 AssertRCReturn(rc, rc);
14726
14727 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14728 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14729 }
14730
14731 Assert(rc == VINF_SUCCESS || rc == VINF_EM_RAW_GUEST_TRAP || rc == VINF_EM_DBG_BREAKPOINT);
14732 return rc;
14733}
14734
14735
14736/**
14737 * VM-exit exception handler for \#AC (alignment check exception).
14738 */
14739static int hmR0VmxExitXcptAC(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14740{
14741 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14742
14743 /*
14744 * Re-inject it. We'll detect any nesting before getting here.
14745 */
14746 int rc = hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14747 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14748 AssertRCReturn(rc, rc);
14749 Assert(ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead) & HMVMX_READ_EXIT_INTERRUPTION_INFO);
14750
14751 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14752 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14753 return VINF_SUCCESS;
14754}
14755
14756
14757/**
14758 * VM-exit exception handler for \#DB (Debug exception).
14759 */
14760static int hmR0VmxExitXcptDB(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14761{
14762 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14763 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
14764
14765 /*
14766 * Get the DR6-like values from the VM-exit qualification and pass it to DBGF
14767 * for processing.
14768 */
14769 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
14770
14771 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
14772 uint64_t const uDR6 = X86_DR6_INIT_VAL
14773 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
14774 | X86_DR6_BD | X86_DR6_BS));
14775
14776 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14777 rc = DBGFRZTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
14778 Log6Func(("rc=%Rrc\n", rc));
14779 if (rc == VINF_EM_RAW_GUEST_TRAP)
14780 {
14781 /*
14782 * The exception was for the guest. Update DR6, DR7.GD and
14783 * IA32_DEBUGCTL.LBR before forwarding it.
14784 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
14785 */
14786 VMMRZCallRing3Disable(pVCpu);
14787 HM_DISABLE_PREEMPT(pVCpu);
14788
14789 pCtx->dr[6] &= ~X86_DR6_B_MASK;
14790 pCtx->dr[6] |= uDR6;
14791 if (CPUMIsGuestDebugStateActive(pVCpu))
14792 ASMSetDR6(pCtx->dr[6]);
14793
14794 HM_RESTORE_PREEMPT();
14795 VMMRZCallRing3Enable(pVCpu);
14796
14797 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
14798 AssertRCReturn(rc, rc);
14799
14800 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
14801 pCtx->dr[7] &= ~X86_DR7_GD;
14802
14803 /* Paranoia. */
14804 pCtx->dr[7] &= ~X86_DR7_RAZ_MASK;
14805 pCtx->dr[7] |= X86_DR7_RA1_MASK;
14806
14807 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_DR7, (uint32_t)pCtx->dr[7]);
14808 AssertRCReturn(rc, rc);
14809
14810 /*
14811 * Raise #DB in the guest.
14812 *
14813 * It is important to reflect exactly what the VM-exit gave us (preserving the
14814 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
14815 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
14816 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
14817 *
14818 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
14819 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
14820 */
14821 rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14822 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14823 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14824 AssertRCReturn(rc, rc);
14825 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14826 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14827 return VINF_SUCCESS;
14828 }
14829
14830 /*
14831 * Not a guest trap, must be a hypervisor related debug event then.
14832 * Update DR6 in case someone is interested in it.
14833 */
14834 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
14835 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
14836 CPUMSetHyperDR6(pVCpu, uDR6);
14837
14838 return rc;
14839}
14840
14841
14842/**
14843 * Hacks its way around the lovely mesa driver's backdoor accesses.
14844 *
14845 * @sa hmR0SvmHandleMesaDrvGp
14846 */
14847static int hmR0VmxHandleMesaDrvGp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14848{
14849 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
14850 RT_NOREF(pCtx);
14851
14852 /* For now we'll just skip the instruction. */
14853 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14854}
14855
14856
14857/**
14858 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
14859 * backdoor logging w/o checking what it is running inside.
14860 *
14861 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
14862 * backdoor port and magic numbers loaded in registers.
14863 *
14864 * @returns true if it is, false if it isn't.
14865 * @sa hmR0SvmIsMesaDrvGp
14866 */
14867DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14868{
14869 /* 0xed: IN eAX,dx */
14870 uint8_t abInstr[1];
14871 if (pVmxTransient->cbInstr != sizeof(abInstr))
14872 return false;
14873
14874 /* Check that it is #GP(0). */
14875 if (pVmxTransient->uExitIntErrorCode != 0)
14876 return false;
14877
14878 /* Check magic and port. */
14879 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
14880 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
14881 if (pCtx->rax != UINT32_C(0x564d5868))
14882 return false;
14883 if (pCtx->dx != UINT32_C(0x5658))
14884 return false;
14885
14886 /* Flat ring-3 CS. */
14887 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
14888 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
14889 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
14890 if (pCtx->cs.Attr.n.u2Dpl != 3)
14891 return false;
14892 if (pCtx->cs.u64Base != 0)
14893 return false;
14894
14895 /* Check opcode. */
14896 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
14897 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
14898 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
14899 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
14900 if (RT_FAILURE(rc))
14901 return false;
14902 if (abInstr[0] != 0xed)
14903 return false;
14904
14905 return true;
14906}
14907
14908
14909/**
14910 * VM-exit exception handler for \#GP (General-protection exception).
14911 *
14912 * @remarks Requires pVmxTransient->uExitIntInfo to be up-to-date.
14913 */
14914static int hmR0VmxExitXcptGP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14915{
14916 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14917 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
14918
14919 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14920 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14921 if (pVmcsInfo->RealMode.fRealOnV86Active)
14922 { /* likely */ }
14923 else
14924 {
14925#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14926 Assert(pVCpu->hm.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv);
14927#endif
14928 /* If the guest is not in real-mode or we have unrestricted guest execution support, reflect #GP to the guest. */
14929 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14930 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14931 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14932 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14933 AssertRCReturn(rc, rc);
14934 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
14935 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
14936
14937 if ( !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
14938 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
14939 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14940 pVmxTransient->cbInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14941 else
14942 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
14943 return rc;
14944 }
14945
14946 Assert(CPUMIsGuestInRealModeEx(pCtx));
14947 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest);
14948
14949 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14950 AssertRCReturn(rc, rc);
14951
14952 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
14953 if (rcStrict == VINF_SUCCESS)
14954 {
14955 if (!CPUMIsGuestInRealModeEx(pCtx))
14956 {
14957 /*
14958 * The guest is no longer in real-mode, check if we can continue executing the
14959 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
14960 */
14961 pVmcsInfo->RealMode.fRealOnV86Active = false;
14962 if (HMCanExecuteVmxGuest(pVCpu, pCtx))
14963 {
14964 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
14965 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14966 }
14967 else
14968 {
14969 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
14970 rcStrict = VINF_EM_RESCHEDULE;
14971 }
14972 }
14973 else
14974 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14975 }
14976 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14977 {
14978 rcStrict = VINF_SUCCESS;
14979 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14980 }
14981 return VBOXSTRICTRC_VAL(rcStrict);
14982}
14983
14984
14985/**
14986 * VM-exit exception handler wrapper for generic exceptions. Simply re-injects
14987 * the exception reported in the VMX transient structure back into the VM.
14988 *
14989 * @remarks Requires uExitIntInfo in the VMX transient structure to be
14990 * up-to-date.
14991 */
14992static int hmR0VmxExitXcptGeneric(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14993{
14994 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14995#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14996 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14997 AssertMsg(pVCpu->hm.s.fUsingDebugLoop || pVmcsInfo->RealMode.fRealOnV86Active,
14998 ("uVector=%#x u32XcptBitmap=%#X32\n",
14999 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
15000 NOREF(pVmcsInfo);
15001#endif
15002
15003 /* Re-inject the exception into the guest. This cannot be a double-fault condition which would have been handled in
15004 hmR0VmxCheckExitDueToEventDelivery(). */
15005 int rc = hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15006 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15007 AssertRCReturn(rc, rc);
15008 Assert(ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead) & HMVMX_READ_EXIT_INTERRUPTION_INFO);
15009
15010#ifdef DEBUG_ramshankar
15011 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
15012 Log(("hmR0VmxExitXcptGeneric: Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n",
15013 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pCtx->cs.Sel, pCtx->rip));
15014#endif
15015
15016 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
15017 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
15018 return VINF_SUCCESS;
15019}
15020
15021
15022/**
15023 * VM-exit exception handler for \#PF (Page-fault exception).
15024 */
15025static int hmR0VmxExitXcptPF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15026{
15027 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15028 PVM pVM = pVCpu->CTX_SUFF(pVM);
15029 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15030 rc |= hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15031 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15032 AssertRCReturn(rc, rc);
15033
15034 if (!pVM->hm.s.fNestedPaging)
15035 { /* likely */ }
15036 else
15037 {
15038#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
15039 Assert(pVCpu->hm.s.fUsingDebugLoop);
15040#endif
15041 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
15042 if (RT_LIKELY(!pVmxTransient->fVectoringDoublePF))
15043 {
15044 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
15045 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
15046 }
15047 else
15048 {
15049 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
15050 hmR0VmxSetPendingXcptDF(pVCpu);
15051 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
15052 }
15053 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
15054 return rc;
15055 }
15056
15057 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
15058 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
15059 if (pVmxTransient->fVectoringPF)
15060 {
15061 Assert(pVCpu->hm.s.Event.fPending);
15062 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15063 }
15064
15065 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15066 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15067 AssertRCReturn(rc, rc);
15068
15069 Log4Func(("#PF: cr2=%#RX64 cs:rip=%#04x:%#RX64 uErrCode %#RX32 cr3=%#RX64\n", pVmxTransient->uExitQual, pCtx->cs.Sel,
15070 pCtx->rip, pVmxTransient->uExitIntErrorCode, pCtx->cr3));
15071
15072 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
15073 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
15074
15075 Log4Func(("#PF: rc=%Rrc\n", rc));
15076 if (rc == VINF_SUCCESS)
15077 {
15078 /*
15079 * This is typically a shadow page table sync or a MMIO instruction. But we may have
15080 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
15081 */
15082 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15083 TRPMResetTrap(pVCpu);
15084 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
15085 return rc;
15086 }
15087
15088 if (rc == VINF_EM_RAW_GUEST_TRAP)
15089 {
15090 if (!pVmxTransient->fVectoringDoublePF)
15091 {
15092 /* It's a guest page fault and needs to be reflected to the guest. */
15093 uint32_t uGstErrorCode = TRPMGetErrorCode(pVCpu);
15094 TRPMResetTrap(pVCpu);
15095 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
15096 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
15097 uGstErrorCode, pVmxTransient->uExitQual);
15098 }
15099 else
15100 {
15101 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
15102 TRPMResetTrap(pVCpu);
15103 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
15104 hmR0VmxSetPendingXcptDF(pVCpu);
15105 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
15106 }
15107
15108 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
15109 return VINF_SUCCESS;
15110 }
15111
15112 TRPMResetTrap(pVCpu);
15113 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
15114 return rc;
15115}
15116
15117#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
15118/** @name VMX instruction handlers.
15119 * @{
15120 */
15121/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
15122/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VMX instructions VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
15123/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
15124
15125/**
15126 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
15127 */
15128HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15129{
15130 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15131
15132 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15133 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15134 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15135 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15136 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15137 AssertRCReturn(rc, rc);
15138
15139 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15140
15141 VMXVEXITINFO ExitInfo;
15142 RT_ZERO(ExitInfo);
15143 ExitInfo.uReason = pVmxTransient->uExitReason;
15144 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15145 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15146 ExitInfo.cbInstr = pVmxTransient->cbInstr;
15147 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15148
15149 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
15150 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15151 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15152 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15153 {
15154 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15155 rcStrict = VINF_SUCCESS;
15156 }
15157 return rcStrict;
15158}
15159
15160
15161/**
15162 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
15163 */
15164HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15165{
15166 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15167
15168 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
15169 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
15170 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15171 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15172 AssertRCReturn(rc, rc);
15173
15174 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15175
15176 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbInstr, VMXINSTRID_VMLAUNCH);
15177 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15178 {
15179 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
15180 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15181 }
15182 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15183 return rcStrict;
15184}
15185
15186
15187/**
15188 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
15189 */
15190HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15191{
15192 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15193
15194 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15195 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15196 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15197 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15198 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15199 AssertRCReturn(rc, rc);
15200
15201 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15202
15203 VMXVEXITINFO ExitInfo;
15204 RT_ZERO(ExitInfo);
15205 ExitInfo.uReason = pVmxTransient->uExitReason;
15206 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15207 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15208 ExitInfo.cbInstr = pVmxTransient->cbInstr;
15209 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15210
15211 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
15212 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15213 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15214 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15215 {
15216 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15217 rcStrict = VINF_SUCCESS;
15218 }
15219 return rcStrict;
15220}
15221
15222
15223/**
15224 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
15225 */
15226HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15227{
15228 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15229
15230 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15231 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15232 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15233 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15234 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15235 AssertRCReturn(rc, rc);
15236
15237 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15238
15239 VMXVEXITINFO ExitInfo;
15240 RT_ZERO(ExitInfo);
15241 ExitInfo.uReason = pVmxTransient->uExitReason;
15242 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15243 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15244 ExitInfo.cbInstr = pVmxTransient->cbInstr;
15245 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
15246
15247 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
15248 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15249 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15250 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15251 {
15252 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15253 rcStrict = VINF_SUCCESS;
15254 }
15255 return rcStrict;
15256}
15257
15258
15259/**
15260 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Unconditional VM-exit.
15261 */
15262HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15263{
15264 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15265
15266 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15267 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15268 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15269 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15270 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15271 AssertRCReturn(rc, rc);
15272
15273 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15274
15275 VMXVEXITINFO ExitInfo;
15276 RT_ZERO(ExitInfo);
15277 ExitInfo.uReason = pVmxTransient->uExitReason;
15278 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15279 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15280 ExitInfo.cbInstr = pVmxTransient->cbInstr;
15281 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
15282 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
15283
15284 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
15285 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15286 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15287 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15288 {
15289 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15290 rcStrict = VINF_SUCCESS;
15291 }
15292 return rcStrict;
15293}
15294
15295
15296/**
15297 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
15298 */
15299HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15300{
15301 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15302
15303 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
15304 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
15305 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15306 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15307 AssertRCReturn(rc, rc);
15308
15309 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15310
15311 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbInstr, VMXINSTRID_VMRESUME);
15312 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15313 {
15314 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
15315 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15316 }
15317 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15318 return rcStrict;
15319}
15320
15321
15322/**
15323 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Unconditional VM-exit.
15324 */
15325HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15326{
15327 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15328
15329 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15330 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15331 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15332 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15333 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15334 AssertRCReturn(rc, rc);
15335
15336 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15337
15338 VMXVEXITINFO ExitInfo;
15339 RT_ZERO(ExitInfo);
15340 ExitInfo.uReason = pVmxTransient->uExitReason;
15341 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15342 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15343 ExitInfo.cbInstr = pVmxTransient->cbInstr;
15344 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
15345 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15346
15347 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
15348 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15349 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15350 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15351 {
15352 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15353 rcStrict = VINF_SUCCESS;
15354 }
15355 return rcStrict;
15356}
15357
15358
15359/**
15360 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
15361 */
15362HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15363{
15364 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15365
15366 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15367 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
15368 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
15369 AssertRCReturn(rc, rc);
15370
15371 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15372
15373 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbInstr);
15374 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15375 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
15376 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15377 {
15378 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15379 rcStrict = VINF_SUCCESS;
15380 }
15381 return rcStrict;
15382}
15383
15384
15385/**
15386 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
15387 */
15388HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15389{
15390 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15391
15392 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15393 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15394 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15395 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15396 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15397 AssertRCReturn(rc, rc);
15398
15399 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15400
15401 VMXVEXITINFO ExitInfo;
15402 RT_ZERO(ExitInfo);
15403 ExitInfo.uReason = pVmxTransient->uExitReason;
15404 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15405 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15406 ExitInfo.cbInstr = pVmxTransient->cbInstr;
15407 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15408
15409 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
15410 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15411 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15412 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15413 {
15414 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15415 rcStrict = VINF_SUCCESS;
15416 }
15417 return rcStrict;
15418}
15419
15420/** @} */
15421#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
15422
Note: See TracBrowser for help on using the repository browser.

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