VirtualBox

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

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

VMM: Refactoring VMMR0/* and VMMRZ/* to use VMCC & VMMCPUCC. bugref:9217

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 701.5 KB
Line 
1/* $Id: HMVMXR0.cpp 80274 2019-08-14 14:34:38Z vboxsync $ */
2/** @file
3 * HM VMX (Intel VT-x) - Host Context Ring-0.
4 */
5
6/*
7 * Copyright (C) 2012-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define VBOX_BUGREF_9217_PART_I
23#define LOG_GROUP LOG_GROUP_HM
24#define VMCPU_INCL_CPUM_GST_CTX
25#include <iprt/x86.h>
26#include <iprt/asm-amd64-x86.h>
27#include <iprt/thread.h>
28#include <iprt/mem.h>
29#include <iprt/mp.h>
30
31#include <VBox/vmm/pdmapi.h>
32#include <VBox/vmm/dbgf.h>
33#include <VBox/vmm/iem.h>
34#include <VBox/vmm/iom.h>
35#include <VBox/vmm/tm.h>
36#include <VBox/vmm/em.h>
37#include <VBox/vmm/gim.h>
38#include <VBox/vmm/apic.h>
39#ifdef VBOX_WITH_REM
40# include <VBox/vmm/rem.h>
41#endif
42#include "HMInternal.h"
43#include <VBox/vmm/vmcc.h>
44#include <VBox/vmm/hmvmxinline.h>
45#include "HMVMXR0.h"
46#include "dtrace/VBoxVMM.h"
47
48#ifdef DEBUG_ramshankar
49# define HMVMX_ALWAYS_SAVE_GUEST_RFLAGS
50# define HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
51# define HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE
52# define HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
53# define HMVMX_ALWAYS_CLEAN_TRANSIENT
54# define HMVMX_ALWAYS_CHECK_GUEST_STATE
55# define HMVMX_ALWAYS_TRAP_ALL_XCPTS
56# define HMVMX_ALWAYS_TRAP_PF
57# define HMVMX_ALWAYS_FLUSH_TLB
58# define HMVMX_ALWAYS_SWAP_EFER
59#endif
60
61
62/*********************************************************************************************************************************
63* Defined Constants And Macros *
64*********************************************************************************************************************************/
65/** Use the function table. */
66#define HMVMX_USE_FUNCTION_TABLE
67
68/** Determine which tagged-TLB flush handler to use. */
69#define HMVMX_FLUSH_TAGGED_TLB_EPT_VPID 0
70#define HMVMX_FLUSH_TAGGED_TLB_EPT 1
71#define HMVMX_FLUSH_TAGGED_TLB_VPID 2
72#define HMVMX_FLUSH_TAGGED_TLB_NONE 3
73
74/**
75 * Flags to skip redundant reads of some common VMCS fields that are not part of
76 * the guest-CPU or VCPU state but are needed while handling VM-exits.
77 */
78#define HMVMX_READ_IDT_VECTORING_INFO RT_BIT_32(0)
79#define HMVMX_READ_IDT_VECTORING_ERROR_CODE RT_BIT_32(1)
80#define HMVMX_READ_EXIT_QUALIFICATION RT_BIT_32(2)
81#define HMVMX_READ_EXIT_INSTR_LEN RT_BIT_32(3)
82#define HMVMX_READ_EXIT_INTERRUPTION_INFO RT_BIT_32(4)
83#define HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE RT_BIT_32(5)
84#define HMVMX_READ_EXIT_INSTR_INFO RT_BIT_32(6)
85#define HMVMX_READ_GUEST_LINEAR_ADDR RT_BIT_32(7)
86#define HMVMX_READ_GUEST_PHYSICAL_ADDR RT_BIT_32(8)
87
88/** All the VMCS fields required for processing of exception/NMI VM-exits. */
89#define HMVMX_READ_XCPT_INFO ( HMVMX_READ_EXIT_INTERRUPTION_INFO \
90 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE \
91 | HMVMX_READ_EXIT_INSTR_LEN \
92 | HMVMX_READ_IDT_VECTORING_INFO \
93 | HMVMX_READ_IDT_VECTORING_ERROR_CODE)
94
95/** Assert that all the given fields have been read from the VMCS. */
96#ifdef VBOX_STRICT
97# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) \
98 do { \
99 uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead); \
100 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); \
101 Assert((fVmcsFieldRead & (a_fReadFields)) == (a_fReadFields)); \
102 } while (0)
103#else
104# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) do { } while (0)
105#endif
106
107/**
108 * Subset of the guest-CPU state that is kept by VMX R0 code while executing the
109 * guest using hardware-assisted VMX.
110 *
111 * This excludes state like GPRs (other than RSP) which are always are
112 * swapped and restored across the world-switch and also registers like EFER,
113 * MSR which cannot be modified by the guest without causing a VM-exit.
114 */
115#define HMVMX_CPUMCTX_EXTRN_ALL ( CPUMCTX_EXTRN_RIP \
116 | CPUMCTX_EXTRN_RFLAGS \
117 | CPUMCTX_EXTRN_RSP \
118 | CPUMCTX_EXTRN_SREG_MASK \
119 | CPUMCTX_EXTRN_TABLE_MASK \
120 | CPUMCTX_EXTRN_KERNEL_GS_BASE \
121 | CPUMCTX_EXTRN_SYSCALL_MSRS \
122 | CPUMCTX_EXTRN_SYSENTER_MSRS \
123 | CPUMCTX_EXTRN_TSC_AUX \
124 | CPUMCTX_EXTRN_OTHER_MSRS \
125 | CPUMCTX_EXTRN_CR0 \
126 | CPUMCTX_EXTRN_CR3 \
127 | CPUMCTX_EXTRN_CR4 \
128 | CPUMCTX_EXTRN_DR7 \
129 | CPUMCTX_EXTRN_HWVIRT \
130 | CPUMCTX_EXTRN_HM_VMX_MASK)
131
132/**
133 * Exception bitmap mask for real-mode guests (real-on-v86).
134 *
135 * We need to intercept all exceptions manually except:
136 * - \#AC and \#DB are always intercepted to prevent the CPU from deadlocking
137 * due to bugs in Intel CPUs.
138 * - \#PF need not be intercepted even in real-mode if we have nested paging
139 * support.
140 */
141#define HMVMX_REAL_MODE_XCPT_MASK ( RT_BIT(X86_XCPT_DE) /* always: | RT_BIT(X86_XCPT_DB) */ | RT_BIT(X86_XCPT_NMI) \
142 | RT_BIT(X86_XCPT_BP) | RT_BIT(X86_XCPT_OF) | RT_BIT(X86_XCPT_BR) \
143 | RT_BIT(X86_XCPT_UD) | RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_DF) \
144 | RT_BIT(X86_XCPT_CO_SEG_OVERRUN) | RT_BIT(X86_XCPT_TS) | RT_BIT(X86_XCPT_NP) \
145 | RT_BIT(X86_XCPT_SS) | RT_BIT(X86_XCPT_GP) /* RT_BIT(X86_XCPT_PF) */ \
146 | RT_BIT(X86_XCPT_MF) /* always: | RT_BIT(X86_XCPT_AC) */ | RT_BIT(X86_XCPT_MC) \
147 | RT_BIT(X86_XCPT_XF))
148
149/** Maximum VM-instruction error number. */
150#define HMVMX_INSTR_ERROR_MAX 28
151
152/** Profiling macro. */
153#ifdef HM_PROFILE_EXIT_DISPATCH
154# define HMVMX_START_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitDispatch, ed)
155# define HMVMX_STOP_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitDispatch, ed)
156#else
157# define HMVMX_START_EXIT_DISPATCH_PROF() do { } while (0)
158# define HMVMX_STOP_EXIT_DISPATCH_PROF() do { } while (0)
159#endif
160
161/** Assert that preemption is disabled or covered by thread-context hooks. */
162#define HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu) Assert( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
163 || !RTThreadPreemptIsEnabled(NIL_RTTHREAD))
164
165/** Assert that we haven't migrated CPUs when thread-context hooks are not
166 * used. */
167#define HMVMX_ASSERT_CPU_SAFE(a_pVCpu) AssertMsg( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
168 || (a_pVCpu)->hm.s.idEnteredCpu == RTMpCpuId(), \
169 ("Illegal migration! Entered on CPU %u Current %u\n", \
170 (a_pVCpu)->hm.s.idEnteredCpu, RTMpCpuId()))
171
172/** Asserts that the given CPUMCTX_EXTRN_XXX bits are present in the guest-CPU
173 * context. */
174#define HMVMX_CPUMCTX_ASSERT(a_pVCpu, a_fExtrnMbz) AssertMsg(!((a_pVCpu)->cpum.GstCtx.fExtrn & (a_fExtrnMbz)), \
175 ("fExtrn=%#RX64 fExtrnMbz=%#RX64\n", \
176 (a_pVCpu)->cpum.GstCtx.fExtrn, (a_fExtrnMbz)))
177
178/** Log the VM-exit reason with an easily visible marker to identify it in a
179 * potential sea of logging data. */
180#define HMVMX_LOG_EXIT(a_pVCpu, a_uExitReason) \
181 do { \
182 Log4(("VM-exit: vcpu[%RU32] %85s -v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-\n", (a_pVCpu)->idCpu, \
183 HMGetVmxExitName(a_uExitReason))); \
184 } while (0) \
185
186
187/*********************************************************************************************************************************
188* Structures and Typedefs *
189*********************************************************************************************************************************/
190/**
191 * VMX per-VCPU transient state.
192 *
193 * A state structure for holding miscellaneous information across
194 * VMX non-root operation and restored after the transition.
195 */
196typedef struct VMXTRANSIENT
197{
198 /** The host's rflags/eflags. */
199 RTCCUINTREG fEFlags;
200
201 /** The guest's TPR value used for TPR shadowing. */
202 uint8_t u8GuestTpr;
203 /** Alignment. */
204 uint8_t abAlignment0[7];
205
206 /** The basic VM-exit reason. */
207 uint16_t uExitReason;
208 /** Alignment. */
209 uint16_t u16Alignment0;
210 /** The VM-exit interruption error code. */
211 uint32_t uExitIntErrorCode;
212 /** The VM-exit exit code qualification. */
213 uint64_t uExitQual;
214 /** The Guest-linear address. */
215 uint64_t uGuestLinearAddr;
216 /** The Guest-physical address. */
217 uint64_t uGuestPhysicalAddr;
218
219 /** The VM-exit interruption-information field. */
220 uint32_t uExitIntInfo;
221 /** The VM-exit instruction-length field. */
222 uint32_t cbInstr;
223 /** The VM-exit instruction-information field. */
224 VMXEXITINSTRINFO ExitInstrInfo;
225 /** Whether the VM-entry failed or not. */
226 bool fVMEntryFailed;
227 /** Whether we are currently executing a nested-guest. */
228 bool fIsNestedGuest;
229 /** Alignment. */
230 uint8_t abAlignment1[2];
231
232 /** The VM-entry interruption-information field. */
233 uint32_t uEntryIntInfo;
234 /** The VM-entry exception error code field. */
235 uint32_t uEntryXcptErrorCode;
236 /** The VM-entry instruction length field. */
237 uint32_t cbEntryInstr;
238
239 /** IDT-vectoring information field. */
240 uint32_t uIdtVectoringInfo;
241 /** IDT-vectoring error code. */
242 uint32_t uIdtVectoringErrorCode;
243
244 /** Mask of currently read VMCS fields; HMVMX_READ_XXX. */
245 uint32_t fVmcsFieldsRead;
246
247 /** Whether the guest debug state was active at the time of VM-exit. */
248 bool fWasGuestDebugStateActive;
249 /** Whether the hyper debug state was active at the time of VM-exit. */
250 bool fWasHyperDebugStateActive;
251 /** Whether TSC-offsetting and VMX-preemption timer was updated before VM-entry. */
252 bool fUpdatedTscOffsettingAndPreemptTimer;
253 /** Whether the VM-exit was caused by a page-fault during delivery of a
254 * contributory exception or a page-fault. */
255 bool fVectoringDoublePF;
256 /** Whether the VM-exit was caused by a page-fault during delivery of an
257 * external interrupt or NMI. */
258 bool fVectoringPF;
259 /** Whether the TSC_AUX MSR needs to be removed from the auto-load/store MSR
260 * area after VM-exit. */
261 bool fRemoveTscAuxMsr;
262 bool afAlignment0[2];
263
264 /** The VMCS info. object. */
265 PVMXVMCSINFO pVmcsInfo;
266} VMXTRANSIENT;
267AssertCompileMemberAlignment(VMXTRANSIENT, uExitReason, sizeof(uint64_t));
268AssertCompileMemberAlignment(VMXTRANSIENT, uExitIntInfo, sizeof(uint64_t));
269AssertCompileMemberAlignment(VMXTRANSIENT, uEntryIntInfo, sizeof(uint64_t));
270AssertCompileMemberAlignment(VMXTRANSIENT, fWasGuestDebugStateActive, sizeof(uint64_t));
271AssertCompileMemberAlignment(VMXTRANSIENT, pVmcsInfo, sizeof(uint64_t));
272AssertCompileMemberSize(VMXTRANSIENT, ExitInstrInfo, sizeof(uint32_t));
273/** Pointer to VMX transient state. */
274typedef VMXTRANSIENT *PVMXTRANSIENT;
275/** Pointer to a const VMX transient state. */
276typedef const VMXTRANSIENT *PCVMXTRANSIENT;
277
278/**
279 * Memory operand read or write access.
280 */
281typedef enum VMXMEMACCESS
282{
283 VMXMEMACCESS_READ = 0,
284 VMXMEMACCESS_WRITE = 1
285} VMXMEMACCESS;
286
287/**
288 * VMX VM-exit handler.
289 *
290 * @returns Strict VBox status code (i.e. informational status codes too).
291 * @param pVCpu The cross context virtual CPU structure.
292 * @param pVmxTransient The VMX-transient structure.
293 */
294#ifndef HMVMX_USE_FUNCTION_TABLE
295typedef VBOXSTRICTRC FNVMXEXITHANDLER(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
296#else
297typedef DECLCALLBACK(VBOXSTRICTRC) FNVMXEXITHANDLER(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
298/** Pointer to VM-exit handler. */
299typedef FNVMXEXITHANDLER *PFNVMXEXITHANDLER;
300#endif
301
302/**
303 * VMX VM-exit handler, non-strict status code.
304 *
305 * This is generally the same as FNVMXEXITHANDLER, the NSRC bit is just FYI.
306 *
307 * @returns VBox status code, no informational status code returned.
308 * @param pVCpu The cross context virtual CPU structure.
309 * @param pVmxTransient The VMX-transient structure.
310 *
311 * @remarks This is not used on anything returning VERR_EM_INTERPRETER as the
312 * use of that status code will be replaced with VINF_EM_SOMETHING
313 * later when switching over to IEM.
314 */
315#ifndef HMVMX_USE_FUNCTION_TABLE
316typedef int FNVMXEXITHANDLERNSRC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
317#else
318typedef FNVMXEXITHANDLER FNVMXEXITHANDLERNSRC;
319#endif
320
321
322/*********************************************************************************************************************************
323* Internal Functions *
324*********************************************************************************************************************************/
325#ifndef HMVMX_USE_FUNCTION_TABLE
326DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
327# define HMVMX_EXIT_DECL DECLINLINE(VBOXSTRICTRC)
328# define HMVMX_EXIT_NSRC_DECL DECLINLINE(int)
329#else
330# define HMVMX_EXIT_DECL static DECLCALLBACK(VBOXSTRICTRC)
331# define HMVMX_EXIT_NSRC_DECL HMVMX_EXIT_DECL
332#endif
333#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
334DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
335#endif
336
337static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat);
338
339/** @name VM-exit handler prototypes.
340 * @{
341 */
342static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmi;
343static FNVMXEXITHANDLER hmR0VmxExitExtInt;
344static FNVMXEXITHANDLER hmR0VmxExitTripleFault;
345static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindow;
346static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindow;
347static FNVMXEXITHANDLER hmR0VmxExitTaskSwitch;
348static FNVMXEXITHANDLER hmR0VmxExitCpuid;
349static FNVMXEXITHANDLER hmR0VmxExitGetsec;
350static FNVMXEXITHANDLER hmR0VmxExitHlt;
351static FNVMXEXITHANDLERNSRC hmR0VmxExitInvd;
352static FNVMXEXITHANDLER hmR0VmxExitInvlpg;
353static FNVMXEXITHANDLER hmR0VmxExitRdpmc;
354static FNVMXEXITHANDLER hmR0VmxExitVmcall;
355#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
356static FNVMXEXITHANDLER hmR0VmxExitVmclear;
357static FNVMXEXITHANDLER hmR0VmxExitVmlaunch;
358static FNVMXEXITHANDLER hmR0VmxExitVmptrld;
359static FNVMXEXITHANDLER hmR0VmxExitVmptrst;
360static FNVMXEXITHANDLER hmR0VmxExitVmread;
361static FNVMXEXITHANDLER hmR0VmxExitVmresume;
362static FNVMXEXITHANDLER hmR0VmxExitVmwrite;
363static FNVMXEXITHANDLER hmR0VmxExitVmxoff;
364static FNVMXEXITHANDLER hmR0VmxExitVmxon;
365static FNVMXEXITHANDLER hmR0VmxExitInvvpid;
366#endif
367static FNVMXEXITHANDLER hmR0VmxExitRdtsc;
368static FNVMXEXITHANDLER hmR0VmxExitMovCRx;
369static FNVMXEXITHANDLER hmR0VmxExitMovDRx;
370static FNVMXEXITHANDLER hmR0VmxExitIoInstr;
371static FNVMXEXITHANDLER hmR0VmxExitRdmsr;
372static FNVMXEXITHANDLER hmR0VmxExitWrmsr;
373static FNVMXEXITHANDLER hmR0VmxExitMwait;
374static FNVMXEXITHANDLER hmR0VmxExitMtf;
375static FNVMXEXITHANDLER hmR0VmxExitMonitor;
376static FNVMXEXITHANDLER hmR0VmxExitPause;
377static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThreshold;
378static FNVMXEXITHANDLER hmR0VmxExitApicAccess;
379static FNVMXEXITHANDLER hmR0VmxExitEptViolation;
380static FNVMXEXITHANDLER hmR0VmxExitEptMisconfig;
381static FNVMXEXITHANDLER hmR0VmxExitRdtscp;
382static FNVMXEXITHANDLER hmR0VmxExitPreemptTimer;
383static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvd;
384static FNVMXEXITHANDLER hmR0VmxExitXsetbv;
385static FNVMXEXITHANDLER hmR0VmxExitInvpcid;
386static FNVMXEXITHANDLERNSRC hmR0VmxExitSetPendingXcptUD;
387static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestState;
388static FNVMXEXITHANDLERNSRC hmR0VmxExitErrUnexpected;
389/** @} */
390
391#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
392/** @name Nested-guest VM-exit handler prototypes.
393 * @{
394 */
395static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmiNested;
396static FNVMXEXITHANDLER hmR0VmxExitTripleFaultNested;
397static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindowNested;
398static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindowNested;
399static FNVMXEXITHANDLER hmR0VmxExitTaskSwitchNested;
400static FNVMXEXITHANDLER hmR0VmxExitHltNested;
401static FNVMXEXITHANDLER hmR0VmxExitInvlpgNested;
402static FNVMXEXITHANDLER hmR0VmxExitRdpmcNested;
403static FNVMXEXITHANDLER hmR0VmxExitVmreadVmwriteNested;
404static FNVMXEXITHANDLER hmR0VmxExitRdtscNested;
405static FNVMXEXITHANDLER hmR0VmxExitMovCRxNested;
406static FNVMXEXITHANDLER hmR0VmxExitMovDRxNested;
407static FNVMXEXITHANDLER hmR0VmxExitIoInstrNested;
408static FNVMXEXITHANDLER hmR0VmxExitRdmsrNested;
409static FNVMXEXITHANDLER hmR0VmxExitWrmsrNested;
410static FNVMXEXITHANDLER hmR0VmxExitMwaitNested;
411static FNVMXEXITHANDLER hmR0VmxExitMtfNested;
412static FNVMXEXITHANDLER hmR0VmxExitMonitorNested;
413static FNVMXEXITHANDLER hmR0VmxExitPauseNested;
414static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThresholdNested;
415static FNVMXEXITHANDLER hmR0VmxExitApicAccessNested;
416static FNVMXEXITHANDLER hmR0VmxExitApicWriteNested;
417static FNVMXEXITHANDLER hmR0VmxExitVirtEoiNested;
418static FNVMXEXITHANDLER hmR0VmxExitRdtscpNested;
419static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvdNested;
420static FNVMXEXITHANDLER hmR0VmxExitInvpcidNested;
421static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestStateNested;
422static FNVMXEXITHANDLER hmR0VmxExitInstrNested;
423static FNVMXEXITHANDLER hmR0VmxExitInstrWithInfoNested;
424/** @} */
425#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
426
427
428/*********************************************************************************************************************************
429* Global Variables *
430*********************************************************************************************************************************/
431#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
432/**
433 * Array of all VMCS fields.
434 * Any fields added to the VT-x spec. should be added here.
435 *
436 * Currently only used to derive shadow VMCS fields for hardware-assisted execution
437 * of nested-guests.
438 */
439static const uint32_t g_aVmcsFields[] =
440{
441 /* 16-bit control fields. */
442 VMX_VMCS16_VPID,
443 VMX_VMCS16_POSTED_INT_NOTIFY_VECTOR,
444 VMX_VMCS16_EPTP_INDEX,
445
446 /* 16-bit guest-state fields. */
447 VMX_VMCS16_GUEST_ES_SEL,
448 VMX_VMCS16_GUEST_CS_SEL,
449 VMX_VMCS16_GUEST_SS_SEL,
450 VMX_VMCS16_GUEST_DS_SEL,
451 VMX_VMCS16_GUEST_FS_SEL,
452 VMX_VMCS16_GUEST_GS_SEL,
453 VMX_VMCS16_GUEST_LDTR_SEL,
454 VMX_VMCS16_GUEST_TR_SEL,
455 VMX_VMCS16_GUEST_INTR_STATUS,
456 VMX_VMCS16_GUEST_PML_INDEX,
457
458 /* 16-bits host-state fields. */
459 VMX_VMCS16_HOST_ES_SEL,
460 VMX_VMCS16_HOST_CS_SEL,
461 VMX_VMCS16_HOST_SS_SEL,
462 VMX_VMCS16_HOST_DS_SEL,
463 VMX_VMCS16_HOST_FS_SEL,
464 VMX_VMCS16_HOST_GS_SEL,
465 VMX_VMCS16_HOST_TR_SEL,
466
467 /* 64-bit control fields. */
468 VMX_VMCS64_CTRL_IO_BITMAP_A_FULL,
469 VMX_VMCS64_CTRL_IO_BITMAP_A_HIGH,
470 VMX_VMCS64_CTRL_IO_BITMAP_B_FULL,
471 VMX_VMCS64_CTRL_IO_BITMAP_B_HIGH,
472 VMX_VMCS64_CTRL_MSR_BITMAP_FULL,
473 VMX_VMCS64_CTRL_MSR_BITMAP_HIGH,
474 VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL,
475 VMX_VMCS64_CTRL_EXIT_MSR_STORE_HIGH,
476 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL,
477 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_HIGH,
478 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL,
479 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_HIGH,
480 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL,
481 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_HIGH,
482 VMX_VMCS64_CTRL_EXEC_PML_ADDR_FULL,
483 VMX_VMCS64_CTRL_EXEC_PML_ADDR_HIGH,
484 VMX_VMCS64_CTRL_TSC_OFFSET_FULL,
485 VMX_VMCS64_CTRL_TSC_OFFSET_HIGH,
486 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL,
487 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_HIGH,
488 VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL,
489 VMX_VMCS64_CTRL_APIC_ACCESSADDR_HIGH,
490 VMX_VMCS64_CTRL_POSTED_INTR_DESC_FULL,
491 VMX_VMCS64_CTRL_POSTED_INTR_DESC_HIGH,
492 VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL,
493 VMX_VMCS64_CTRL_VMFUNC_CTRLS_HIGH,
494 VMX_VMCS64_CTRL_EPTP_FULL,
495 VMX_VMCS64_CTRL_EPTP_HIGH,
496 VMX_VMCS64_CTRL_EOI_BITMAP_0_FULL,
497 VMX_VMCS64_CTRL_EOI_BITMAP_0_HIGH,
498 VMX_VMCS64_CTRL_EOI_BITMAP_1_FULL,
499 VMX_VMCS64_CTRL_EOI_BITMAP_1_HIGH,
500 VMX_VMCS64_CTRL_EOI_BITMAP_2_FULL,
501 VMX_VMCS64_CTRL_EOI_BITMAP_2_HIGH,
502 VMX_VMCS64_CTRL_EOI_BITMAP_3_FULL,
503 VMX_VMCS64_CTRL_EOI_BITMAP_3_HIGH,
504 VMX_VMCS64_CTRL_EPTP_LIST_FULL,
505 VMX_VMCS64_CTRL_EPTP_LIST_HIGH,
506 VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL,
507 VMX_VMCS64_CTRL_VMREAD_BITMAP_HIGH,
508 VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL,
509 VMX_VMCS64_CTRL_VMWRITE_BITMAP_HIGH,
510 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_FULL,
511 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_HIGH,
512 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_FULL,
513 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_HIGH,
514 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_FULL,
515 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_HIGH,
516 VMX_VMCS64_CTRL_TSC_MULTIPLIER_FULL,
517 VMX_VMCS64_CTRL_TSC_MULTIPLIER_HIGH,
518
519 /* 64-bit read-only data fields. */
520 VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL,
521 VMX_VMCS64_RO_GUEST_PHYS_ADDR_HIGH,
522
523 /* 64-bit guest-state fields. */
524 VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL,
525 VMX_VMCS64_GUEST_VMCS_LINK_PTR_HIGH,
526 VMX_VMCS64_GUEST_DEBUGCTL_FULL,
527 VMX_VMCS64_GUEST_DEBUGCTL_HIGH,
528 VMX_VMCS64_GUEST_PAT_FULL,
529 VMX_VMCS64_GUEST_PAT_HIGH,
530 VMX_VMCS64_GUEST_EFER_FULL,
531 VMX_VMCS64_GUEST_EFER_HIGH,
532 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL,
533 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_HIGH,
534 VMX_VMCS64_GUEST_PDPTE0_FULL,
535 VMX_VMCS64_GUEST_PDPTE0_HIGH,
536 VMX_VMCS64_GUEST_PDPTE1_FULL,
537 VMX_VMCS64_GUEST_PDPTE1_HIGH,
538 VMX_VMCS64_GUEST_PDPTE2_FULL,
539 VMX_VMCS64_GUEST_PDPTE2_HIGH,
540 VMX_VMCS64_GUEST_PDPTE3_FULL,
541 VMX_VMCS64_GUEST_PDPTE3_HIGH,
542 VMX_VMCS64_GUEST_BNDCFGS_FULL,
543 VMX_VMCS64_GUEST_BNDCFGS_HIGH,
544
545 /* 64-bit host-state fields. */
546 VMX_VMCS64_HOST_PAT_FULL,
547 VMX_VMCS64_HOST_PAT_HIGH,
548 VMX_VMCS64_HOST_EFER_FULL,
549 VMX_VMCS64_HOST_EFER_HIGH,
550 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL,
551 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_HIGH,
552
553 /* 32-bit control fields. */
554 VMX_VMCS32_CTRL_PIN_EXEC,
555 VMX_VMCS32_CTRL_PROC_EXEC,
556 VMX_VMCS32_CTRL_EXCEPTION_BITMAP,
557 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK,
558 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH,
559 VMX_VMCS32_CTRL_CR3_TARGET_COUNT,
560 VMX_VMCS32_CTRL_EXIT,
561 VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT,
562 VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT,
563 VMX_VMCS32_CTRL_ENTRY,
564 VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT,
565 VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO,
566 VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE,
567 VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH,
568 VMX_VMCS32_CTRL_TPR_THRESHOLD,
569 VMX_VMCS32_CTRL_PROC_EXEC2,
570 VMX_VMCS32_CTRL_PLE_GAP,
571 VMX_VMCS32_CTRL_PLE_WINDOW,
572
573 /* 32-bits read-only fields. */
574 VMX_VMCS32_RO_VM_INSTR_ERROR,
575 VMX_VMCS32_RO_EXIT_REASON,
576 VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO,
577 VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE,
578 VMX_VMCS32_RO_IDT_VECTORING_INFO,
579 VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE,
580 VMX_VMCS32_RO_EXIT_INSTR_LENGTH,
581 VMX_VMCS32_RO_EXIT_INSTR_INFO,
582
583 /* 32-bit guest-state fields. */
584 VMX_VMCS32_GUEST_ES_LIMIT,
585 VMX_VMCS32_GUEST_CS_LIMIT,
586 VMX_VMCS32_GUEST_SS_LIMIT,
587 VMX_VMCS32_GUEST_DS_LIMIT,
588 VMX_VMCS32_GUEST_FS_LIMIT,
589 VMX_VMCS32_GUEST_GS_LIMIT,
590 VMX_VMCS32_GUEST_LDTR_LIMIT,
591 VMX_VMCS32_GUEST_TR_LIMIT,
592 VMX_VMCS32_GUEST_GDTR_LIMIT,
593 VMX_VMCS32_GUEST_IDTR_LIMIT,
594 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
595 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
596 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
597 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
598 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
599 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS,
600 VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS,
601 VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS,
602 VMX_VMCS32_GUEST_INT_STATE,
603 VMX_VMCS32_GUEST_ACTIVITY_STATE,
604 VMX_VMCS32_GUEST_SMBASE,
605 VMX_VMCS32_GUEST_SYSENTER_CS,
606 VMX_VMCS32_PREEMPT_TIMER_VALUE,
607
608 /* 32-bit host-state fields. */
609 VMX_VMCS32_HOST_SYSENTER_CS,
610
611 /* Natural-width control fields. */
612 VMX_VMCS_CTRL_CR0_MASK,
613 VMX_VMCS_CTRL_CR4_MASK,
614 VMX_VMCS_CTRL_CR0_READ_SHADOW,
615 VMX_VMCS_CTRL_CR4_READ_SHADOW,
616 VMX_VMCS_CTRL_CR3_TARGET_VAL0,
617 VMX_VMCS_CTRL_CR3_TARGET_VAL1,
618 VMX_VMCS_CTRL_CR3_TARGET_VAL2,
619 VMX_VMCS_CTRL_CR3_TARGET_VAL3,
620
621 /* Natural-width read-only data fields. */
622 VMX_VMCS_RO_EXIT_QUALIFICATION,
623 VMX_VMCS_RO_IO_RCX,
624 VMX_VMCS_RO_IO_RSI,
625 VMX_VMCS_RO_IO_RDI,
626 VMX_VMCS_RO_IO_RIP,
627 VMX_VMCS_RO_GUEST_LINEAR_ADDR,
628
629 /* Natural-width guest-state field */
630 VMX_VMCS_GUEST_CR0,
631 VMX_VMCS_GUEST_CR3,
632 VMX_VMCS_GUEST_CR4,
633 VMX_VMCS_GUEST_ES_BASE,
634 VMX_VMCS_GUEST_CS_BASE,
635 VMX_VMCS_GUEST_SS_BASE,
636 VMX_VMCS_GUEST_DS_BASE,
637 VMX_VMCS_GUEST_FS_BASE,
638 VMX_VMCS_GUEST_GS_BASE,
639 VMX_VMCS_GUEST_LDTR_BASE,
640 VMX_VMCS_GUEST_TR_BASE,
641 VMX_VMCS_GUEST_GDTR_BASE,
642 VMX_VMCS_GUEST_IDTR_BASE,
643 VMX_VMCS_GUEST_DR7,
644 VMX_VMCS_GUEST_RSP,
645 VMX_VMCS_GUEST_RIP,
646 VMX_VMCS_GUEST_RFLAGS,
647 VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS,
648 VMX_VMCS_GUEST_SYSENTER_ESP,
649 VMX_VMCS_GUEST_SYSENTER_EIP,
650
651 /* Natural-width host-state fields */
652 VMX_VMCS_HOST_CR0,
653 VMX_VMCS_HOST_CR3,
654 VMX_VMCS_HOST_CR4,
655 VMX_VMCS_HOST_FS_BASE,
656 VMX_VMCS_HOST_GS_BASE,
657 VMX_VMCS_HOST_TR_BASE,
658 VMX_VMCS_HOST_GDTR_BASE,
659 VMX_VMCS_HOST_IDTR_BASE,
660 VMX_VMCS_HOST_SYSENTER_ESP,
661 VMX_VMCS_HOST_SYSENTER_EIP,
662 VMX_VMCS_HOST_RSP,
663 VMX_VMCS_HOST_RIP
664};
665#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
666
667static const uint32_t g_aVmcsSegBase[] =
668{
669 VMX_VMCS_GUEST_ES_BASE,
670 VMX_VMCS_GUEST_CS_BASE,
671 VMX_VMCS_GUEST_SS_BASE,
672 VMX_VMCS_GUEST_DS_BASE,
673 VMX_VMCS_GUEST_FS_BASE,
674 VMX_VMCS_GUEST_GS_BASE
675};
676static const uint32_t g_aVmcsSegSel[] =
677{
678 VMX_VMCS16_GUEST_ES_SEL,
679 VMX_VMCS16_GUEST_CS_SEL,
680 VMX_VMCS16_GUEST_SS_SEL,
681 VMX_VMCS16_GUEST_DS_SEL,
682 VMX_VMCS16_GUEST_FS_SEL,
683 VMX_VMCS16_GUEST_GS_SEL
684};
685static const uint32_t g_aVmcsSegLimit[] =
686{
687 VMX_VMCS32_GUEST_ES_LIMIT,
688 VMX_VMCS32_GUEST_CS_LIMIT,
689 VMX_VMCS32_GUEST_SS_LIMIT,
690 VMX_VMCS32_GUEST_DS_LIMIT,
691 VMX_VMCS32_GUEST_FS_LIMIT,
692 VMX_VMCS32_GUEST_GS_LIMIT
693};
694static const uint32_t g_aVmcsSegAttr[] =
695{
696 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
697 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
698 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
699 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
700 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
701 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS
702};
703AssertCompile(RT_ELEMENTS(g_aVmcsSegSel) == X86_SREG_COUNT);
704AssertCompile(RT_ELEMENTS(g_aVmcsSegLimit) == X86_SREG_COUNT);
705AssertCompile(RT_ELEMENTS(g_aVmcsSegBase) == X86_SREG_COUNT);
706AssertCompile(RT_ELEMENTS(g_aVmcsSegAttr) == X86_SREG_COUNT);
707
708#ifdef HMVMX_USE_FUNCTION_TABLE
709/**
710 * VMX_EXIT dispatch table.
711 */
712static const PFNVMXEXITHANDLER g_apfnVMExitHandlers[VMX_EXIT_MAX + 1] =
713{
714 /* 0 VMX_EXIT_XCPT_OR_NMI */ hmR0VmxExitXcptOrNmi,
715 /* 1 VMX_EXIT_EXT_INT */ hmR0VmxExitExtInt,
716 /* 2 VMX_EXIT_TRIPLE_FAULT */ hmR0VmxExitTripleFault,
717 /* 3 VMX_EXIT_INIT_SIGNAL */ hmR0VmxExitErrUnexpected,
718 /* 4 VMX_EXIT_SIPI */ hmR0VmxExitErrUnexpected,
719 /* 5 VMX_EXIT_IO_SMI */ hmR0VmxExitErrUnexpected,
720 /* 6 VMX_EXIT_SMI */ hmR0VmxExitErrUnexpected,
721 /* 7 VMX_EXIT_INT_WINDOW */ hmR0VmxExitIntWindow,
722 /* 8 VMX_EXIT_NMI_WINDOW */ hmR0VmxExitNmiWindow,
723 /* 9 VMX_EXIT_TASK_SWITCH */ hmR0VmxExitTaskSwitch,
724 /* 10 VMX_EXIT_CPUID */ hmR0VmxExitCpuid,
725 /* 11 VMX_EXIT_GETSEC */ hmR0VmxExitGetsec,
726 /* 12 VMX_EXIT_HLT */ hmR0VmxExitHlt,
727 /* 13 VMX_EXIT_INVD */ hmR0VmxExitInvd,
728 /* 14 VMX_EXIT_INVLPG */ hmR0VmxExitInvlpg,
729 /* 15 VMX_EXIT_RDPMC */ hmR0VmxExitRdpmc,
730 /* 16 VMX_EXIT_RDTSC */ hmR0VmxExitRdtsc,
731 /* 17 VMX_EXIT_RSM */ hmR0VmxExitErrUnexpected,
732 /* 18 VMX_EXIT_VMCALL */ hmR0VmxExitVmcall,
733#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
734 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitVmclear,
735 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitVmlaunch,
736 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitVmptrld,
737 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitVmptrst,
738 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitVmread,
739 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitVmresume,
740 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitVmwrite,
741 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitVmxoff,
742 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitVmxon,
743#else
744 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitSetPendingXcptUD,
745 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitSetPendingXcptUD,
746 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitSetPendingXcptUD,
747 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitSetPendingXcptUD,
748 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitSetPendingXcptUD,
749 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitSetPendingXcptUD,
750 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitSetPendingXcptUD,
751 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitSetPendingXcptUD,
752 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitSetPendingXcptUD,
753#endif
754 /* 28 VMX_EXIT_MOV_CRX */ hmR0VmxExitMovCRx,
755 /* 29 VMX_EXIT_MOV_DRX */ hmR0VmxExitMovDRx,
756 /* 30 VMX_EXIT_IO_INSTR */ hmR0VmxExitIoInstr,
757 /* 31 VMX_EXIT_RDMSR */ hmR0VmxExitRdmsr,
758 /* 32 VMX_EXIT_WRMSR */ hmR0VmxExitWrmsr,
759 /* 33 VMX_EXIT_ERR_INVALID_GUEST_STATE */ hmR0VmxExitErrInvalidGuestState,
760 /* 34 VMX_EXIT_ERR_MSR_LOAD */ hmR0VmxExitErrUnexpected,
761 /* 35 UNDEFINED */ hmR0VmxExitErrUnexpected,
762 /* 36 VMX_EXIT_MWAIT */ hmR0VmxExitMwait,
763 /* 37 VMX_EXIT_MTF */ hmR0VmxExitMtf,
764 /* 38 UNDEFINED */ hmR0VmxExitErrUnexpected,
765 /* 39 VMX_EXIT_MONITOR */ hmR0VmxExitMonitor,
766 /* 40 VMX_EXIT_PAUSE */ hmR0VmxExitPause,
767 /* 41 VMX_EXIT_ERR_MACHINE_CHECK */ hmR0VmxExitErrUnexpected,
768 /* 42 UNDEFINED */ hmR0VmxExitErrUnexpected,
769 /* 43 VMX_EXIT_TPR_BELOW_THRESHOLD */ hmR0VmxExitTprBelowThreshold,
770 /* 44 VMX_EXIT_APIC_ACCESS */ hmR0VmxExitApicAccess,
771 /* 45 VMX_EXIT_VIRTUALIZED_EOI */ hmR0VmxExitErrUnexpected,
772 /* 46 VMX_EXIT_GDTR_IDTR_ACCESS */ hmR0VmxExitErrUnexpected,
773 /* 47 VMX_EXIT_LDTR_TR_ACCESS */ hmR0VmxExitErrUnexpected,
774 /* 48 VMX_EXIT_EPT_VIOLATION */ hmR0VmxExitEptViolation,
775 /* 49 VMX_EXIT_EPT_MISCONFIG */ hmR0VmxExitEptMisconfig,
776 /* 50 VMX_EXIT_INVEPT */ hmR0VmxExitSetPendingXcptUD,
777 /* 51 VMX_EXIT_RDTSCP */ hmR0VmxExitRdtscp,
778 /* 52 VMX_EXIT_PREEMPT_TIMER */ hmR0VmxExitPreemptTimer,
779#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
780 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitInvvpid,
781#else
782 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitSetPendingXcptUD,
783#endif
784 /* 54 VMX_EXIT_WBINVD */ hmR0VmxExitWbinvd,
785 /* 55 VMX_EXIT_XSETBV */ hmR0VmxExitXsetbv,
786 /* 56 VMX_EXIT_APIC_WRITE */ hmR0VmxExitErrUnexpected,
787 /* 57 VMX_EXIT_RDRAND */ hmR0VmxExitErrUnexpected,
788 /* 58 VMX_EXIT_INVPCID */ hmR0VmxExitInvpcid,
789 /* 59 VMX_EXIT_VMFUNC */ hmR0VmxExitErrUnexpected,
790 /* 60 VMX_EXIT_ENCLS */ hmR0VmxExitErrUnexpected,
791 /* 61 VMX_EXIT_RDSEED */ hmR0VmxExitErrUnexpected,
792 /* 62 VMX_EXIT_PML_FULL */ hmR0VmxExitErrUnexpected,
793 /* 63 VMX_EXIT_XSAVES */ hmR0VmxExitErrUnexpected,
794 /* 64 VMX_EXIT_XRSTORS */ hmR0VmxExitErrUnexpected,
795 /* 65 UNDEFINED */ hmR0VmxExitErrUnexpected,
796 /* 66 VMX_EXIT_SPP_EVENT */ hmR0VmxExitErrUnexpected,
797 /* 67 VMX_EXIT_UMWAIT */ hmR0VmxExitErrUnexpected,
798 /* 68 VMX_EXIT_TPAUSE */ hmR0VmxExitErrUnexpected,
799};
800#endif /* HMVMX_USE_FUNCTION_TABLE */
801
802#if defined(VBOX_STRICT) && defined(LOG_ENABLED)
803static const char * const g_apszVmxInstrErrors[HMVMX_INSTR_ERROR_MAX + 1] =
804{
805 /* 0 */ "(Not Used)",
806 /* 1 */ "VMCALL executed in VMX root operation.",
807 /* 2 */ "VMCLEAR with invalid physical address.",
808 /* 3 */ "VMCLEAR with VMXON pointer.",
809 /* 4 */ "VMLAUNCH with non-clear VMCS.",
810 /* 5 */ "VMRESUME with non-launched VMCS.",
811 /* 6 */ "VMRESUME after VMXOFF",
812 /* 7 */ "VM-entry with invalid control fields.",
813 /* 8 */ "VM-entry with invalid host state fields.",
814 /* 9 */ "VMPTRLD with invalid physical address.",
815 /* 10 */ "VMPTRLD with VMXON pointer.",
816 /* 11 */ "VMPTRLD with incorrect revision identifier.",
817 /* 12 */ "VMREAD/VMWRITE from/to unsupported VMCS component.",
818 /* 13 */ "VMWRITE to read-only VMCS component.",
819 /* 14 */ "(Not Used)",
820 /* 15 */ "VMXON executed in VMX root operation.",
821 /* 16 */ "VM-entry with invalid executive-VMCS pointer.",
822 /* 17 */ "VM-entry with non-launched executing VMCS.",
823 /* 18 */ "VM-entry with executive-VMCS pointer not VMXON pointer.",
824 /* 19 */ "VMCALL with non-clear VMCS.",
825 /* 20 */ "VMCALL with invalid VM-exit control fields.",
826 /* 21 */ "(Not Used)",
827 /* 22 */ "VMCALL with incorrect MSEG revision identifier.",
828 /* 23 */ "VMXOFF under dual monitor treatment of SMIs and SMM.",
829 /* 24 */ "VMCALL with invalid SMM-monitor features.",
830 /* 25 */ "VM-entry with invalid VM-execution control fields in executive VMCS.",
831 /* 26 */ "VM-entry with events blocked by MOV SS.",
832 /* 27 */ "(Not Used)",
833 /* 28 */ "Invalid operand to INVEPT/INVVPID."
834};
835#endif /* VBOX_STRICT && LOG_ENABLED */
836
837
838/**
839 * Get the CR0 guest/host mask that does not change through the lifetime of a VM.
840 *
841 * Any bit set in this mask is owned by the host/hypervisor and would cause a
842 * VM-exit when modified by the guest.
843 *
844 * @returns The static CR0 guest/host mask.
845 * @param pVCpu The cross context virtual CPU structure.
846 */
847DECL_FORCE_INLINE(uint64_t) hmR0VmxGetFixedCr0Mask(PCVMCPUCC pVCpu)
848{
849 /*
850 * Modifications to CR0 bits that VT-x ignores saving/restoring (CD, ET, NW) and
851 * to CR0 bits that we require for shadow paging (PG) by the guest must cause VM-exits.
852 */
853 /** @todo Avoid intercepting CR0.PE with unrestricted guest execution. Fix PGM
854 * enmGuestMode to be in-sync with the current mode. See @bugref{6398}
855 * and @bugref{6944}. */
856 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
857 return ( X86_CR0_PE
858 | X86_CR0_NE
859 | (pVM->hm.s.fNestedPaging ? 0 : X86_CR0_WP)
860 | X86_CR0_PG
861 | X86_CR0_ET /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.ET */
862 | X86_CR0_CD /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.CD */
863 | X86_CR0_NW); /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.NW */
864}
865
866
867/**
868 * Gets the CR4 guest/host mask that does not change through the lifetime of a VM.
869 *
870 * Any bit set in this mask is owned by the host/hypervisor and would cause a
871 * VM-exit when modified by the guest.
872 *
873 * @returns The static CR4 guest/host mask.
874 * @param pVCpu The cross context virtual CPU structure.
875 */
876DECL_FORCE_INLINE(uint64_t) hmR0VmxGetFixedCr4Mask(PCVMCPUCC pVCpu)
877{
878 /*
879 * We need to look at the host features here (for e.g. OSXSAVE, PCID) because
880 * these bits are reserved on hardware that does not support them. Since the
881 * CPU cannot refer to our virtual CPUID, we need to intercept CR4 changes to
882 * these bits and handle it depending on whether we expose them to the guest.
883 */
884 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
885 bool const fXSaveRstor = pVM->cpum.ro.HostFeatures.fXSaveRstor;
886 bool const fPcid = pVM->cpum.ro.HostFeatures.fPcid;
887 return ( X86_CR4_VMXE
888 | X86_CR4_VME
889 | X86_CR4_PAE
890 | X86_CR4_PGE
891 | X86_CR4_PSE
892 | (fXSaveRstor ? X86_CR4_OSXSAVE : 0)
893 | (fPcid ? X86_CR4_PCIDE : 0));
894}
895
896
897/**
898 * Returns whether the the VM-exit MSR-store area differs from the VM-exit MSR-load
899 * area.
900 *
901 * @returns @c true if it's different, @c false otherwise.
902 * @param pVmcsInfo The VMCS info. object.
903 */
904DECL_FORCE_INLINE(bool) hmR0VmxIsSeparateExitMsrStoreAreaVmcs(PCVMXVMCSINFO pVmcsInfo)
905{
906 return RT_BOOL( pVmcsInfo->pvGuestMsrStore != pVmcsInfo->pvGuestMsrLoad
907 && pVmcsInfo->pvGuestMsrStore);
908}
909
910
911/**
912 * Sets the given Processor-based VM-execution controls.
913 *
914 * @param pVmxTransient The VMX-transient structure.
915 * @param uProcCtls The Processor-based VM-execution controls to set.
916 */
917static void hmR0VmxSetProcCtlsVmcs(PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
918{
919 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
920 if ((pVmcsInfo->u32ProcCtls & uProcCtls) != uProcCtls)
921 {
922 pVmcsInfo->u32ProcCtls |= uProcCtls;
923 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
924 AssertRC(rc);
925 }
926}
927
928
929/**
930 * Removes the given Processor-based VM-execution controls.
931 *
932 * @param pVCpu The cross context virtual CPU structure.
933 * @param pVmxTransient The VMX-transient structure.
934 * @param uProcCtls The Processor-based VM-execution controls to remove.
935 *
936 * @remarks When executing a nested-guest, this will not remove any of the specified
937 * controls if the guest hypervisor has set any one of them.
938 */
939static void hmR0VmxRemoveProcCtlsVmcs(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
940{
941 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
942 if (pVmcsInfo->u32ProcCtls & uProcCtls)
943 {
944#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
945 bool const fRemoveCtls = !pVmxTransient->fIsNestedGuest
946 ? true
947 : !CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uProcCtls);
948#else
949 NOREF(pVCpu);
950 bool const fRemoveCtls = true;
951#endif
952 if (fRemoveCtls)
953 {
954 pVmcsInfo->u32ProcCtls &= ~uProcCtls;
955 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
956 AssertRC(rc);
957 }
958 }
959}
960
961
962/**
963 * Sets the TSC offset for the current VMCS.
964 *
965 * @param uTscOffset The TSC offset to set.
966 * @param pVmcsInfo The VMCS info. object.
967 */
968static void hmR0VmxSetTscOffsetVmcs(PVMXVMCSINFO pVmcsInfo, uint64_t uTscOffset)
969{
970 if (pVmcsInfo->u64TscOffset != uTscOffset)
971 {
972 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, uTscOffset);
973 AssertRC(rc);
974 pVmcsInfo->u64TscOffset = uTscOffset;
975 }
976}
977
978
979/**
980 * Adds one or more exceptions to the exception bitmap and commits it to the current
981 * VMCS.
982 *
983 * @param pVmxTransient The VMX-transient structure.
984 * @param uXcptMask The exception(s) to add.
985 */
986static void hmR0VmxAddXcptInterceptMask(PVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
987{
988 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
989 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
990 if ((uXcptBitmap & uXcptMask) != uXcptMask)
991 {
992 uXcptBitmap |= uXcptMask;
993 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
994 AssertRC(rc);
995 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
996 }
997}
998
999
1000/**
1001 * Adds an exception to the exception bitmap and commits it to the current VMCS.
1002 *
1003 * @param pVmxTransient The VMX-transient structure.
1004 * @param uXcpt The exception to add.
1005 */
1006static void hmR0VmxAddXcptIntercept(PVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1007{
1008 Assert(uXcpt <= X86_XCPT_LAST);
1009 hmR0VmxAddXcptInterceptMask(pVmxTransient, RT_BIT_32(uXcpt));
1010}
1011
1012
1013/**
1014 * Remove one or more exceptions from the exception bitmap and commits it to the
1015 * current VMCS.
1016 *
1017 * This takes care of not removing the exception intercept if a nested-guest
1018 * requires the exception to be intercepted.
1019 *
1020 * @returns VBox status code.
1021 * @param pVCpu The cross context virtual CPU structure.
1022 * @param pVmxTransient The VMX-transient structure.
1023 * @param uXcptMask The exception(s) to remove.
1024 */
1025static int hmR0VmxRemoveXcptInterceptMask(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1026{
1027 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1028 uint32_t u32XcptBitmap = pVmcsInfo->u32XcptBitmap;
1029 if (u32XcptBitmap & uXcptMask)
1030 {
1031#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1032 if (!pVmxTransient->fIsNestedGuest)
1033 { /* likely */ }
1034 else
1035 {
1036 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
1037 uXcptMask &= ~pVmcsNstGst->u32XcptBitmap;
1038 }
1039#endif
1040#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
1041 uXcptMask &= ~( RT_BIT(X86_XCPT_BP)
1042 | RT_BIT(X86_XCPT_DE)
1043 | RT_BIT(X86_XCPT_NM)
1044 | RT_BIT(X86_XCPT_TS)
1045 | RT_BIT(X86_XCPT_UD)
1046 | RT_BIT(X86_XCPT_NP)
1047 | RT_BIT(X86_XCPT_SS)
1048 | RT_BIT(X86_XCPT_GP)
1049 | RT_BIT(X86_XCPT_PF)
1050 | RT_BIT(X86_XCPT_MF));
1051#elif defined(HMVMX_ALWAYS_TRAP_PF)
1052 uXcptMask &= ~RT_BIT(X86_XCPT_PF);
1053#endif
1054 if (uXcptMask)
1055 {
1056 /* Validate we are not removing any essential exception intercepts. */
1057 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || !(uXcptMask & RT_BIT(X86_XCPT_PF)));
1058 NOREF(pVCpu);
1059 Assert(!(uXcptMask & RT_BIT(X86_XCPT_DB)));
1060 Assert(!(uXcptMask & RT_BIT(X86_XCPT_AC)));
1061
1062 /* Remove it from the exception bitmap. */
1063 u32XcptBitmap &= ~uXcptMask;
1064
1065 /* Commit and update the cache if necessary. */
1066 if (pVmcsInfo->u32XcptBitmap != u32XcptBitmap)
1067 {
1068 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
1069 AssertRC(rc);
1070 pVmcsInfo->u32XcptBitmap = u32XcptBitmap;
1071 }
1072 }
1073 }
1074 return VINF_SUCCESS;
1075}
1076
1077
1078/**
1079 * Remove an exceptions from the exception bitmap and commits it to the current
1080 * VMCS.
1081 *
1082 * @returns VBox status code.
1083 * @param pVCpu The cross context virtual CPU structure.
1084 * @param pVmxTransient The VMX-transient structure.
1085 * @param uXcpt The exception to remove.
1086 */
1087static int hmR0VmxRemoveXcptIntercept(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1088{
1089 return hmR0VmxRemoveXcptInterceptMask(pVCpu, pVmxTransient, RT_BIT(uXcpt));
1090}
1091
1092
1093/**
1094 * Loads the VMCS specified by the VMCS info. object.
1095 *
1096 * @returns VBox status code.
1097 * @param pVmcsInfo The VMCS info. object.
1098 *
1099 * @remarks Can be called with interrupts disabled.
1100 */
1101static int hmR0VmxLoadVmcs(PVMXVMCSINFO pVmcsInfo)
1102{
1103 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1104 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1105
1106 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysVmcs);
1107 if (RT_SUCCESS(rc))
1108 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1109 return rc;
1110}
1111
1112
1113/**
1114 * Clears the VMCS specified by the VMCS info. object.
1115 *
1116 * @returns VBox status code.
1117 * @param pVmcsInfo The VMCS info. object.
1118 *
1119 * @remarks Can be called with interrupts disabled.
1120 */
1121static int hmR0VmxClearVmcs(PVMXVMCSINFO pVmcsInfo)
1122{
1123 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1124 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1125
1126 int rc = VMXClearVmcs(pVmcsInfo->HCPhysVmcs);
1127 if (RT_SUCCESS(rc))
1128 pVmcsInfo->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1129 return rc;
1130}
1131
1132
1133#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1134/**
1135 * Loads the shadow VMCS specified by the VMCS info. object.
1136 *
1137 * @returns VBox status code.
1138 * @param pVmcsInfo The VMCS info. object.
1139 *
1140 * @remarks Can be called with interrupts disabled.
1141 */
1142static int hmR0VmxLoadShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1143{
1144 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1145 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1146
1147 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysShadowVmcs);
1148 if (RT_SUCCESS(rc))
1149 pVmcsInfo->fShadowVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1150 return rc;
1151}
1152
1153
1154/**
1155 * Clears the shadow VMCS specified by the VMCS info. object.
1156 *
1157 * @returns VBox status code.
1158 * @param pVmcsInfo The VMCS info. object.
1159 *
1160 * @remarks Can be called with interrupts disabled.
1161 */
1162static int hmR0VmxClearShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1163{
1164 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1165 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1166
1167 int rc = VMXClearVmcs(pVmcsInfo->HCPhysShadowVmcs);
1168 if (RT_SUCCESS(rc))
1169 pVmcsInfo->fShadowVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1170 return rc;
1171}
1172
1173
1174/**
1175 * Switches from and to the specified VMCSes.
1176 *
1177 * @returns VBox status code.
1178 * @param pVmcsInfoFrom The VMCS info. object we are switching from.
1179 * @param pVmcsInfoTo The VMCS info. object we are switching to.
1180 *
1181 * @remarks Called with interrupts disabled.
1182 */
1183static int hmR0VmxSwitchVmcs(PVMXVMCSINFO pVmcsInfoFrom, PVMXVMCSINFO pVmcsInfoTo)
1184{
1185 /*
1186 * Clear the VMCS we are switching out if it has not already been cleared.
1187 * This will sync any CPU internal data back to the VMCS.
1188 */
1189 if (pVmcsInfoFrom->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1190 {
1191 int rc = hmR0VmxClearVmcs(pVmcsInfoFrom);
1192 if (RT_SUCCESS(rc))
1193 {
1194 /*
1195 * The shadow VMCS, if any, would not be active at this point since we
1196 * would have cleared it while importing the virtual hardware-virtualization
1197 * state as part the VMLAUNCH/VMRESUME VM-exit. Hence, there's no need to
1198 * clear the shadow VMCS here, just assert for safety.
1199 */
1200 Assert(!pVmcsInfoFrom->pvShadowVmcs || pVmcsInfoFrom->fShadowVmcsState == VMX_V_VMCS_LAUNCH_STATE_CLEAR);
1201 }
1202 else
1203 return rc;
1204 }
1205
1206 /*
1207 * Clear the VMCS we are switching to if it has not already been cleared.
1208 * This will initialize the VMCS launch state to "clear" required for loading it.
1209 *
1210 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
1211 */
1212 if (pVmcsInfoTo->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1213 {
1214 int rc = hmR0VmxClearVmcs(pVmcsInfoTo);
1215 if (RT_SUCCESS(rc))
1216 { /* likely */ }
1217 else
1218 return rc;
1219 }
1220
1221 /*
1222 * Finally, load the VMCS we are switching to.
1223 */
1224 return hmR0VmxLoadVmcs(pVmcsInfoTo);
1225}
1226
1227
1228/**
1229 * Switches between the guest VMCS and the nested-guest VMCS as specified by the
1230 * caller.
1231 *
1232 * @returns VBox status code.
1233 * @param pVCpu The cross context virtual CPU structure.
1234 * @param fSwitchToNstGstVmcs Whether to switch to the nested-guest VMCS (pass
1235 * true) or guest VMCS (pass false).
1236 */
1237static int hmR0VmxSwitchToGstOrNstGstVmcs(PVMCPUCC pVCpu, bool fSwitchToNstGstVmcs)
1238{
1239 /* Ensure we have synced everything from the guest-CPU context to the VMCS before switching. */
1240 HMVMX_CPUMCTX_ASSERT(pVCpu, HMVMX_CPUMCTX_EXTRN_ALL);
1241
1242 PVMXVMCSINFO pVmcsInfoFrom;
1243 PVMXVMCSINFO pVmcsInfoTo;
1244 if (fSwitchToNstGstVmcs)
1245 {
1246 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfo;
1247 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1248 }
1249 else
1250 {
1251 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1252 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfo;
1253 }
1254
1255 /*
1256 * Disable interrupts to prevent being preempted while we switch the current VMCS as the
1257 * preemption hook code path acquires the current VMCS.
1258 */
1259 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1260
1261 int rc = hmR0VmxSwitchVmcs(pVmcsInfoFrom, pVmcsInfoTo);
1262 if (RT_SUCCESS(rc))
1263 {
1264 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fSwitchToNstGstVmcs;
1265
1266 /*
1267 * If we are switching to a VMCS that was executed on a different host CPU or was
1268 * never executed before, flag that we need to export the host state before executing
1269 * guest/nested-guest code using hardware-assisted VMX.
1270 *
1271 * This could probably be done in a preemptible context since the preemption hook
1272 * will flag the necessary change in host context. However, since preemption is
1273 * already disabled and to avoid making assumptions about host specific code in
1274 * RTMpCpuId when called with preemption enabled, we'll do this while preemption is
1275 * disabled.
1276 */
1277 if (pVmcsInfoTo->idHostCpu == RTMpCpuId())
1278 { /* likely */ }
1279 else
1280 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE);
1281
1282 ASMSetFlags(fEFlags);
1283
1284 /*
1285 * We use a different VM-exit MSR-store areas for the guest and nested-guest. Hence,
1286 * flag that we need to update the host MSR values there. Even if we decide in the
1287 * future to share the VM-exit MSR-store area page between the guest and nested-guest,
1288 * if its content differs, we would have to update the host MSRs anyway.
1289 */
1290 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
1291 }
1292 else
1293 ASMSetFlags(fEFlags);
1294 return rc;
1295}
1296#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
1297
1298
1299/**
1300 * Updates the VM's last error record.
1301 *
1302 * If there was a VMX instruction error, reads the error data from the VMCS and
1303 * updates VCPU's last error record as well.
1304 *
1305 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
1306 * Can be NULL if @a rc is not VERR_VMX_UNABLE_TO_START_VM or
1307 * VERR_VMX_INVALID_VMCS_FIELD.
1308 * @param rc The error code.
1309 */
1310static void hmR0VmxUpdateErrorRecord(PVMCPUCC pVCpu, int rc)
1311{
1312 if ( rc == VERR_VMX_INVALID_VMCS_FIELD
1313 || rc == VERR_VMX_UNABLE_TO_START_VM)
1314 {
1315 AssertPtrReturnVoid(pVCpu);
1316 VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
1317 }
1318 pVCpu->CTX_SUFF(pVM)->hm.s.rcInit = rc;
1319}
1320
1321
1322#ifdef VBOX_STRICT
1323/**
1324 * Reads the VM-entry interruption-information field from the VMCS into the VMX
1325 * transient structure.
1326 *
1327 * @param pVmxTransient The VMX-transient structure.
1328 */
1329DECLINLINE(void) hmR0VmxReadEntryIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1330{
1331 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &pVmxTransient->uEntryIntInfo);
1332 AssertRC(rc);
1333}
1334
1335
1336/**
1337 * Reads the VM-entry exception error code field from the VMCS into
1338 * the VMX transient structure.
1339 *
1340 * @param pVmxTransient The VMX-transient structure.
1341 */
1342DECLINLINE(void) hmR0VmxReadEntryXcptErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1343{
1344 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &pVmxTransient->uEntryXcptErrorCode);
1345 AssertRC(rc);
1346}
1347
1348
1349/**
1350 * Reads the VM-entry exception error code field from the VMCS into
1351 * the VMX transient structure.
1352 *
1353 * @param pVmxTransient The VMX-transient structure.
1354 */
1355DECLINLINE(void) hmR0VmxReadEntryInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1356{
1357 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &pVmxTransient->cbEntryInstr);
1358 AssertRC(rc);
1359}
1360#endif /* VBOX_STRICT */
1361
1362
1363/**
1364 * Reads the VM-exit interruption-information field from the VMCS into the VMX
1365 * transient structure.
1366 *
1367 * @param pVmxTransient The VMX-transient structure.
1368 */
1369DECLINLINE(void) hmR0VmxReadExitIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1370{
1371 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_INFO))
1372 {
1373 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1374 AssertRC(rc);
1375 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_INFO;
1376 }
1377}
1378
1379
1380/**
1381 * Reads the VM-exit interruption error code from the VMCS into the VMX
1382 * transient structure.
1383 *
1384 * @param pVmxTransient The VMX-transient structure.
1385 */
1386DECLINLINE(void) hmR0VmxReadExitIntErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1387{
1388 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE))
1389 {
1390 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1391 AssertRC(rc);
1392 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE;
1393 }
1394}
1395
1396
1397/**
1398 * Reads the VM-exit instruction length field from the VMCS into the VMX
1399 * transient structure.
1400 *
1401 * @param pVmxTransient The VMX-transient structure.
1402 */
1403DECLINLINE(void) hmR0VmxReadExitInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1404{
1405 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_LEN))
1406 {
1407 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbInstr);
1408 AssertRC(rc);
1409 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_LEN;
1410 }
1411}
1412
1413
1414/**
1415 * Reads the VM-exit instruction-information field from the VMCS into
1416 * the VMX transient structure.
1417 *
1418 * @param pVmxTransient The VMX-transient structure.
1419 */
1420DECLINLINE(void) hmR0VmxReadExitInstrInfoVmcs(PVMXTRANSIENT pVmxTransient)
1421{
1422 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_INFO))
1423 {
1424 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1425 AssertRC(rc);
1426 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_INFO;
1427 }
1428}
1429
1430
1431/**
1432 * Reads the Exit Qualification from the VMCS into the VMX transient structure.
1433 *
1434 * @param pVmxTransient The VMX-transient structure.
1435 */
1436DECLINLINE(void) hmR0VmxReadExitQualVmcs(PVMXTRANSIENT pVmxTransient)
1437{
1438 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_QUALIFICATION))
1439 {
1440 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1441 AssertRC(rc);
1442 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION;
1443 }
1444}
1445
1446
1447/**
1448 * Reads the Guest-linear address from the VMCS into the VMX transient structure.
1449 *
1450 * @param pVmxTransient The VMX-transient structure.
1451 */
1452DECLINLINE(void) hmR0VmxReadGuestLinearAddrVmcs(PVMXTRANSIENT pVmxTransient)
1453{
1454 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_LINEAR_ADDR))
1455 {
1456 int rc = VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1457 AssertRC(rc);
1458 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_LINEAR_ADDR;
1459 }
1460}
1461
1462
1463/**
1464 * Reads the Guest-physical address from the VMCS into the VMX transient structure.
1465 *
1466 * @param pVmxTransient The VMX-transient structure.
1467 */
1468DECLINLINE(void) hmR0VmxReadGuestPhysicalAddrVmcs(PVMXTRANSIENT pVmxTransient)
1469{
1470 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PHYSICAL_ADDR))
1471 {
1472 int rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1473 AssertRC(rc);
1474 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PHYSICAL_ADDR;
1475 }
1476}
1477
1478
1479/**
1480 * Reads the IDT-vectoring information field from the VMCS into the VMX
1481 * transient structure.
1482 *
1483 * @param pVmxTransient The VMX-transient structure.
1484 *
1485 * @remarks No-long-jump zone!!!
1486 */
1487DECLINLINE(void) hmR0VmxReadIdtVectoringInfoVmcs(PVMXTRANSIENT pVmxTransient)
1488{
1489 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_INFO))
1490 {
1491 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1492 AssertRC(rc);
1493 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_INFO;
1494 }
1495}
1496
1497
1498/**
1499 * Reads the IDT-vectoring error code from the VMCS into the VMX
1500 * transient structure.
1501 *
1502 * @param pVmxTransient The VMX-transient structure.
1503 */
1504DECLINLINE(void) hmR0VmxReadIdtVectoringErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1505{
1506 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_ERROR_CODE))
1507 {
1508 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1509 AssertRC(rc);
1510 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_ERROR_CODE;
1511 }
1512}
1513
1514#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
1515/**
1516 * Reads all relevant read-only VMCS fields into the VMX transient structure.
1517 *
1518 * @param pVmxTransient The VMX-transient structure.
1519 */
1520static void hmR0VmxReadAllRoFieldsVmcs(PVMXTRANSIENT pVmxTransient)
1521{
1522 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1523 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbInstr);
1524 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1525 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1526 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1527 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1528 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1529 rc |= VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1530 rc |= VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1531 AssertRC(rc);
1532 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION
1533 | HMVMX_READ_EXIT_INSTR_LEN
1534 | HMVMX_READ_EXIT_INSTR_INFO
1535 | HMVMX_READ_IDT_VECTORING_INFO
1536 | HMVMX_READ_IDT_VECTORING_ERROR_CODE
1537 | HMVMX_READ_EXIT_INTERRUPTION_INFO
1538 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
1539 | HMVMX_READ_GUEST_LINEAR_ADDR
1540 | HMVMX_READ_GUEST_PHYSICAL_ADDR;
1541}
1542#endif
1543
1544/**
1545 * Enters VMX root mode operation on the current CPU.
1546 *
1547 * @returns VBox status code.
1548 * @param pVM The cross context VM structure. Can be
1549 * NULL, after a resume.
1550 * @param HCPhysCpuPage Physical address of the VMXON region.
1551 * @param pvCpuPage Pointer to the VMXON region.
1552 */
1553static int hmR0VmxEnterRootMode(PVMCC pVM, RTHCPHYS HCPhysCpuPage, void *pvCpuPage)
1554{
1555 Assert(HCPhysCpuPage && HCPhysCpuPage != NIL_RTHCPHYS);
1556 Assert(RT_ALIGN_T(HCPhysCpuPage, _4K, RTHCPHYS) == HCPhysCpuPage);
1557 Assert(pvCpuPage);
1558 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1559
1560 if (pVM)
1561 {
1562 /* Write the VMCS revision identifier to the VMXON region. */
1563 *(uint32_t *)pvCpuPage = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
1564 }
1565
1566 /* Paranoid: Disable interrupts as, in theory, interrupt handlers might mess with CR4. */
1567 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1568
1569 /* Enable the VMX bit in CR4 if necessary. */
1570 RTCCUINTREG const uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
1571
1572 /* Enter VMX root mode. */
1573 int rc = VMXEnable(HCPhysCpuPage);
1574 if (RT_FAILURE(rc))
1575 {
1576 if (!(uOldCr4 & X86_CR4_VMXE))
1577 SUPR0ChangeCR4(0 /* fOrMask */, ~X86_CR4_VMXE);
1578
1579 if (pVM)
1580 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
1581 }
1582
1583 /* Restore interrupts. */
1584 ASMSetFlags(fEFlags);
1585 return rc;
1586}
1587
1588
1589/**
1590 * Exits VMX root mode operation on the current CPU.
1591 *
1592 * @returns VBox status code.
1593 */
1594static int hmR0VmxLeaveRootMode(void)
1595{
1596 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1597
1598 /* Paranoid: Disable interrupts as, in theory, interrupts handlers might mess with CR4. */
1599 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1600
1601 /* If we're for some reason not in VMX root mode, then don't leave it. */
1602 RTCCUINTREG const uHostCr4 = ASMGetCR4();
1603
1604 int rc;
1605 if (uHostCr4 & X86_CR4_VMXE)
1606 {
1607 /* Exit VMX root mode and clear the VMX bit in CR4. */
1608 VMXDisable();
1609 SUPR0ChangeCR4(0 /* fOrMask */, ~X86_CR4_VMXE);
1610 rc = VINF_SUCCESS;
1611 }
1612 else
1613 rc = VERR_VMX_NOT_IN_VMX_ROOT_MODE;
1614
1615 /* Restore interrupts. */
1616 ASMSetFlags(fEFlags);
1617 return rc;
1618}
1619
1620
1621/**
1622 * Allocates and maps a physically contiguous page. The allocated page is
1623 * zero'd out (used by various VT-x structures).
1624 *
1625 * @returns IPRT status code.
1626 * @param pMemObj Pointer to the ring-0 memory object.
1627 * @param ppVirt Where to store the virtual address of the allocation.
1628 * @param pHCPhys Where to store the physical address of the allocation.
1629 */
1630static int hmR0VmxPageAllocZ(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1631{
1632 AssertPtr(pMemObj);
1633 AssertPtr(ppVirt);
1634 AssertPtr(pHCPhys);
1635 int rc = RTR0MemObjAllocCont(pMemObj, X86_PAGE_4K_SIZE, false /* fExecutable */);
1636 if (RT_FAILURE(rc))
1637 return rc;
1638 *ppVirt = RTR0MemObjAddress(*pMemObj);
1639 *pHCPhys = RTR0MemObjGetPagePhysAddr(*pMemObj, 0 /* iPage */);
1640 ASMMemZero32(*ppVirt, X86_PAGE_4K_SIZE);
1641 return VINF_SUCCESS;
1642}
1643
1644
1645/**
1646 * Frees and unmaps an allocated, physical page.
1647 *
1648 * @param pMemObj Pointer to the ring-0 memory object.
1649 * @param ppVirt Where to re-initialize the virtual address of allocation as
1650 * 0.
1651 * @param pHCPhys Where to re-initialize the physical address of the
1652 * allocation as 0.
1653 */
1654static void hmR0VmxPageFree(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1655{
1656 AssertPtr(pMemObj);
1657 AssertPtr(ppVirt);
1658 AssertPtr(pHCPhys);
1659 /* NULL is valid, accepted and ignored by the free function below. */
1660 RTR0MemObjFree(*pMemObj, true /* fFreeMappings */);
1661 *pMemObj = NIL_RTR0MEMOBJ;
1662 *ppVirt = NULL;
1663 *pHCPhys = NIL_RTHCPHYS;
1664}
1665
1666
1667/**
1668 * Initializes a VMCS info. object.
1669 *
1670 * @param pVmcsInfo The VMCS info. object.
1671 */
1672static void hmR0VmxInitVmcsInfo(PVMXVMCSINFO pVmcsInfo)
1673{
1674 memset(pVmcsInfo, 0, sizeof(*pVmcsInfo));
1675
1676 Assert(pVmcsInfo->hMemObjVmcs == NIL_RTR0MEMOBJ);
1677 Assert(pVmcsInfo->hMemObjShadowVmcs == NIL_RTR0MEMOBJ);
1678 Assert(pVmcsInfo->hMemObjMsrBitmap == NIL_RTR0MEMOBJ);
1679 Assert(pVmcsInfo->hMemObjGuestMsrLoad == NIL_RTR0MEMOBJ);
1680 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1681 Assert(pVmcsInfo->hMemObjHostMsrLoad == NIL_RTR0MEMOBJ);
1682 pVmcsInfo->HCPhysVmcs = NIL_RTHCPHYS;
1683 pVmcsInfo->HCPhysShadowVmcs = NIL_RTHCPHYS;
1684 pVmcsInfo->HCPhysMsrBitmap = NIL_RTHCPHYS;
1685 pVmcsInfo->HCPhysGuestMsrLoad = NIL_RTHCPHYS;
1686 pVmcsInfo->HCPhysGuestMsrStore = NIL_RTHCPHYS;
1687 pVmcsInfo->HCPhysHostMsrLoad = NIL_RTHCPHYS;
1688 pVmcsInfo->HCPhysVirtApic = NIL_RTHCPHYS;
1689 pVmcsInfo->HCPhysEPTP = NIL_RTHCPHYS;
1690 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
1691 pVmcsInfo->idHostCpu = NIL_RTCPUID;
1692}
1693
1694
1695/**
1696 * Frees the VT-x structures for a VMCS info. object.
1697 *
1698 * @param pVM The cross context VM structure.
1699 * @param pVmcsInfo The VMCS info. object.
1700 */
1701static void hmR0VmxFreeVmcsInfo(PVMCC pVM, PVMXVMCSINFO pVmcsInfo)
1702{
1703 hmR0VmxPageFree(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1704
1705#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1706 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1707 hmR0VmxPageFree(&pVmcsInfo->hMemObjShadowVmcs, &pVmcsInfo->pvShadowVmcs, &pVmcsInfo->HCPhysShadowVmcs);
1708#endif
1709
1710 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1711 hmR0VmxPageFree(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1712
1713 hmR0VmxPageFree(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad, &pVmcsInfo->HCPhysHostMsrLoad);
1714 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad, &pVmcsInfo->HCPhysGuestMsrLoad);
1715 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrStore, &pVmcsInfo->pvGuestMsrStore, &pVmcsInfo->HCPhysGuestMsrStore);
1716
1717 hmR0VmxInitVmcsInfo(pVmcsInfo);
1718}
1719
1720
1721/**
1722 * Allocates the VT-x structures for a VMCS info. object.
1723 *
1724 * @returns VBox status code.
1725 * @param pVCpu The cross context virtual CPU structure.
1726 * @param pVmcsInfo The VMCS info. object.
1727 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
1728 */
1729static int hmR0VmxAllocVmcsInfo(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
1730{
1731 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
1732
1733 /* Allocate the guest VM control structure (VMCS). */
1734 int rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1735 if (RT_SUCCESS(rc))
1736 {
1737 if (!fIsNstGstVmcs)
1738 {
1739#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1740 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1741 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjShadowVmcs, &pVmcsInfo->pvShadowVmcs, &pVmcsInfo->HCPhysShadowVmcs);
1742#endif
1743 if (RT_SUCCESS(rc))
1744 {
1745 /* Get the allocated virtual-APIC page from the virtual APIC device. */
1746 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
1747 && (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW))
1748 rc = APICGetApicPageForCpu(pVCpu, &pVmcsInfo->HCPhysVirtApic, (PRTR0PTR)&pVmcsInfo->pbVirtApic, NULL /*pR3Ptr*/);
1749 }
1750 }
1751 else
1752 {
1753 /* We don't yet support exposing VMCS shadowing to the guest. */
1754 Assert(pVmcsInfo->HCPhysShadowVmcs == NIL_RTHCPHYS);
1755 Assert(!pVmcsInfo->pvShadowVmcs);
1756
1757 /* Get the allocated virtual-APIC page from CPUM. */
1758 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
1759 {
1760 /** @todo NSTVMX: Get rid of this. There is no need to allocate a separate HC
1761 * page for this. Use the one provided by the nested-guest directly. */
1762 pVmcsInfo->pbVirtApic = (uint8_t *)CPUMGetGuestVmxVirtApicPage(pVCpu, &pVCpu->cpum.GstCtx,
1763 &pVmcsInfo->HCPhysVirtApic);
1764 Assert(pVmcsInfo->pbVirtApic);
1765 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1766 }
1767 }
1768
1769 if (RT_SUCCESS(rc))
1770 {
1771 /*
1772 * Allocate the MSR-bitmap if supported by the CPU. The MSR-bitmap is for
1773 * transparent accesses of specific MSRs.
1774 *
1775 * If the condition for enabling MSR bitmaps changes here, don't forget to
1776 * update HMIsMsrBitmapActive().
1777 *
1778 * We don't share MSR bitmaps between the guest and nested-guest as we then
1779 * don't need to care about carefully restoring the guest MSR bitmap.
1780 * The guest visible nested-guest MSR bitmap needs to remain unchanged.
1781 * Hence, allocate a separate MSR bitmap for the guest and nested-guest.
1782 * We also don't need to re-initialize the nested-guest MSR bitmap here as
1783 * we do that later while merging VMCS.
1784 */
1785 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1786 {
1787 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1788 if ( RT_SUCCESS(rc)
1789 && !fIsNstGstVmcs)
1790 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
1791 }
1792
1793 if (RT_SUCCESS(rc))
1794 {
1795 /*
1796 * Allocate the VM-entry MSR-load area for the guest MSRs.
1797 *
1798 * Similar to MSR-bitmaps, we do not share the auto MSR-load/store are between
1799 * the guest and nested-guest.
1800 */
1801 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad,
1802 &pVmcsInfo->HCPhysGuestMsrLoad);
1803 if (RT_SUCCESS(rc))
1804 {
1805 /*
1806 * We use the same page for VM-entry MSR-load and VM-exit MSR store areas.
1807 * These contain the guest MSRs to load on VM-entry and store on VM-exit.
1808 */
1809 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1810 pVmcsInfo->pvGuestMsrStore = pVmcsInfo->pvGuestMsrLoad;
1811 pVmcsInfo->HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrLoad;
1812
1813 /* Allocate the VM-exit MSR-load page for the host MSRs. */
1814 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad,
1815 &pVmcsInfo->HCPhysHostMsrLoad);
1816 }
1817 }
1818 }
1819 }
1820
1821 return rc;
1822}
1823
1824
1825/**
1826 * Free all VT-x structures for the VM.
1827 *
1828 * @returns IPRT status code.
1829 * @param pVM The cross context VM structure.
1830 */
1831static void hmR0VmxStructsFree(PVMCC pVM)
1832{
1833#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1834 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1835#endif
1836 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess, &pVM->hm.s.vmx.HCPhysApicAccess);
1837
1838#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1839 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1840 {
1841 RTMemFree(pVM->hm.s.vmx.paShadowVmcsFields);
1842 RTMemFree(pVM->hm.s.vmx.paShadowVmcsRoFields);
1843 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap, &pVM->hm.s.vmx.HCPhysVmreadBitmap);
1844 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap, &pVM->hm.s.vmx.HCPhysVmwriteBitmap);
1845 }
1846#endif
1847
1848 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1849 {
1850 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
1851 PVMXVMCSINFO pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
1852 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1853#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1854 if (pVM->cpum.ro.GuestFeatures.fVmx)
1855 {
1856 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1857 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1858 }
1859#endif
1860 }
1861}
1862
1863
1864/**
1865 * Allocate all VT-x structures for the VM.
1866 *
1867 * @returns IPRT status code.
1868 * @param pVM The cross context VM structure.
1869 */
1870static int hmR0VmxStructsAlloc(PVMCC pVM)
1871{
1872 /*
1873 * Sanity check the VMCS size reported by the CPU as we assume 4KB allocations.
1874 * The VMCS size cannot be more than 4096 bytes.
1875 *
1876 * See Intel spec. Appendix A.1 "Basic VMX Information".
1877 */
1878 uint32_t const cbVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_SIZE);
1879 if (cbVmcs <= X86_PAGE_4K_SIZE)
1880 { /* likely */ }
1881 else
1882 {
1883 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_INVALID_VMCS_SIZE;
1884 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
1885 }
1886
1887 /*
1888 * Initialize/check members up-front so we can cleanup en masse on allocation failures.
1889 */
1890#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1891 Assert(pVM->hm.s.vmx.hMemObjScratch == NIL_RTR0MEMOBJ);
1892 Assert(pVM->hm.s.vmx.pbScratch == NULL);
1893 pVM->hm.s.vmx.HCPhysScratch = NIL_RTHCPHYS;
1894#endif
1895
1896 Assert(pVM->hm.s.vmx.hMemObjApicAccess == NIL_RTR0MEMOBJ);
1897 Assert(pVM->hm.s.vmx.pbApicAccess == NULL);
1898 pVM->hm.s.vmx.HCPhysApicAccess = NIL_RTHCPHYS;
1899
1900 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1901 {
1902 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
1903 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfo);
1904 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
1905 }
1906
1907 /*
1908 * Allocate per-VM VT-x structures.
1909 */
1910 int rc = VINF_SUCCESS;
1911#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1912 /* Allocate crash-dump magic scratch page. */
1913 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1914 if (RT_FAILURE(rc))
1915 {
1916 hmR0VmxStructsFree(pVM);
1917 return rc;
1918 }
1919 strcpy((char *)pVM->hm.s.vmx.pbScratch, "SCRATCH Magic");
1920 *(uint64_t *)(pVM->hm.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
1921#endif
1922
1923 /* Allocate the APIC-access page for trapping APIC accesses from the guest. */
1924 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
1925 {
1926 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess,
1927 &pVM->hm.s.vmx.HCPhysApicAccess);
1928 if (RT_FAILURE(rc))
1929 {
1930 hmR0VmxStructsFree(pVM);
1931 return rc;
1932 }
1933 }
1934
1935#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1936 /* Allocate the shadow VMCS fields array, VMREAD, VMWRITE bitmaps.. */
1937 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1938 {
1939 Assert(!pVM->hm.s.vmx.cShadowVmcsFields);
1940 Assert(!pVM->hm.s.vmx.cShadowVmcsRoFields);
1941 pVM->hm.s.vmx.paShadowVmcsFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1942 pVM->hm.s.vmx.paShadowVmcsRoFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1943 if (RT_LIKELY( pVM->hm.s.vmx.paShadowVmcsFields
1944 && pVM->hm.s.vmx.paShadowVmcsRoFields))
1945 {
1946 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap,
1947 &pVM->hm.s.vmx.HCPhysVmreadBitmap);
1948 if (RT_SUCCESS(rc))
1949 {
1950 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap,
1951 &pVM->hm.s.vmx.HCPhysVmwriteBitmap);
1952 }
1953 }
1954 else
1955 rc = VERR_NO_MEMORY;
1956
1957 if (RT_FAILURE(rc))
1958 {
1959 hmR0VmxStructsFree(pVM);
1960 return rc;
1961 }
1962 }
1963#endif
1964
1965 /*
1966 * Initialize per-VCPU VT-x structures.
1967 */
1968 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1969 {
1970 /* Allocate the guest VMCS structures. */
1971 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
1972 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
1973 if (RT_SUCCESS(rc))
1974 {
1975#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1976 /* Allocate the nested-guest VMCS structures, when the VMX feature is exposed to the guest. */
1977 if (pVM->cpum.ro.GuestFeatures.fVmx)
1978 {
1979 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
1980 if (RT_SUCCESS(rc))
1981 { /* likely */ }
1982 else
1983 break;
1984 }
1985#endif
1986 }
1987 else
1988 break;
1989 }
1990
1991 if (RT_FAILURE(rc))
1992 {
1993 hmR0VmxStructsFree(pVM);
1994 return rc;
1995 }
1996
1997 return VINF_SUCCESS;
1998}
1999
2000#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2001/**
2002 * Returns whether an MSR at the given MSR-bitmap offset is intercepted or not.
2003 *
2004 * @returns @c true if the MSR is intercepted, @c false otherwise.
2005 * @param pvMsrBitmap The MSR bitmap.
2006 * @param offMsr The MSR byte offset.
2007 * @param iBit The bit offset from the byte offset.
2008 */
2009DECLINLINE(bool) hmR0VmxIsMsrBitSet(const void *pvMsrBitmap, uint16_t offMsr, int32_t iBit)
2010{
2011 uint8_t const * const pbMsrBitmap = (uint8_t const * const)pvMsrBitmap;
2012 Assert(pbMsrBitmap);
2013 Assert(offMsr + (iBit >> 3) <= X86_PAGE_4K_SIZE);
2014 return ASMBitTest(pbMsrBitmap + offMsr, iBit);
2015}
2016#endif
2017
2018/**
2019 * Sets the permission bits for the specified MSR in the given MSR bitmap.
2020 *
2021 * If the passed VMCS is a nested-guest VMCS, this function ensures that the
2022 * read/write intercept is cleared from the MSR bitmap used for hardware-assisted
2023 * VMX execution of the nested-guest, only if nested-guest is also not intercepting
2024 * the read/write access of this MSR.
2025 *
2026 * @param pVCpu The cross context virtual CPU structure.
2027 * @param pVmcsInfo The VMCS info. object.
2028 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2029 * @param idMsr The MSR value.
2030 * @param fMsrpm The MSR permissions (see VMXMSRPM_XXX). This must
2031 * include both a read -and- a write permission!
2032 *
2033 * @sa CPUMGetVmxMsrPermission.
2034 * @remarks Can be called with interrupts disabled.
2035 */
2036static void hmR0VmxSetMsrPermission(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs, uint32_t idMsr, uint32_t fMsrpm)
2037{
2038 uint8_t *pbMsrBitmap = (uint8_t *)pVmcsInfo->pvMsrBitmap;
2039 Assert(pbMsrBitmap);
2040 Assert(VMXMSRPM_IS_FLAG_VALID(fMsrpm));
2041
2042 /*
2043 * MSR-bitmap Layout:
2044 * Byte index MSR range Interpreted as
2045 * 0x000 - 0x3ff 0x00000000 - 0x00001fff Low MSR read bits.
2046 * 0x400 - 0x7ff 0xc0000000 - 0xc0001fff High MSR read bits.
2047 * 0x800 - 0xbff 0x00000000 - 0x00001fff Low MSR write bits.
2048 * 0xc00 - 0xfff 0xc0000000 - 0xc0001fff High MSR write bits.
2049 *
2050 * A bit corresponding to an MSR within the above range causes a VM-exit
2051 * if the bit is 1 on executions of RDMSR/WRMSR. If an MSR falls out of
2052 * the MSR range, it always cause a VM-exit.
2053 *
2054 * See Intel spec. 24.6.9 "MSR-Bitmap Address".
2055 */
2056 uint16_t const offBitmapRead = 0;
2057 uint16_t const offBitmapWrite = 0x800;
2058 uint16_t offMsr;
2059 int32_t iBit;
2060 if (idMsr <= UINT32_C(0x00001fff))
2061 {
2062 offMsr = 0;
2063 iBit = idMsr;
2064 }
2065 else if (idMsr - UINT32_C(0xc0000000) <= UINT32_C(0x00001fff))
2066 {
2067 offMsr = 0x400;
2068 iBit = idMsr - UINT32_C(0xc0000000);
2069 }
2070 else
2071 AssertMsgFailedReturnVoid(("Invalid MSR %#RX32\n", idMsr));
2072
2073 /*
2074 * Set the MSR read permission.
2075 */
2076 uint16_t const offMsrRead = offBitmapRead + offMsr;
2077 Assert(offMsrRead + (iBit >> 3) < offBitmapWrite);
2078 if (fMsrpm & VMXMSRPM_ALLOW_RD)
2079 {
2080#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2081 bool const fClear = !fIsNstGstVmcs ? true
2082 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrRead, iBit);
2083#else
2084 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2085 bool const fClear = true;
2086#endif
2087 if (fClear)
2088 ASMBitClear(pbMsrBitmap + offMsrRead, iBit);
2089 }
2090 else
2091 ASMBitSet(pbMsrBitmap + offMsrRead, iBit);
2092
2093 /*
2094 * Set the MSR write permission.
2095 */
2096 uint16_t const offMsrWrite = offBitmapWrite + offMsr;
2097 Assert(offMsrWrite + (iBit >> 3) < X86_PAGE_4K_SIZE);
2098 if (fMsrpm & VMXMSRPM_ALLOW_WR)
2099 {
2100#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2101 bool const fClear = !fIsNstGstVmcs ? true
2102 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrWrite, iBit);
2103#else
2104 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2105 bool const fClear = true;
2106#endif
2107 if (fClear)
2108 ASMBitClear(pbMsrBitmap + offMsrWrite, iBit);
2109 }
2110 else
2111 ASMBitSet(pbMsrBitmap + offMsrWrite, iBit);
2112}
2113
2114
2115/**
2116 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR
2117 * area.
2118 *
2119 * @returns VBox status code.
2120 * @param pVCpu The cross context virtual CPU structure.
2121 * @param pVmcsInfo The VMCS info. object.
2122 * @param cMsrs The number of MSRs.
2123 */
2124static int hmR0VmxSetAutoLoadStoreMsrCount(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t cMsrs)
2125{
2126 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */
2127 uint32_t const cMaxSupportedMsrs = VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc);
2128 if (RT_LIKELY(cMsrs < cMaxSupportedMsrs))
2129 {
2130 /* Commit the MSR counts to the VMCS and update the cache. */
2131 if (pVmcsInfo->cEntryMsrLoad != cMsrs)
2132 {
2133 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2134 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs); AssertRC(rc);
2135 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2136 pVmcsInfo->cEntryMsrLoad = cMsrs;
2137 pVmcsInfo->cExitMsrStore = cMsrs;
2138 pVmcsInfo->cExitMsrLoad = cMsrs;
2139 }
2140 return VINF_SUCCESS;
2141 }
2142
2143 LogRel(("Auto-load/store MSR count exceeded! cMsrs=%u MaxSupported=%u\n", cMsrs, cMaxSupportedMsrs));
2144 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE;
2145 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2146}
2147
2148
2149/**
2150 * Adds a new (or updates the value of an existing) guest/host MSR
2151 * pair to be swapped during the world-switch as part of the
2152 * auto-load/store MSR area in the VMCS.
2153 *
2154 * @returns VBox status code.
2155 * @param pVCpu The cross context virtual CPU structure.
2156 * @param pVmxTransient The VMX-transient structure.
2157 * @param idMsr The MSR.
2158 * @param uGuestMsrValue Value of the guest MSR.
2159 * @param fSetReadWrite Whether to set the guest read/write access of this
2160 * MSR (thus not causing a VM-exit).
2161 * @param fUpdateHostMsr Whether to update the value of the host MSR if
2162 * necessary.
2163 */
2164static int hmR0VmxAddAutoLoadStoreMsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t idMsr, uint64_t uGuestMsrValue,
2165 bool fSetReadWrite, bool fUpdateHostMsr)
2166{
2167 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2168 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2169 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2170 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2171 uint32_t i;
2172
2173 /* Paranoia. */
2174 Assert(pGuestMsrLoad);
2175
2176 LogFlowFunc(("pVCpu=%p idMsr=%#RX32 uGestMsrValue=%#RX64\n", pVCpu, idMsr, uGuestMsrValue));
2177
2178 /* Check if the MSR already exists in the VM-entry MSR-load area. */
2179 for (i = 0; i < cMsrs; i++)
2180 {
2181 if (pGuestMsrLoad[i].u32Msr == idMsr)
2182 break;
2183 }
2184
2185 bool fAdded = false;
2186 if (i == cMsrs)
2187 {
2188 /* The MSR does not exist, bump the MSR count to make room for the new MSR. */
2189 ++cMsrs;
2190 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2191 AssertMsgRCReturn(rc, ("Insufficient space to add MSR to VM-entry MSR-load/store area %u\n", idMsr), rc);
2192
2193 /* Set the guest to read/write this MSR without causing VM-exits. */
2194 if ( fSetReadWrite
2195 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
2196 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_ALLOW_RD_WR);
2197
2198 Log4Func(("Added MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2199 fAdded = true;
2200 }
2201
2202 /* Update the MSR value for the newly added or already existing MSR. */
2203 pGuestMsrLoad[i].u32Msr = idMsr;
2204 pGuestMsrLoad[i].u64Value = uGuestMsrValue;
2205
2206 /* Create the corresponding slot in the VM-exit MSR-store area if we use a different page. */
2207 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2208 {
2209 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2210 pGuestMsrStore[i].u32Msr = idMsr;
2211 pGuestMsrStore[i].u64Value = uGuestMsrValue;
2212 }
2213
2214 /* Update the corresponding slot in the host MSR area. */
2215 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2216 Assert(pHostMsr != pVmcsInfo->pvGuestMsrLoad);
2217 Assert(pHostMsr != pVmcsInfo->pvGuestMsrStore);
2218 pHostMsr[i].u32Msr = idMsr;
2219
2220 /*
2221 * Only if the caller requests to update the host MSR value AND we've newly added the
2222 * MSR to the host MSR area do we actually update the value. Otherwise, it will be
2223 * updated by hmR0VmxUpdateAutoLoadHostMsrs().
2224 *
2225 * We do this for performance reasons since reading MSRs may be quite expensive.
2226 */
2227 if (fAdded)
2228 {
2229 if (fUpdateHostMsr)
2230 {
2231 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2232 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2233 pHostMsr[i].u64Value = ASMRdMsr(idMsr);
2234 }
2235 else
2236 {
2237 /* Someone else can do the work. */
2238 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
2239 }
2240 }
2241 return VINF_SUCCESS;
2242}
2243
2244
2245/**
2246 * Removes a guest/host MSR pair to be swapped during the world-switch from the
2247 * auto-load/store MSR area in the VMCS.
2248 *
2249 * @returns VBox status code.
2250 * @param pVCpu The cross context virtual CPU structure.
2251 * @param pVmxTransient The VMX-transient structure.
2252 * @param idMsr The MSR.
2253 */
2254static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t idMsr)
2255{
2256 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2257 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2258 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2259 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2260
2261 LogFlowFunc(("pVCpu=%p idMsr=%#RX32\n", pVCpu, idMsr));
2262
2263 for (uint32_t i = 0; i < cMsrs; i++)
2264 {
2265 /* Find the MSR. */
2266 if (pGuestMsrLoad[i].u32Msr == idMsr)
2267 {
2268 /*
2269 * If it's the last MSR, we only need to reduce the MSR count.
2270 * If it's -not- the last MSR, copy the last MSR in place of it and reduce the MSR count.
2271 */
2272 if (i < cMsrs - 1)
2273 {
2274 /* Remove it from the VM-entry MSR-load area. */
2275 pGuestMsrLoad[i].u32Msr = pGuestMsrLoad[cMsrs - 1].u32Msr;
2276 pGuestMsrLoad[i].u64Value = pGuestMsrLoad[cMsrs - 1].u64Value;
2277
2278 /* Remove it from the VM-exit MSR-store area if it's in a different page. */
2279 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2280 {
2281 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2282 Assert(pGuestMsrStore[i].u32Msr == idMsr);
2283 pGuestMsrStore[i].u32Msr = pGuestMsrStore[cMsrs - 1].u32Msr;
2284 pGuestMsrStore[i].u64Value = pGuestMsrStore[cMsrs - 1].u64Value;
2285 }
2286
2287 /* Remove it from the VM-exit MSR-load area. */
2288 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2289 Assert(pHostMsr[i].u32Msr == idMsr);
2290 pHostMsr[i].u32Msr = pHostMsr[cMsrs - 1].u32Msr;
2291 pHostMsr[i].u64Value = pHostMsr[cMsrs - 1].u64Value;
2292 }
2293
2294 /* Reduce the count to reflect the removed MSR and bail. */
2295 --cMsrs;
2296 break;
2297 }
2298 }
2299
2300 /* Update the VMCS if the count changed (meaning the MSR was found and removed). */
2301 if (cMsrs != pVmcsInfo->cEntryMsrLoad)
2302 {
2303 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2304 AssertRCReturn(rc, rc);
2305
2306 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */
2307 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2308 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR);
2309
2310 Log4Func(("Removed MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2311 return VINF_SUCCESS;
2312 }
2313
2314 return VERR_NOT_FOUND;
2315}
2316
2317
2318/**
2319 * Checks if the specified guest MSR is part of the VM-entry MSR-load area.
2320 *
2321 * @returns @c true if found, @c false otherwise.
2322 * @param pVmcsInfo The VMCS info. object.
2323 * @param idMsr The MSR to find.
2324 */
2325static bool hmR0VmxIsAutoLoadGuestMsr(PCVMXVMCSINFO pVmcsInfo, uint32_t idMsr)
2326{
2327 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2328 uint32_t const cMsrs = pVmcsInfo->cEntryMsrLoad;
2329 Assert(pMsrs);
2330 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
2331 for (uint32_t i = 0; i < cMsrs; i++)
2332 {
2333 if (pMsrs[i].u32Msr == idMsr)
2334 return true;
2335 }
2336 return false;
2337}
2338
2339
2340/**
2341 * Updates the value of all host MSRs in the VM-exit MSR-load area.
2342 *
2343 * @param pVCpu The cross context virtual CPU structure.
2344 * @param pVmcsInfo The VMCS info. object.
2345 *
2346 * @remarks No-long-jump zone!!!
2347 */
2348static void hmR0VmxUpdateAutoLoadHostMsrs(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2349{
2350 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2351
2352 PVMXAUTOMSR pHostMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2353 uint32_t const cMsrs = pVmcsInfo->cExitMsrLoad;
2354 Assert(pHostMsrLoad);
2355 Assert(sizeof(*pHostMsrLoad) * cMsrs <= X86_PAGE_4K_SIZE);
2356 LogFlowFunc(("pVCpu=%p cMsrs=%u\n", pVCpu, cMsrs));
2357 for (uint32_t i = 0; i < cMsrs; i++)
2358 {
2359 /*
2360 * Performance hack for the host EFER MSR. We use the cached value rather than re-read it.
2361 * Strict builds will catch mismatches in hmR0VmxCheckAutoLoadStoreMsrs(). See @bugref{7368}.
2362 */
2363 if (pHostMsrLoad[i].u32Msr == MSR_K6_EFER)
2364 pHostMsrLoad[i].u64Value = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2365 else
2366 pHostMsrLoad[i].u64Value = ASMRdMsr(pHostMsrLoad[i].u32Msr);
2367 }
2368}
2369
2370
2371/**
2372 * Saves a set of host MSRs to allow read/write passthru access to the guest and
2373 * perform lazy restoration of the host MSRs while leaving VT-x.
2374 *
2375 * @param pVCpu The cross context virtual CPU structure.
2376 *
2377 * @remarks No-long-jump zone!!!
2378 */
2379static void hmR0VmxLazySaveHostMsrs(PVMCPUCC pVCpu)
2380{
2381 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2382
2383 /*
2384 * Note: If you're adding MSRs here, make sure to update the MSR-bitmap accesses in hmR0VmxSetupVmcsProcCtls().
2385 */
2386 if (!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST))
2387 {
2388 Assert(!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)); /* Guest MSRs better not be loaded now. */
2389 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2390 {
2391 pVCpu->hm.s.vmx.u64HostMsrLStar = ASMRdMsr(MSR_K8_LSTAR);
2392 pVCpu->hm.s.vmx.u64HostMsrStar = ASMRdMsr(MSR_K6_STAR);
2393 pVCpu->hm.s.vmx.u64HostMsrSfMask = ASMRdMsr(MSR_K8_SF_MASK);
2394 pVCpu->hm.s.vmx.u64HostMsrKernelGsBase = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
2395 }
2396 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_SAVED_HOST;
2397 }
2398}
2399
2400
2401/**
2402 * Checks whether the MSR belongs to the set of guest MSRs that we restore
2403 * lazily while leaving VT-x.
2404 *
2405 * @returns true if it does, false otherwise.
2406 * @param pVCpu The cross context virtual CPU structure.
2407 * @param idMsr The MSR to check.
2408 */
2409static bool hmR0VmxIsLazyGuestMsr(PCVMCPUCC pVCpu, uint32_t idMsr)
2410{
2411 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2412 {
2413 switch (idMsr)
2414 {
2415 case MSR_K8_LSTAR:
2416 case MSR_K6_STAR:
2417 case MSR_K8_SF_MASK:
2418 case MSR_K8_KERNEL_GS_BASE:
2419 return true;
2420 }
2421 }
2422 return false;
2423}
2424
2425
2426/**
2427 * Loads a set of guests MSRs to allow read/passthru to the guest.
2428 *
2429 * The name of this function is slightly confusing. This function does NOT
2430 * postpone loading, but loads the MSR right now. "hmR0VmxLazy" is simply a
2431 * common prefix for functions dealing with "lazy restoration" of the shared
2432 * MSRs.
2433 *
2434 * @param pVCpu The cross context virtual CPU structure.
2435 *
2436 * @remarks No-long-jump zone!!!
2437 */
2438static void hmR0VmxLazyLoadGuestMsrs(PVMCPUCC pVCpu)
2439{
2440 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2441 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2442
2443 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2444 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2445 {
2446 /*
2447 * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
2448 * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
2449 * we can skip a few MSR writes.
2450 *
2451 * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
2452 * guest MSR values in the guest-CPU context might be different to what's currently
2453 * loaded in the CPU. In either case, we need to write the new guest MSR values to the
2454 * CPU, see @bugref{8728}.
2455 */
2456 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2457 if ( !(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2458 && pCtx->msrKERNELGSBASE == pVCpu->hm.s.vmx.u64HostMsrKernelGsBase
2459 && pCtx->msrLSTAR == pVCpu->hm.s.vmx.u64HostMsrLStar
2460 && pCtx->msrSTAR == pVCpu->hm.s.vmx.u64HostMsrStar
2461 && pCtx->msrSFMASK == pVCpu->hm.s.vmx.u64HostMsrSfMask)
2462 {
2463#ifdef VBOX_STRICT
2464 Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pCtx->msrKERNELGSBASE);
2465 Assert(ASMRdMsr(MSR_K8_LSTAR) == pCtx->msrLSTAR);
2466 Assert(ASMRdMsr(MSR_K6_STAR) == pCtx->msrSTAR);
2467 Assert(ASMRdMsr(MSR_K8_SF_MASK) == pCtx->msrSFMASK);
2468#endif
2469 }
2470 else
2471 {
2472 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE);
2473 ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR);
2474 ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR);
2475 ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK);
2476 }
2477 }
2478 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
2479}
2480
2481
2482/**
2483 * Performs lazy restoration of the set of host MSRs if they were previously
2484 * loaded with guest MSR values.
2485 *
2486 * @param pVCpu The cross context virtual CPU structure.
2487 *
2488 * @remarks No-long-jump zone!!!
2489 * @remarks The guest MSRs should have been saved back into the guest-CPU
2490 * context by hmR0VmxImportGuestState()!!!
2491 */
2492static void hmR0VmxLazyRestoreHostMsrs(PVMCPUCC pVCpu)
2493{
2494 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2495 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2496
2497 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2498 {
2499 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2500 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2501 {
2502 ASMWrMsr(MSR_K8_LSTAR, pVCpu->hm.s.vmx.u64HostMsrLStar);
2503 ASMWrMsr(MSR_K6_STAR, pVCpu->hm.s.vmx.u64HostMsrStar);
2504 ASMWrMsr(MSR_K8_SF_MASK, pVCpu->hm.s.vmx.u64HostMsrSfMask);
2505 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pVCpu->hm.s.vmx.u64HostMsrKernelGsBase);
2506 }
2507 }
2508 pVCpu->hm.s.vmx.fLazyMsrs &= ~(VMX_LAZY_MSRS_LOADED_GUEST | VMX_LAZY_MSRS_SAVED_HOST);
2509}
2510
2511
2512/**
2513 * Verifies that our cached values of the VMCS fields are all consistent with
2514 * what's actually present in the VMCS.
2515 *
2516 * @returns VBox status code.
2517 * @retval VINF_SUCCESS if all our caches match their respective VMCS fields.
2518 * @retval VERR_VMX_VMCS_FIELD_CACHE_INVALID if a cache field doesn't match the
2519 * VMCS content. HMCPU error-field is
2520 * updated, see VMX_VCI_XXX.
2521 * @param pVCpu The cross context virtual CPU structure.
2522 * @param pVmcsInfo The VMCS info. object.
2523 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2524 */
2525static int hmR0VmxCheckVmcsCtls(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2526{
2527 const char * const pcszVmcs = fIsNstGstVmcs ? "Nested-guest VMCS" : "VMCS";
2528
2529 uint32_t u32Val;
2530 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
2531 AssertRC(rc);
2532 AssertMsgReturnStmt(pVmcsInfo->u32EntryCtls == u32Val,
2533 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32EntryCtls, u32Val),
2534 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_ENTRY,
2535 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2536
2537 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val);
2538 AssertRC(rc);
2539 AssertMsgReturnStmt(pVmcsInfo->u32ExitCtls == u32Val,
2540 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ExitCtls, u32Val),
2541 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_EXIT,
2542 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2543
2544 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val);
2545 AssertRC(rc);
2546 AssertMsgReturnStmt(pVmcsInfo->u32PinCtls == u32Val,
2547 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32PinCtls, u32Val),
2548 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PIN_EXEC,
2549 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2550
2551 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val);
2552 AssertRC(rc);
2553 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls == u32Val,
2554 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls, u32Val),
2555 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC,
2556 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2557
2558 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
2559 {
2560 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val);
2561 AssertRC(rc);
2562 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls2 == u32Val,
2563 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls2, u32Val),
2564 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC2,
2565 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2566 }
2567
2568 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val);
2569 AssertRC(rc);
2570 AssertMsgReturnStmt(pVmcsInfo->u32XcptBitmap == u32Val,
2571 ("%s exception bitmap mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32XcptBitmap, u32Val),
2572 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_XCPT_BITMAP,
2573 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2574
2575 uint64_t u64Val;
2576 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, &u64Val);
2577 AssertRC(rc);
2578 AssertMsgReturnStmt(pVmcsInfo->u64TscOffset == u64Val,
2579 ("%s TSC offset mismatch: Cache=%#RX64 VMCS=%#RX64\n", pcszVmcs, pVmcsInfo->u64TscOffset, u64Val),
2580 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_TSC_OFFSET,
2581 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2582
2583 NOREF(pcszVmcs);
2584 return VINF_SUCCESS;
2585}
2586
2587
2588#ifdef VBOX_STRICT
2589/**
2590 * Verifies that our cached host EFER MSR value has not changed since we cached it.
2591 *
2592 * @param pVCpu The cross context virtual CPU structure.
2593 * @param pVmcsInfo The VMCS info. object.
2594 */
2595static void hmR0VmxCheckHostEferMsr(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2596{
2597 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2598
2599 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2600 {
2601 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2602 uint64_t const uHostEferMsrCache = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2603 uint64_t uVmcsEferMsrVmcs;
2604 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2605 AssertRC(rc);
2606
2607 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2608 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2609 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2610 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2611 }
2612}
2613
2614
2615/**
2616 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2617 * VMCS are correct.
2618 *
2619 * @param pVCpu The cross context virtual CPU structure.
2620 * @param pVmcsInfo The VMCS info. object.
2621 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2622 */
2623static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2624{
2625 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2626
2627 /* Read the various MSR-area counts from the VMCS. */
2628 uint32_t cEntryLoadMsrs;
2629 uint32_t cExitStoreMsrs;
2630 uint32_t cExitLoadMsrs;
2631 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2632 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2633 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2634
2635 /* Verify all the MSR counts are the same. */
2636 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2637 Assert(cExitStoreMsrs == cExitLoadMsrs);
2638 uint32_t const cMsrs = cExitLoadMsrs;
2639
2640 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2641 Assert(cMsrs < VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc));
2642
2643 /* Verify the MSR counts are within the allocated page size. */
2644 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2645
2646 /* Verify the relevant contents of the MSR areas match. */
2647 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2648 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2649 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2650 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2651 for (uint32_t i = 0; i < cMsrs; i++)
2652 {
2653 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2654 if (fSeparateExitMsrStorePage)
2655 {
2656 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2657 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2658 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2659 }
2660
2661 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2662 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2663 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2664
2665 uint64_t const u64Msr = ASMRdMsr(pHostMsrLoad->u32Msr);
2666 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64Msr,
2667 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2668 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64Msr, cMsrs));
2669
2670 /* Verify that cached host EFER MSR matches what's loaded the CPU. */
2671 bool const fIsEferMsr = RT_BOOL(pHostMsrLoad->u32Msr == MSR_K6_EFER);
2672 if (fIsEferMsr)
2673 {
2674 AssertMsgReturnVoid(u64Msr == pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer,
2675 ("Cached=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2676 pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer, u64Msr, cMsrs));
2677 }
2678
2679 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2680 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2681 {
2682 uint32_t const fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2683 if (fIsEferMsr)
2684 {
2685 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2686 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2687 }
2688 else
2689 {
2690 if (!fIsNstGstVmcs)
2691 {
2692 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_ALLOW_RD_WR) == VMXMSRPM_ALLOW_RD_WR,
2693 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2694 }
2695 else
2696 {
2697 /*
2698 * A nested-guest VMCS must -also- allow read/write passthrough for the MSR for us to
2699 * execute a nested-guest with MSR passthrough.
2700 *
2701 * Check if the nested-guest MSR bitmap allows passthrough, and if so, assert that we
2702 * allow passthrough too.
2703 */
2704 void const *pvMsrBitmapNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
2705 Assert(pvMsrBitmapNstGst);
2706 uint32_t const fMsrpmNstGst = CPUMGetVmxMsrPermission(pvMsrBitmapNstGst, pGuestMsrLoad->u32Msr);
2707 AssertMsgReturnVoid(fMsrpm == fMsrpmNstGst,
2708 ("u32Msr=%#RX32 cMsrs=%u Permission mismatch fMsrpm=%#x fMsrpmNstGst=%#x!\n",
2709 pGuestMsrLoad->u32Msr, cMsrs, fMsrpm, fMsrpmNstGst));
2710 }
2711 }
2712 }
2713
2714 /* Move to the next MSR. */
2715 pHostMsrLoad++;
2716 pGuestMsrLoad++;
2717 pGuestMsrStore++;
2718 }
2719}
2720#endif /* VBOX_STRICT */
2721
2722
2723/**
2724 * Flushes the TLB using EPT.
2725 *
2726 * @returns VBox status code.
2727 * @param pVCpu The cross context virtual CPU structure of the calling
2728 * EMT. Can be NULL depending on @a enmTlbFlush.
2729 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2730 * enmTlbFlush.
2731 * @param enmTlbFlush Type of flush.
2732 *
2733 * @remarks Caller is responsible for making sure this function is called only
2734 * when NestedPaging is supported and providing @a enmTlbFlush that is
2735 * supported by the CPU.
2736 * @remarks Can be called with interrupts disabled.
2737 */
2738static void hmR0VmxFlushEpt(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2739{
2740 uint64_t au64Descriptor[2];
2741 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2742 au64Descriptor[0] = 0;
2743 else
2744 {
2745 Assert(pVCpu);
2746 Assert(pVmcsInfo);
2747 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2748 }
2749 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2750
2751 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2752 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2753
2754 if ( RT_SUCCESS(rc)
2755 && pVCpu)
2756 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2757}
2758
2759
2760/**
2761 * Flushes the TLB using VPID.
2762 *
2763 * @returns VBox status code.
2764 * @param pVCpu The cross context virtual CPU structure of the calling
2765 * EMT. Can be NULL depending on @a enmTlbFlush.
2766 * @param enmTlbFlush Type of flush.
2767 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2768 * on @a enmTlbFlush).
2769 *
2770 * @remarks Can be called with interrupts disabled.
2771 */
2772static void hmR0VmxFlushVpid(PVMCPUCC pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2773{
2774 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid);
2775
2776 uint64_t au64Descriptor[2];
2777 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2778 {
2779 au64Descriptor[0] = 0;
2780 au64Descriptor[1] = 0;
2781 }
2782 else
2783 {
2784 AssertPtr(pVCpu);
2785 AssertMsg(pVCpu->hm.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2786 AssertMsg(pVCpu->hm.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2787 au64Descriptor[0] = pVCpu->hm.s.uCurrentAsid;
2788 au64Descriptor[1] = GCPtr;
2789 }
2790
2791 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2792 AssertMsg(rc == VINF_SUCCESS,
2793 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hm.s.uCurrentAsid : 0, GCPtr, rc));
2794
2795 if ( RT_SUCCESS(rc)
2796 && pVCpu)
2797 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2798 NOREF(rc);
2799}
2800
2801
2802/**
2803 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2804 * otherwise there is nothing really to invalidate.
2805 *
2806 * @returns VBox status code.
2807 * @param pVCpu The cross context virtual CPU structure.
2808 * @param GCVirt Guest virtual address of the page to invalidate.
2809 */
2810VMMR0DECL(int) VMXR0InvalidatePage(PVMCPUCC pVCpu, RTGCPTR GCVirt)
2811{
2812 AssertPtr(pVCpu);
2813 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2814
2815 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2816 {
2817 /*
2818 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2819 * the EPT case. See @bugref{6043} and @bugref{6177}.
2820 *
2821 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2822 * as this function maybe called in a loop with individual addresses.
2823 */
2824 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2825 if (pVM->hm.s.vmx.fVpid)
2826 {
2827 bool fVpidFlush = RT_BOOL(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
2828 if (fVpidFlush)
2829 {
2830 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2831 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2832 }
2833 else
2834 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2835 }
2836 else if (pVM->hm.s.fNestedPaging)
2837 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2838 }
2839
2840 return VINF_SUCCESS;
2841}
2842
2843
2844/**
2845 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2846 * case where neither EPT nor VPID is supported by the CPU.
2847 *
2848 * @param pHostCpu The HM physical-CPU structure.
2849 * @param pVCpu The cross context virtual CPU structure.
2850 *
2851 * @remarks Called with interrupts disabled.
2852 */
2853static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
2854{
2855 AssertPtr(pVCpu);
2856 AssertPtr(pHostCpu);
2857
2858 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2859
2860 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2861 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2862 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2863 pVCpu->hm.s.fForceTLBFlush = false;
2864 return;
2865}
2866
2867
2868/**
2869 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
2870 *
2871 * @param pHostCpu The HM physical-CPU structure.
2872 * @param pVCpu The cross context virtual CPU structure.
2873 * @param pVmcsInfo The VMCS info. object.
2874 *
2875 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
2876 * nomenclature. The reason is, to avoid confusion in compare statements
2877 * since the host-CPU copies are named "ASID".
2878 *
2879 * @remarks Called with interrupts disabled.
2880 */
2881static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2882{
2883#ifdef VBOX_WITH_STATISTICS
2884 bool fTlbFlushed = false;
2885# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
2886# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
2887 if (!fTlbFlushed) \
2888 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
2889 } while (0)
2890#else
2891# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
2892# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
2893#endif
2894
2895 AssertPtr(pVCpu);
2896 AssertPtr(pHostCpu);
2897 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2898
2899 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2900 AssertMsg(pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid,
2901 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
2902 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hm.s.fNestedPaging, pVM->hm.s.vmx.fVpid));
2903
2904 /*
2905 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
2906 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
2907 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
2908 * cannot reuse the current ASID anymore.
2909 */
2910 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
2911 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
2912 {
2913 ++pHostCpu->uCurrentAsid;
2914 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
2915 {
2916 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
2917 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
2918 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
2919 }
2920
2921 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
2922 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2923 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2924
2925 /*
2926 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
2927 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
2928 */
2929 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2930 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
2931 HMVMX_SET_TAGGED_TLB_FLUSHED();
2932 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2933 }
2934 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
2935 {
2936 /*
2937 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
2938 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
2939 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
2940 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
2941 * mappings, see @bugref{6568}.
2942 *
2943 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
2944 */
2945 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2946 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
2947 HMVMX_SET_TAGGED_TLB_FLUSHED();
2948 }
2949 else if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
2950 {
2951 /*
2952 * The nested-guest specifies its own guest-physical address to use as the APIC-access
2953 * address which requires flushing the TLB of EPT cached structures.
2954 *
2955 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
2956 */
2957 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2958 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
2959 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
2960 HMVMX_SET_TAGGED_TLB_FLUSHED();
2961 }
2962
2963
2964 pVCpu->hm.s.fForceTLBFlush = false;
2965 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
2966
2967 Assert(pVCpu->hm.s.idLastCpu == pHostCpu->idCpu);
2968 Assert(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes);
2969 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
2970 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
2971 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
2972 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
2973 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
2974 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
2975 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
2976
2977 /* Update VMCS with the VPID. */
2978 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
2979 AssertRC(rc);
2980
2981#undef HMVMX_SET_TAGGED_TLB_FLUSHED
2982}
2983
2984
2985/**
2986 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
2987 *
2988 * @param pHostCpu The HM physical-CPU structure.
2989 * @param pVCpu The cross context virtual CPU structure.
2990 * @param pVmcsInfo The VMCS info. object.
2991 *
2992 * @remarks Called with interrupts disabled.
2993 */
2994static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2995{
2996 AssertPtr(pVCpu);
2997 AssertPtr(pHostCpu);
2998 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2999 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
3000 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
3001
3002 /*
3003 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
3004 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
3005 */
3006 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3007 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3008 {
3009 pVCpu->hm.s.fForceTLBFlush = true;
3010 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3011 }
3012
3013 /* Check for explicit TLB flushes. */
3014 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3015 {
3016 pVCpu->hm.s.fForceTLBFlush = true;
3017 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3018 }
3019
3020 /* Check for TLB flushes while switching to/from a nested-guest. */
3021 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3022 {
3023 pVCpu->hm.s.fForceTLBFlush = true;
3024 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3025 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3026 }
3027
3028 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3029 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3030
3031 if (pVCpu->hm.s.fForceTLBFlush)
3032 {
3033 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hm.s.vmx.enmTlbFlushEpt);
3034 pVCpu->hm.s.fForceTLBFlush = false;
3035 }
3036}
3037
3038
3039/**
3040 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
3041 *
3042 * @param pHostCpu The HM physical-CPU structure.
3043 * @param pVCpu The cross context virtual CPU structure.
3044 *
3045 * @remarks Called with interrupts disabled.
3046 */
3047static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
3048{
3049 AssertPtr(pVCpu);
3050 AssertPtr(pHostCpu);
3051 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3052 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
3053 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
3054
3055 /*
3056 * Force a TLB flush for the first world switch if the current CPU differs from the one we
3057 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3058 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3059 * cannot reuse the current ASID anymore.
3060 */
3061 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3062 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3063 {
3064 pVCpu->hm.s.fForceTLBFlush = true;
3065 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3066 }
3067
3068 /* Check for explicit TLB flushes. */
3069 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3070 {
3071 /*
3072 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
3073 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
3074 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
3075 * include fExplicitFlush's too) - an obscure corner case.
3076 */
3077 pVCpu->hm.s.fForceTLBFlush = true;
3078 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3079 }
3080
3081 /* Check for TLB flushes while switching to/from a nested-guest. */
3082 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3083 {
3084 pVCpu->hm.s.fForceTLBFlush = true;
3085 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3086 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3087 }
3088
3089 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3090 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3091 if (pVCpu->hm.s.fForceTLBFlush)
3092 {
3093 ++pHostCpu->uCurrentAsid;
3094 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3095 {
3096 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
3097 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3098 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3099 }
3100
3101 pVCpu->hm.s.fForceTLBFlush = false;
3102 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3103 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3104 if (pHostCpu->fFlushAsidBeforeUse)
3105 {
3106 if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
3107 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
3108 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
3109 {
3110 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
3111 pHostCpu->fFlushAsidBeforeUse = false;
3112 }
3113 else
3114 {
3115 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
3116 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
3117 }
3118 }
3119 }
3120
3121 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3122 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3123 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3124 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3125 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3126 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3127 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3128
3129 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3130 AssertRC(rc);
3131}
3132
3133
3134/**
3135 * Flushes the guest TLB entry based on CPU capabilities.
3136 *
3137 * @param pHostCpu The HM physical-CPU structure.
3138 * @param pVCpu The cross context virtual CPU structure.
3139 * @param pVmcsInfo The VMCS info. object.
3140 *
3141 * @remarks Called with interrupts disabled.
3142 */
3143static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3144{
3145#ifdef HMVMX_ALWAYS_FLUSH_TLB
3146 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
3147#endif
3148 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3149 switch (pVM->hm.s.vmx.enmTlbFlushType)
3150 {
3151 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
3152 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
3153 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
3154 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
3155 default:
3156 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
3157 break;
3158 }
3159 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
3160}
3161
3162
3163/**
3164 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
3165 * TLB entries from the host TLB before VM-entry.
3166 *
3167 * @returns VBox status code.
3168 * @param pVM The cross context VM structure.
3169 */
3170static int hmR0VmxSetupTaggedTlb(PVMCC pVM)
3171{
3172 /*
3173 * Determine optimal flush type for nested paging.
3174 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
3175 * unrestricted guest execution (see hmR3InitFinalizeR0()).
3176 */
3177 if (pVM->hm.s.fNestedPaging)
3178 {
3179 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
3180 {
3181 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
3182 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
3183 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3184 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
3185 else
3186 {
3187 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
3188 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3189 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
3190 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3191 }
3192
3193 /* Make sure the write-back cacheable memory type for EPT is supported. */
3194 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
3195 {
3196 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3197 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
3198 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3199 }
3200
3201 /* EPT requires a page-walk length of 4. */
3202 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
3203 {
3204 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3205 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
3206 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3207 }
3208 }
3209 else
3210 {
3211 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
3212 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3213 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
3214 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3215 }
3216 }
3217
3218 /*
3219 * Determine optimal flush type for VPID.
3220 */
3221 if (pVM->hm.s.vmx.fVpid)
3222 {
3223 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
3224 {
3225 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
3226 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
3227 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
3228 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
3229 else
3230 {
3231 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
3232 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
3233 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
3234 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
3235 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
3236 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3237 pVM->hm.s.vmx.fVpid = false;
3238 }
3239 }
3240 else
3241 {
3242 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
3243 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
3244 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3245 pVM->hm.s.vmx.fVpid = false;
3246 }
3247 }
3248
3249 /*
3250 * Setup the handler for flushing tagged-TLBs.
3251 */
3252 if (pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid)
3253 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
3254 else if (pVM->hm.s.fNestedPaging)
3255 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
3256 else if (pVM->hm.s.vmx.fVpid)
3257 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
3258 else
3259 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
3260 return VINF_SUCCESS;
3261}
3262
3263
3264#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3265/**
3266 * Sets up the shadow VMCS fields arrays.
3267 *
3268 * This function builds arrays of VMCS fields to sync the shadow VMCS later while
3269 * executing the guest.
3270 *
3271 * @returns VBox status code.
3272 * @param pVM The cross context VM structure.
3273 */
3274static int hmR0VmxSetupShadowVmcsFieldsArrays(PVMCC pVM)
3275{
3276 /*
3277 * Paranoia. Ensure we haven't exposed the VMWRITE-All VMX feature to the guest
3278 * when the host does not support it.
3279 */
3280 bool const fGstVmwriteAll = pVM->cpum.ro.GuestFeatures.fVmxVmwriteAll;
3281 if ( !fGstVmwriteAll
3282 || (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL))
3283 { /* likely. */ }
3284 else
3285 {
3286 LogRelFunc(("VMX VMWRITE-All feature exposed to the guest but host CPU does not support it!\n"));
3287 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_GST_HOST_VMWRITE_ALL;
3288 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3289 }
3290
3291 uint32_t const cVmcsFields = RT_ELEMENTS(g_aVmcsFields);
3292 uint32_t cRwFields = 0;
3293 uint32_t cRoFields = 0;
3294 for (uint32_t i = 0; i < cVmcsFields; i++)
3295 {
3296 VMXVMCSFIELD VmcsField;
3297 VmcsField.u = g_aVmcsFields[i];
3298
3299 /*
3300 * We will be writing "FULL" (64-bit) fields while syncing the shadow VMCS.
3301 * Therefore, "HIGH" (32-bit portion of 64-bit) fields must not be included
3302 * in the shadow VMCS fields array as they would be redundant.
3303 *
3304 * If the VMCS field depends on a CPU feature that is not exposed to the guest,
3305 * we must not include it in the shadow VMCS fields array. Guests attempting to
3306 * VMREAD/VMWRITE such VMCS fields would cause a VM-exit and we shall emulate
3307 * the required behavior.
3308 */
3309 if ( VmcsField.n.fAccessType == VMX_VMCSFIELD_ACCESS_FULL
3310 && CPUMIsGuestVmxVmcsFieldValid(pVM, VmcsField.u))
3311 {
3312 /*
3313 * Read-only fields are placed in a separate array so that while syncing shadow
3314 * VMCS fields later (which is more performance critical) we can avoid branches.
3315 *
3316 * However, if the guest can write to all fields (including read-only fields),
3317 * we treat it a as read/write field. Otherwise, writing to these fields would
3318 * cause a VMWRITE instruction error while syncing the shadow VMCS .
3319 */
3320 if ( fGstVmwriteAll
3321 || !VMXIsVmcsFieldReadOnly(VmcsField.u))
3322 pVM->hm.s.vmx.paShadowVmcsFields[cRwFields++] = VmcsField.u;
3323 else
3324 pVM->hm.s.vmx.paShadowVmcsRoFields[cRoFields++] = VmcsField.u;
3325 }
3326 }
3327
3328 /* Update the counts. */
3329 pVM->hm.s.vmx.cShadowVmcsFields = cRwFields;
3330 pVM->hm.s.vmx.cShadowVmcsRoFields = cRoFields;
3331 return VINF_SUCCESS;
3332}
3333
3334
3335/**
3336 * Sets up the VMREAD and VMWRITE bitmaps.
3337 *
3338 * @param pVM The cross context VM structure.
3339 */
3340static void hmR0VmxSetupVmreadVmwriteBitmaps(PVMCC pVM)
3341{
3342 /*
3343 * By default, ensure guest attempts to acceses to any VMCS fields cause VM-exits.
3344 */
3345 uint32_t const cbBitmap = X86_PAGE_4K_SIZE;
3346 uint8_t *pbVmreadBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmreadBitmap;
3347 uint8_t *pbVmwriteBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmwriteBitmap;
3348 ASMMemFill32(pbVmreadBitmap, cbBitmap, UINT32_C(0xffffffff));
3349 ASMMemFill32(pbVmwriteBitmap, cbBitmap, UINT32_C(0xffffffff));
3350
3351 /*
3352 * Skip intercepting VMREAD/VMWRITE to guest read/write fields in the
3353 * VMREAD and VMWRITE bitmaps.
3354 */
3355 {
3356 uint32_t const *paShadowVmcsFields = pVM->hm.s.vmx.paShadowVmcsFields;
3357 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
3358 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
3359 {
3360 uint32_t const uVmcsField = paShadowVmcsFields[i];
3361 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3362 Assert(uVmcsField >> 3 < cbBitmap);
3363 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3364 ASMBitClear(pbVmwriteBitmap + (uVmcsField >> 3), uVmcsField & 7);
3365 }
3366 }
3367
3368 /*
3369 * Skip intercepting VMREAD for guest read-only fields in the VMREAD bitmap
3370 * if the host supports VMWRITE to all supported VMCS fields.
3371 */
3372 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
3373 {
3374 uint32_t const *paShadowVmcsRoFields = pVM->hm.s.vmx.paShadowVmcsRoFields;
3375 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
3376 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
3377 {
3378 uint32_t const uVmcsField = paShadowVmcsRoFields[i];
3379 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3380 Assert(uVmcsField >> 3 < cbBitmap);
3381 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3382 }
3383 }
3384}
3385#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
3386
3387
3388/**
3389 * Sets up the virtual-APIC page address for the VMCS.
3390 *
3391 * @param pVmcsInfo The VMCS info. object.
3392 */
3393DECLINLINE(void) hmR0VmxSetupVmcsVirtApicAddr(PCVMXVMCSINFO pVmcsInfo)
3394{
3395 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
3396 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
3397 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
3398 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
3399 AssertRC(rc);
3400}
3401
3402
3403/**
3404 * Sets up the MSR-bitmap address for the VMCS.
3405 *
3406 * @param pVmcsInfo The VMCS info. object.
3407 */
3408DECLINLINE(void) hmR0VmxSetupVmcsMsrBitmapAddr(PCVMXVMCSINFO pVmcsInfo)
3409{
3410 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
3411 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
3412 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3413 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
3414 AssertRC(rc);
3415}
3416
3417
3418/**
3419 * Sets up the APIC-access page address for the VMCS.
3420 *
3421 * @param pVCpu The cross context virtual CPU structure.
3422 */
3423DECLINLINE(void) hmR0VmxSetupVmcsApicAccessAddr(PVMCPUCC pVCpu)
3424{
3425 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysApicAccess;
3426 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
3427 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
3428 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
3429 AssertRC(rc);
3430}
3431
3432
3433#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3434/**
3435 * Sets up the VMREAD bitmap address for the VMCS.
3436 *
3437 * @param pVCpu The cross context virtual CPU structure.
3438 */
3439DECLINLINE(void) hmR0VmxSetupVmcsVmreadBitmapAddr(PVMCPUCC pVCpu)
3440{
3441 RTHCPHYS const HCPhysVmreadBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmreadBitmap;
3442 Assert(HCPhysVmreadBitmap != NIL_RTHCPHYS);
3443 Assert(!(HCPhysVmreadBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3444 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL, HCPhysVmreadBitmap);
3445 AssertRC(rc);
3446}
3447
3448
3449/**
3450 * Sets up the VMWRITE bitmap address for the VMCS.
3451 *
3452 * @param pVCpu The cross context virtual CPU structure.
3453 */
3454DECLINLINE(void) hmR0VmxSetupVmcsVmwriteBitmapAddr(PVMCPUCC pVCpu)
3455{
3456 RTHCPHYS const HCPhysVmwriteBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmwriteBitmap;
3457 Assert(HCPhysVmwriteBitmap != NIL_RTHCPHYS);
3458 Assert(!(HCPhysVmwriteBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3459 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL, HCPhysVmwriteBitmap);
3460 AssertRC(rc);
3461}
3462#endif
3463
3464
3465/**
3466 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
3467 * in the VMCS.
3468 *
3469 * @returns VBox status code.
3470 * @param pVmcsInfo The VMCS info. object.
3471 */
3472DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMXVMCSINFO pVmcsInfo)
3473{
3474 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
3475 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
3476 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3477
3478 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
3479 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
3480 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
3481
3482 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
3483 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
3484 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3485
3486 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad); AssertRC(rc);
3487 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore); AssertRC(rc);
3488 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad); AssertRC(rc);
3489 return VINF_SUCCESS;
3490}
3491
3492
3493/**
3494 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
3495 *
3496 * @param pVCpu The cross context virtual CPU structure.
3497 * @param pVmcsInfo The VMCS info. object.
3498 */
3499static void hmR0VmxSetupVmcsMsrPermissions(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3500{
3501 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
3502
3503 /*
3504 * The guest can access the following MSRs (read, write) without causing
3505 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
3506 */
3507 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3508 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
3509 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
3510 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
3511 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3512 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
3513
3514 /*
3515 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
3516 * associated with then. We never need to intercept access (writes need to be
3517 * executed without causing a VM-exit, reads will #GP fault anyway).
3518 *
3519 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
3520 * read/write them. We swap the the guest/host MSR value using the
3521 * auto-load/store MSR area.
3522 */
3523 if (pVM->cpum.ro.GuestFeatures.fIbpb)
3524 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
3525 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
3526 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
3527 if (pVM->cpum.ro.GuestFeatures.fIbrs)
3528 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
3529
3530 /*
3531 * Allow full read/write access for the following MSRs (mandatory for VT-x)
3532 * required for 64-bit guests.
3533 */
3534 if (pVM->hm.s.fAllow64BitGuests)
3535 {
3536 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
3537 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
3538 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
3539 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3540 }
3541
3542 /*
3543 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
3544 */
3545#ifdef VBOX_STRICT
3546 Assert(pVmcsInfo->pvMsrBitmap);
3547 uint32_t const fMsrpmEfer = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
3548 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
3549#endif
3550}
3551
3552
3553/**
3554 * Sets up pin-based VM-execution controls in the VMCS.
3555 *
3556 * @returns VBox status code.
3557 * @param pVCpu The cross context virtual CPU structure.
3558 * @param pVmcsInfo The VMCS info. object.
3559 */
3560static int hmR0VmxSetupVmcsPinCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3561{
3562 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3563 uint32_t fVal = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0; /* Bits set here must always be set. */
3564 uint32_t const fZap = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
3565
3566 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
3567 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
3568
3569 if (pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
3570 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
3571
3572 /* Enable the VMX-preemption timer. */
3573 if (pVM->hm.s.vmx.fUsePreemptTimer)
3574 {
3575 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
3576 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
3577 }
3578
3579#if 0
3580 /* Enable posted-interrupt processing. */
3581 if (pVM->hm.s.fPostedIntrs)
3582 {
3583 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
3584 Assert(pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
3585 fVal |= VMX_PIN_CTLS_POSTED_INT;
3586 }
3587#endif
3588
3589 if ((fVal & fZap) != fVal)
3590 {
3591 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3592 pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0, fVal, fZap));
3593 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
3594 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3595 }
3596
3597 /* Commit it to the VMCS and update our cache. */
3598 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
3599 AssertRC(rc);
3600 pVmcsInfo->u32PinCtls = fVal;
3601
3602 return VINF_SUCCESS;
3603}
3604
3605
3606/**
3607 * Sets up secondary processor-based VM-execution controls in the VMCS.
3608 *
3609 * @returns VBox status code.
3610 * @param pVCpu The cross context virtual CPU structure.
3611 * @param pVmcsInfo The VMCS info. object.
3612 */
3613static int hmR0VmxSetupVmcsProcCtls2(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3614{
3615 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3616 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
3617 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3618
3619 /* WBINVD causes a VM-exit. */
3620 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
3621 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
3622
3623 /* Enable EPT (aka nested-paging). */
3624 if (pVM->hm.s.fNestedPaging)
3625 fVal |= VMX_PROC_CTLS2_EPT;
3626
3627 /* Enable the INVPCID instruction if we expose it to the guest and is supported
3628 by the hardware. Without this, guest executing INVPCID would cause a #UD. */
3629 if ( pVM->cpum.ro.GuestFeatures.fInvpcid
3630 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID))
3631 fVal |= VMX_PROC_CTLS2_INVPCID;
3632
3633 /* Enable VPID. */
3634 if (pVM->hm.s.vmx.fVpid)
3635 fVal |= VMX_PROC_CTLS2_VPID;
3636
3637 /* Enable unrestricted guest execution. */
3638 if (pVM->hm.s.vmx.fUnrestrictedGuest)
3639 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
3640
3641#if 0
3642 if (pVM->hm.s.fVirtApicRegs)
3643 {
3644 /* Enable APIC-register virtualization. */
3645 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
3646 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
3647
3648 /* Enable virtual-interrupt delivery. */
3649 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
3650 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
3651 }
3652#endif
3653
3654 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is
3655 where the TPR shadow resides. */
3656 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
3657 * done dynamically. */
3658 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3659 {
3660 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
3661 hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3662 }
3663
3664 /* Enable the RDTSCP instruction if we expose it to the guest and is supported
3665 by the hardware. Without this, guest executing RDTSCP would cause a #UD. */
3666 if ( pVM->cpum.ro.GuestFeatures.fRdTscP
3667 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP))
3668 fVal |= VMX_PROC_CTLS2_RDTSCP;
3669
3670 /* Enable Pause-Loop exiting. */
3671 if ( (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
3672 && pVM->hm.s.vmx.cPleGapTicks
3673 && pVM->hm.s.vmx.cPleWindowTicks)
3674 {
3675 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3676
3677 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks); AssertRC(rc);
3678 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks); AssertRC(rc);
3679 }
3680
3681 if ((fVal & fZap) != fVal)
3682 {
3683 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3684 pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0, fVal, fZap));
3685 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3686 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3687 }
3688
3689 /* Commit it to the VMCS and update our cache. */
3690 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3691 AssertRC(rc);
3692 pVmcsInfo->u32ProcCtls2 = fVal;
3693
3694 return VINF_SUCCESS;
3695}
3696
3697
3698/**
3699 * Sets up processor-based VM-execution controls in the VMCS.
3700 *
3701 * @returns VBox status code.
3702 * @param pVCpu The cross context virtual CPU structure.
3703 * @param pVmcsInfo The VMCS info. object.
3704 */
3705static int hmR0VmxSetupVmcsProcCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3706{
3707 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3708
3709 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3710 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3711
3712 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3713 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3714 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3715 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3716 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3717 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3718 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3719
3720 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3721 if ( !(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3722 || (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3723 {
3724 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3725 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3726 }
3727
3728 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3729 if (!pVM->hm.s.fNestedPaging)
3730 {
3731 Assert(!pVM->hm.s.vmx.fUnrestrictedGuest);
3732 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3733 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3734 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3735 }
3736
3737 /* Use TPR shadowing if supported by the CPU. */
3738 if ( PDMHasApic(pVM)
3739 && pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
3740 {
3741 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
3742 /* CR8 writes cause a VM-exit based on TPR threshold. */
3743 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
3744 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
3745 hmR0VmxSetupVmcsVirtApicAddr(pVmcsInfo);
3746 }
3747 else
3748 {
3749 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
3750 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
3751 if (pVM->hm.s.fAllow64BitGuests)
3752 {
3753 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
3754 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
3755 }
3756 }
3757
3758 /* Use MSR-bitmaps if supported by the CPU. */
3759 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3760 {
3761 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
3762 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
3763 }
3764
3765 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
3766 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3767 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
3768
3769 if ((fVal & fZap) != fVal)
3770 {
3771 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3772 pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0, fVal, fZap));
3773 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
3774 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3775 }
3776
3777 /* Commit it to the VMCS and update our cache. */
3778 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, fVal);
3779 AssertRC(rc);
3780 pVmcsInfo->u32ProcCtls = fVal;
3781
3782 /* Set up MSR permissions that don't change through the lifetime of the VM. */
3783 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3784 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo);
3785
3786 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
3787 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3788 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
3789
3790 /* Sanity check, should not really happen. */
3791 if (RT_LIKELY(!pVM->hm.s.vmx.fUnrestrictedGuest))
3792 { /* likely */ }
3793 else
3794 {
3795 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
3796 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3797 }
3798
3799 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
3800 return VINF_SUCCESS;
3801}
3802
3803
3804/**
3805 * Sets up miscellaneous (everything other than Pin, Processor and secondary
3806 * Processor-based VM-execution) control fields in the VMCS.
3807 *
3808 * @returns VBox status code.
3809 * @param pVCpu The cross context virtual CPU structure.
3810 * @param pVmcsInfo The VMCS info. object.
3811 */
3812static int hmR0VmxSetupVmcsMiscCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3813{
3814#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3815 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
3816 {
3817 hmR0VmxSetupVmcsVmreadBitmapAddr(pVCpu);
3818 hmR0VmxSetupVmcsVmwriteBitmapAddr(pVCpu);
3819 }
3820#endif
3821
3822 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3823 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3824 AssertRC(rc);
3825
3826 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
3827 if (RT_SUCCESS(rc))
3828 {
3829 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
3830 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
3831
3832 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask); AssertRC(rc);
3833 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask); AssertRC(rc);
3834
3835 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
3836 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
3837 return VINF_SUCCESS;
3838 }
3839 else
3840 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
3841 return rc;
3842}
3843
3844
3845/**
3846 * Sets up the initial exception bitmap in the VMCS based on static conditions.
3847 *
3848 * We shall setup those exception intercepts that don't change during the
3849 * lifetime of the VM here. The rest are done dynamically while loading the
3850 * guest state.
3851 *
3852 * @param pVCpu The cross context virtual CPU structure.
3853 * @param pVmcsInfo The VMCS info. object.
3854 */
3855static void hmR0VmxSetupVmcsXcptBitmap(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3856{
3857 /*
3858 * The following exceptions are always intercepted:
3859 *
3860 * #AC - To prevent the guest from hanging the CPU.
3861 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
3862 * recursive #DBs can cause a CPU hang.
3863 * #PF - To sync our shadow page tables when nested-paging is not used.
3864 */
3865 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging;
3866 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
3867 | RT_BIT(X86_XCPT_DB)
3868 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
3869
3870 /* Commit it to the VMCS. */
3871 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
3872 AssertRC(rc);
3873
3874 /* Update our cache of the exception bitmap. */
3875 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
3876}
3877
3878
3879#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3880/**
3881 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
3882 *
3883 * @returns VBox status code.
3884 * @param pVCpu The cross context virtual CPU structure.
3885 * @param pVmcsInfo The VMCS info. object.
3886 */
3887static int hmR0VmxSetupVmcsCtlsNested(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3888{
3889 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3890 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3891 AssertRC(rc);
3892
3893 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
3894 if (RT_SUCCESS(rc))
3895 {
3896 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3897 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
3898 return VINF_SUCCESS;
3899 }
3900 else
3901 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
3902 return rc;
3903}
3904#endif
3905
3906
3907/**
3908 * Sets up the VMCS for executing a guest (or nested-guest) using hardware-assisted
3909 * VMX.
3910 *
3911 * @returns VBox status code.
3912 * @param pVCpu The cross context virtual CPU structure.
3913 * @param pVmcsInfo The VMCS info. object.
3914 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
3915 */
3916static int hmR0VmxSetupVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
3917{
3918 Assert(pVmcsInfo->pvVmcs);
3919 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
3920
3921 /* Set the CPU specified revision identifier at the beginning of the VMCS structure. */
3922 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3923 *(uint32_t *)pVmcsInfo->pvVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
3924 const char * const pszVmcs = fIsNstGstVmcs ? "nested-guest VMCS" : "guest VMCS";
3925
3926 LogFlowFunc(("\n"));
3927
3928 /*
3929 * Initialize the VMCS using VMCLEAR before loading the VMCS.
3930 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
3931 */
3932 int rc = hmR0VmxClearVmcs(pVmcsInfo);
3933 if (RT_SUCCESS(rc))
3934 {
3935 rc = hmR0VmxLoadVmcs(pVmcsInfo);
3936 if (RT_SUCCESS(rc))
3937 {
3938 if (!fIsNstGstVmcs)
3939 {
3940 rc = hmR0VmxSetupVmcsPinCtls(pVCpu, pVmcsInfo);
3941 if (RT_SUCCESS(rc))
3942 {
3943 rc = hmR0VmxSetupVmcsProcCtls(pVCpu, pVmcsInfo);
3944 if (RT_SUCCESS(rc))
3945 {
3946 rc = hmR0VmxSetupVmcsMiscCtls(pVCpu, pVmcsInfo);
3947 if (RT_SUCCESS(rc))
3948 {
3949 hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
3950#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3951 /*
3952 * If a shadow VMCS is allocated for the VMCS info. object, initialize the
3953 * VMCS revision ID and shadow VMCS indicator bit. Also, clear the VMCS
3954 * making it fit for use when VMCS shadowing is later enabled.
3955 */
3956 if (pVmcsInfo->pvShadowVmcs)
3957 {
3958 VMXVMCSREVID VmcsRevId;
3959 VmcsRevId.u = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
3960 VmcsRevId.n.fIsShadowVmcs = 1;
3961 *(uint32_t *)pVmcsInfo->pvShadowVmcs = VmcsRevId.u;
3962 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
3963 if (RT_SUCCESS(rc))
3964 { /* likely */ }
3965 else
3966 LogRelFunc(("Failed to initialize shadow VMCS. rc=%Rrc\n", rc));
3967 }
3968#endif
3969 }
3970 else
3971 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
3972 }
3973 else
3974 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
3975 }
3976 else
3977 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
3978 }
3979 else
3980 {
3981#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3982 rc = hmR0VmxSetupVmcsCtlsNested(pVCpu, pVmcsInfo);
3983 if (RT_SUCCESS(rc))
3984 { /* likely */ }
3985 else
3986 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
3987#else
3988 AssertFailed();
3989#endif
3990 }
3991 }
3992 else
3993 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
3994 }
3995 else
3996 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
3997
3998 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
3999 if (RT_SUCCESS(rc))
4000 {
4001 rc = hmR0VmxClearVmcs(pVmcsInfo);
4002 if (RT_SUCCESS(rc))
4003 { /* likely */ }
4004 else
4005 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
4006 }
4007
4008 /*
4009 * Update the last-error record both for failures and success, so we
4010 * can propagate the status code back to ring-3 for diagnostics.
4011 */
4012 hmR0VmxUpdateErrorRecord(pVCpu, rc);
4013 NOREF(pszVmcs);
4014 return rc;
4015}
4016
4017
4018/**
4019 * Does global VT-x initialization (called during module initialization).
4020 *
4021 * @returns VBox status code.
4022 */
4023VMMR0DECL(int) VMXR0GlobalInit(void)
4024{
4025#ifdef HMVMX_USE_FUNCTION_TABLE
4026 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_apfnVMExitHandlers));
4027# ifdef VBOX_STRICT
4028 for (unsigned i = 0; i < RT_ELEMENTS(g_apfnVMExitHandlers); i++)
4029 Assert(g_apfnVMExitHandlers[i]);
4030# endif
4031#endif
4032 return VINF_SUCCESS;
4033}
4034
4035
4036/**
4037 * Does global VT-x termination (called during module termination).
4038 */
4039VMMR0DECL(void) VMXR0GlobalTerm()
4040{
4041 /* Nothing to do currently. */
4042}
4043
4044
4045/**
4046 * Sets up and activates VT-x on the current CPU.
4047 *
4048 * @returns VBox status code.
4049 * @param pHostCpu The HM physical-CPU structure.
4050 * @param pVM The cross context VM structure. Can be
4051 * NULL after a host resume operation.
4052 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
4053 * fEnabledByHost is @c true).
4054 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
4055 * @a fEnabledByHost is @c true).
4056 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
4057 * enable VT-x on the host.
4058 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
4059 */
4060VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
4061 PCSUPHWVIRTMSRS pHwvirtMsrs)
4062{
4063 AssertPtr(pHostCpu);
4064 AssertPtr(pHwvirtMsrs);
4065 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4066
4067 /* Enable VT-x if it's not already enabled by the host. */
4068 if (!fEnabledByHost)
4069 {
4070 int rc = hmR0VmxEnterRootMode(pVM, HCPhysCpuPage, pvCpuPage);
4071 if (RT_FAILURE(rc))
4072 return rc;
4073 }
4074
4075 /*
4076 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
4077 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
4078 * invalidated when flushing by VPID.
4079 */
4080 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
4081 {
4082 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
4083 pHostCpu->fFlushAsidBeforeUse = false;
4084 }
4085 else
4086 pHostCpu->fFlushAsidBeforeUse = true;
4087
4088 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
4089 ++pHostCpu->cTlbFlushes;
4090
4091 return VINF_SUCCESS;
4092}
4093
4094
4095/**
4096 * Deactivates VT-x on the current CPU.
4097 *
4098 * @returns VBox status code.
4099 * @param pvCpuPage Pointer to the VMXON region.
4100 * @param HCPhysCpuPage Physical address of the VMXON region.
4101 *
4102 * @remarks This function should never be called when SUPR0EnableVTx() or
4103 * similar was used to enable VT-x on the host.
4104 */
4105VMMR0DECL(int) VMXR0DisableCpu(void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
4106{
4107 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
4108
4109 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4110 return hmR0VmxLeaveRootMode();
4111}
4112
4113
4114/**
4115 * Does per-VM VT-x initialization.
4116 *
4117 * @returns VBox status code.
4118 * @param pVM The cross context VM structure.
4119 */
4120VMMR0DECL(int) VMXR0InitVM(PVMCC pVM)
4121{
4122 AssertPtr(pVM);
4123 LogFlowFunc(("pVM=%p\n", pVM));
4124
4125 int rc = hmR0VmxStructsAlloc(pVM);
4126 if (RT_FAILURE(rc))
4127 {
4128 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
4129 return rc;
4130 }
4131
4132 return VINF_SUCCESS;
4133}
4134
4135
4136/**
4137 * Does per-VM VT-x termination.
4138 *
4139 * @returns VBox status code.
4140 * @param pVM The cross context VM structure.
4141 */
4142VMMR0DECL(int) VMXR0TermVM(PVMCC pVM)
4143{
4144 AssertPtr(pVM);
4145 LogFlowFunc(("pVM=%p\n", pVM));
4146
4147#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4148 if (pVM->hm.s.vmx.hMemObjScratch != NIL_RTR0MEMOBJ)
4149 {
4150 Assert(pVM->hm.s.vmx.pvScratch);
4151 ASMMemZero32(pVM->hm.s.vmx.pvScratch, X86_PAGE_4K_SIZE);
4152 }
4153#endif
4154 hmR0VmxStructsFree(pVM);
4155 return VINF_SUCCESS;
4156}
4157
4158
4159/**
4160 * Sets up the VM for execution using hardware-assisted VMX.
4161 * This function is only called once per-VM during initialization.
4162 *
4163 * @returns VBox status code.
4164 * @param pVM The cross context VM structure.
4165 */
4166VMMR0DECL(int) VMXR0SetupVM(PVMCC pVM)
4167{
4168 AssertPtr(pVM);
4169 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4170
4171 LogFlowFunc(("pVM=%p\n", pVM));
4172
4173 /*
4174 * At least verify if VMX is enabled, since we can't check if we're in
4175 * VMX root mode or not without causing a #GP.
4176 */
4177 RTCCUINTREG const uHostCr4 = ASMGetCR4();
4178 if (RT_LIKELY(uHostCr4 & X86_CR4_VMXE))
4179 { /* likely */ }
4180 else
4181 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
4182
4183 /*
4184 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
4185 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
4186 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
4187 */
4188 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
4189 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
4190 || !pVM->hm.s.vmx.pRealModeTSS))
4191 {
4192 LogRelFunc(("Invalid real-on-v86 state.\n"));
4193 return VERR_INTERNAL_ERROR;
4194 }
4195
4196 /* Initialize these always, see hmR3InitFinalizeR0().*/
4197 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
4198 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
4199
4200 /* Setup the tagged-TLB flush handlers. */
4201 int rc = hmR0VmxSetupTaggedTlb(pVM);
4202 if (RT_FAILURE(rc))
4203 {
4204 LogRelFunc(("Failed to setup tagged TLB. rc=%Rrc\n", rc));
4205 return rc;
4206 }
4207
4208#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4209 /* Setup the shadow VMCS fields array and VMREAD/VMWRITE bitmaps. */
4210 if (pVM->hm.s.vmx.fUseVmcsShadowing)
4211 {
4212 rc = hmR0VmxSetupShadowVmcsFieldsArrays(pVM);
4213 if (RT_SUCCESS(rc))
4214 hmR0VmxSetupVmreadVmwriteBitmaps(pVM);
4215 else
4216 {
4217 LogRelFunc(("Failed to setup shadow VMCS fields arrays. rc=%Rrc\n", rc));
4218 return rc;
4219 }
4220 }
4221#endif
4222
4223 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4224 {
4225 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
4226 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
4227
4228 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
4229 if (RT_SUCCESS(rc))
4230 {
4231#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4232 if (pVM->cpum.ro.GuestFeatures.fVmx)
4233 {
4234 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
4235 if (RT_SUCCESS(rc))
4236 { /* likely */ }
4237 else
4238 {
4239 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
4240 return rc;
4241 }
4242 }
4243#endif
4244 }
4245 else
4246 {
4247 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
4248 return rc;
4249 }
4250 }
4251
4252 return VINF_SUCCESS;
4253}
4254
4255
4256/**
4257 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
4258 * the VMCS.
4259 */
4260static void hmR0VmxExportHostControlRegs(void)
4261{
4262 int rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR0, ASMGetCR0()); AssertRC(rc);
4263 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR3, ASMGetCR3()); AssertRC(rc);
4264 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR4, ASMGetCR4()); AssertRC(rc);
4265}
4266
4267
4268/**
4269 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
4270 * the host-state area in the VMCS.
4271 *
4272 * @returns VBox status code.
4273 * @param pVCpu The cross context virtual CPU structure.
4274 */
4275static int hmR0VmxExportHostSegmentRegs(PVMCPUCC pVCpu)
4276{
4277/**
4278 * Macro for adjusting host segment selectors to satisfy VT-x's VM-entry
4279 * requirements. See hmR0VmxExportHostSegmentRegs().
4280 */
4281#define VMXLOCAL_ADJUST_HOST_SEG(a_Seg, a_selValue) \
4282 if ((a_selValue) & (X86_SEL_RPL | X86_SEL_LDT)) \
4283 { \
4284 bool fValidSelector = true; \
4285 if ((a_selValue) & X86_SEL_LDT) \
4286 { \
4287 uint32_t const uAttr = ASMGetSegAttr(a_selValue); \
4288 fValidSelector = RT_BOOL(uAttr != UINT32_MAX && (uAttr & X86_DESC_P)); \
4289 } \
4290 if (fValidSelector) \
4291 { \
4292 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4293 pVCpu->hm.s.vmx.RestoreHost.uHostSel##a_Seg = (a_selValue); \
4294 } \
4295 (a_selValue) = 0; \
4296 }
4297
4298 /*
4299 * If we've executed guest code using hardware-assisted VMX, the host-state bits
4300 * will be messed up. We should -not- save the messed up state without restoring
4301 * the original host-state, see @bugref{7240}.
4302 *
4303 * This apparently can happen (most likely the FPU changes), deal with it rather than
4304 * asserting. Was observed booting Solaris 10u10 32-bit guest.
4305 */
4306 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
4307 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
4308 {
4309 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags,
4310 pVCpu->idCpu));
4311 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
4312 }
4313 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
4314
4315 /*
4316 * Host segment registers.
4317 */
4318 RTSEL uSelES = ASMGetES();
4319 RTSEL uSelCS = ASMGetCS();
4320 RTSEL uSelSS = ASMGetSS();
4321 RTSEL uSelDS = ASMGetDS();
4322 RTSEL uSelFS = ASMGetFS();
4323 RTSEL uSelGS = ASMGetGS();
4324 RTSEL uSelTR = ASMGetTR();
4325
4326 /*
4327 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
4328 * gain VM-entry and restore them before we get preempted.
4329 *
4330 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
4331 */
4332 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4333 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4334 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4335 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4336
4337 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
4338 Assert(!(uSelCS & X86_SEL_RPL)); Assert(!(uSelCS & X86_SEL_LDT));
4339 Assert(!(uSelSS & X86_SEL_RPL)); Assert(!(uSelSS & X86_SEL_LDT));
4340 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
4341 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
4342 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
4343 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
4344 Assert(!(uSelTR & X86_SEL_RPL)); Assert(!(uSelTR & X86_SEL_LDT));
4345 Assert(uSelCS);
4346 Assert(uSelTR);
4347
4348 /* Write these host selector fields into the host-state area in the VMCS. */
4349 int rc = VMXWriteVmcs16(VMX_VMCS16_HOST_CS_SEL, uSelCS); AssertRC(rc);
4350 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_SS_SEL, uSelSS); AssertRC(rc);
4351 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_DS_SEL, uSelDS); AssertRC(rc);
4352 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_ES_SEL, uSelES); AssertRC(rc);
4353 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_FS_SEL, uSelFS); AssertRC(rc);
4354 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_GS_SEL, uSelGS); AssertRC(rc);
4355 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_TR_SEL, uSelTR); AssertRC(rc);
4356
4357 /*
4358 * Host GDTR and IDTR.
4359 */
4360 RTGDTR Gdtr;
4361 RTIDTR Idtr;
4362 RT_ZERO(Gdtr);
4363 RT_ZERO(Idtr);
4364 ASMGetGDTR(&Gdtr);
4365 ASMGetIDTR(&Idtr);
4366 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GDTR_BASE, Gdtr.pGdt); AssertRC(rc);
4367 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_IDTR_BASE, Idtr.pIdt); AssertRC(rc);
4368
4369 /*
4370 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
4371 * them to the maximum limit (0xffff) on every VM-exit.
4372 */
4373 if (Gdtr.cbGdt != 0xffff)
4374 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
4375
4376 /*
4377 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
4378 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
4379 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
4380 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
4381 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
4382 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
4383 * at 0xffff on hosts where we are sure it won't cause trouble.
4384 */
4385#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
4386 if (Idtr.cbIdt < 0x0fff)
4387#else
4388 if (Idtr.cbIdt != 0xffff)
4389#endif
4390 {
4391 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4392 AssertCompile(sizeof(Idtr) == sizeof(X86XDTR64));
4393 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostIdtr, &Idtr, sizeof(X86XDTR64));
4394 }
4395
4396 /*
4397 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4398 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4399 * RPL should be too in most cases.
4400 */
4401 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= Gdtr.cbGdt,
4402 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, Gdtr.cbGdt), VERR_VMX_INVALID_HOST_STATE);
4403
4404 PCX86DESCHC pDesc = (PCX86DESCHC)(Gdtr.pGdt + (uSelTR & X86_SEL_MASK));
4405 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4406
4407 /*
4408 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4409 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4410 * restoration if the host has something else. Task switching is not supported in 64-bit
4411 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4412 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4413 *
4414 * [1] See Intel spec. 3.5 "System Descriptor Types".
4415 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4416 */
4417 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4418 Assert(pDesc->System.u4Type == 11);
4419 if ( pDesc->System.u16LimitLow != 0x67
4420 || pDesc->System.u4LimitHigh)
4421 {
4422 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4423 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4424 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4425 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4426 pVCpu->hm.s.vmx.RestoreHost.uHostSelTR = uSelTR;
4427 }
4428
4429 /*
4430 * Store the GDTR as we need it when restoring the GDT and while restoring the TR.
4431 */
4432 if (pVCpu->hm.s.vmx.fRestoreHostFlags & (VMX_RESTORE_HOST_GDTR | VMX_RESTORE_HOST_SEL_TR))
4433 {
4434 AssertCompile(sizeof(Gdtr) == sizeof(X86XDTR64));
4435 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostGdtr, &Gdtr, sizeof(X86XDTR64));
4436 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4437 {
4438 /* The GDT is read-only but the writable GDT is available. */
4439 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4440 pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.cb = Gdtr.cbGdt;
4441 rc = SUPR0GetCurrentGdtRw(&pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4442 AssertRCReturn(rc, rc);
4443 }
4444 }
4445
4446 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_TR_BASE, uTRBase);
4447 AssertRC(rc);
4448
4449 /*
4450 * Host FS base and GS base.
4451 */
4452 uint64_t const u64FSBase = ASMRdMsr(MSR_K8_FS_BASE);
4453 uint64_t const u64GSBase = ASMRdMsr(MSR_K8_GS_BASE);
4454 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_FS_BASE, u64FSBase); AssertRC(rc);
4455 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GS_BASE, u64GSBase); AssertRC(rc);
4456
4457 /* Store the base if we have to restore FS or GS manually as we need to restore the base as well. */
4458 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_FS)
4459 pVCpu->hm.s.vmx.RestoreHost.uHostFSBase = u64FSBase;
4460 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_GS)
4461 pVCpu->hm.s.vmx.RestoreHost.uHostGSBase = u64GSBase;
4462
4463 return VINF_SUCCESS;
4464#undef VMXLOCAL_ADJUST_HOST_SEG
4465}
4466
4467
4468/**
4469 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4470 * host-state area of the VMCS.
4471 *
4472 * These MSRs will be automatically restored on the host after every successful
4473 * VM-exit.
4474 *
4475 * @param pVCpu The cross context virtual CPU structure.
4476 *
4477 * @remarks No-long-jump zone!!!
4478 */
4479static void hmR0VmxExportHostMsrs(PVMCPUCC pVCpu)
4480{
4481 AssertPtr(pVCpu);
4482
4483 /*
4484 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4485 * rather than swapping them on every VM-entry.
4486 */
4487 hmR0VmxLazySaveHostMsrs(pVCpu);
4488
4489 /*
4490 * Host Sysenter MSRs.
4491 */
4492 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS)); AssertRC(rc);
4493 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP)); AssertRC(rc);
4494 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP)); AssertRC(rc);
4495
4496 /*
4497 * Host EFER MSR.
4498 *
4499 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4500 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4501 */
4502 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4503 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
4504 {
4505 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, pVM->hm.s.vmx.u64HostMsrEfer);
4506 AssertRC(rc);
4507 }
4508
4509 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4510 * hmR0VmxExportGuestEntryExitCtls(). */
4511}
4512
4513
4514/**
4515 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4516 *
4517 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4518 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4519 *
4520 * @returns true if we need to load guest EFER, false otherwise.
4521 * @param pVCpu The cross context virtual CPU structure.
4522 *
4523 * @remarks Requires EFER, CR4.
4524 * @remarks No-long-jump zone!!!
4525 */
4526static bool hmR0VmxShouldSwapEferMsr(PCVMCPUCC pVCpu)
4527{
4528#ifdef HMVMX_ALWAYS_SWAP_EFER
4529 RT_NOREF(pVCpu);
4530 return true;
4531#else
4532 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4533 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4534 uint64_t const u64HostEfer = pVM->hm.s.vmx.u64HostMsrEfer;
4535 uint64_t const u64GuestEfer = pCtx->msrEFER;
4536
4537 /*
4538 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4539 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4540 */
4541 if ( CPUMIsGuestInLongModeEx(pCtx)
4542 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4543 return true;
4544
4545 /*
4546 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4547 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4548 *
4549 * See Intel spec. 4.5 "IA-32e Paging".
4550 * See Intel spec. 4.1.1 "Three Paging Modes".
4551 *
4552 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4553 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4554 */
4555 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4556 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4557 if ( (pCtx->cr4 & X86_CR4_PAE)
4558 && (pCtx->cr0 & X86_CR0_PG)
4559 && (u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4560 {
4561 /* Assert that host is NX capable. */
4562 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4563 return true;
4564 }
4565
4566 return false;
4567#endif
4568}
4569
4570/**
4571 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
4572 * VMCS.
4573 *
4574 * This is typically required when the guest changes paging mode.
4575 *
4576 * @returns VBox status code.
4577 * @param pVCpu The cross context virtual CPU structure.
4578 * @param pVmxTransient The VMX-transient structure.
4579 *
4580 * @remarks Requires EFER.
4581 * @remarks No-long-jump zone!!!
4582 */
4583static int hmR0VmxExportGuestEntryExitCtls(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
4584{
4585 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
4586 {
4587 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4588 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4589
4590 /*
4591 * VM-entry controls.
4592 */
4593 {
4594 uint32_t fVal = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4595 uint32_t const fZap = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4596
4597 /*
4598 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
4599 * The first VT-x capable CPUs only supported the 1-setting of this bit.
4600 *
4601 * For nested-guests, this is a mandatory VM-entry control. It's also
4602 * required because we do not want to leak host bits to the nested-guest.
4603 */
4604 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
4605
4606 /*
4607 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
4608 *
4609 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
4610 * required to get the nested-guest working with hardware-assisted VMX execution.
4611 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a guest hypervisor
4612 * can skip intercepting changes to the EFER MSR. This is why it it needs to be done
4613 * here rather than while merging the guest VMCS controls.
4614 */
4615 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
4616 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
4617 else
4618 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
4619
4620 /*
4621 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
4622 *
4623 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
4624 * regardless of whether the nested-guest VMCS specifies it because we are free to
4625 * load whatever MSRs we require and we do not need to modify the guest visible copy
4626 * of the VM-entry MSR load area.
4627 */
4628 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4629 && hmR0VmxShouldSwapEferMsr(pVCpu))
4630 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
4631 else
4632 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
4633
4634 /*
4635 * The following should -not- be set (since we're not in SMM mode):
4636 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
4637 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
4638 */
4639
4640 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
4641 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
4642
4643 if ((fVal & fZap) == fVal)
4644 { /* likely */ }
4645 else
4646 {
4647 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
4648 pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0, fVal, fZap));
4649 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
4650 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4651 }
4652
4653 /* Commit it to the VMCS. */
4654 if (pVmcsInfo->u32EntryCtls != fVal)
4655 {
4656 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
4657 AssertRC(rc);
4658 pVmcsInfo->u32EntryCtls = fVal;
4659 }
4660 }
4661
4662 /*
4663 * VM-exit controls.
4664 */
4665 {
4666 uint32_t fVal = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4667 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4668
4669 /*
4670 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
4671 * supported the 1-setting of this bit.
4672 *
4673 * For nested-guests, we set the "save debug controls" as the converse
4674 * "load debug controls" is mandatory for nested-guests anyway.
4675 */
4676 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
4677
4678 /*
4679 * Set the host long mode active (EFER.LMA) bit (which Intel calls
4680 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
4681 * host EFER.LMA and EFER.LME bit to this value. See assertion in
4682 * hmR0VmxExportHostMsrs().
4683 *
4684 * For nested-guests, we always set this bit as we do not support 32-bit
4685 * hosts.
4686 */
4687 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
4688
4689 /*
4690 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
4691 *
4692 * For nested-guests, we should use the "save IA32_EFER" control if we also
4693 * used the "load IA32_EFER" control while exporting VM-entry controls.
4694 */
4695 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4696 && hmR0VmxShouldSwapEferMsr(pVCpu))
4697 {
4698 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
4699 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
4700 }
4701
4702 /*
4703 * Enable saving of the VMX-preemption timer value on VM-exit.
4704 * For nested-guests, currently not exposed/used.
4705 */
4706 if ( pVM->hm.s.vmx.fUsePreemptTimer
4707 && (pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER))
4708 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
4709
4710 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
4711 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
4712
4713 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
4714 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
4715 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
4716
4717 if ((fVal & fZap) == fVal)
4718 { /* likely */ }
4719 else
4720 {
4721 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
4722 pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0, fVal, fZap));
4723 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
4724 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4725 }
4726
4727 /* Commit it to the VMCS. */
4728 if (pVmcsInfo->u32ExitCtls != fVal)
4729 {
4730 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
4731 AssertRC(rc);
4732 pVmcsInfo->u32ExitCtls = fVal;
4733 }
4734 }
4735
4736 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
4737 }
4738 return VINF_SUCCESS;
4739}
4740
4741
4742/**
4743 * Sets the TPR threshold in the VMCS.
4744 *
4745 * @param pVmcsInfo The VMCS info. object.
4746 * @param u32TprThreshold The TPR threshold (task-priority class only).
4747 */
4748DECLINLINE(void) hmR0VmxApicSetTprThreshold(PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
4749{
4750 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
4751 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
4752 RT_NOREF(pVmcsInfo);
4753 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
4754 AssertRC(rc);
4755}
4756
4757
4758/**
4759 * Exports the guest APIC TPR state into the VMCS.
4760 *
4761 * @returns VBox status code.
4762 * @param pVCpu The cross context virtual CPU structure.
4763 * @param pVmxTransient The VMX-transient structure.
4764 *
4765 * @remarks No-long-jump zone!!!
4766 */
4767static int hmR0VmxExportGuestApicTpr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
4768{
4769 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
4770 {
4771 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
4772
4773 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4774 if (!pVmxTransient->fIsNestedGuest)
4775 {
4776 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
4777 && APICIsEnabled(pVCpu))
4778 {
4779 /*
4780 * Setup TPR shadowing.
4781 */
4782 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
4783 {
4784 bool fPendingIntr = false;
4785 uint8_t u8Tpr = 0;
4786 uint8_t u8PendingIntr = 0;
4787 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
4788 AssertRCReturn(rc, rc);
4789
4790 /*
4791 * If there are interrupts pending but masked by the TPR, instruct VT-x to
4792 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
4793 * priority of the pending interrupt so we can deliver the interrupt. If there
4794 * are no interrupts pending, set threshold to 0 to not cause any
4795 * TPR-below-threshold VM-exits.
4796 */
4797 uint32_t u32TprThreshold = 0;
4798 if (fPendingIntr)
4799 {
4800 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
4801 (which is the Task-Priority Class). */
4802 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
4803 const uint8_t u8TprPriority = u8Tpr >> 4;
4804 if (u8PendingPriority <= u8TprPriority)
4805 u32TprThreshold = u8PendingPriority;
4806 }
4807
4808 hmR0VmxApicSetTprThreshold(pVmcsInfo, u32TprThreshold);
4809 }
4810 }
4811 }
4812 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
4813 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
4814 }
4815 return VINF_SUCCESS;
4816}
4817
4818
4819/**
4820 * Gets the guest interruptibility-state.
4821 *
4822 * @returns Guest's interruptibility-state.
4823 * @param pVCpu The cross context virtual CPU structure.
4824 * @param pVmxTransient The VMX-transient structure.
4825 *
4826 * @remarks No-long-jump zone!!!
4827 */
4828static uint32_t hmR0VmxGetGuestIntrState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
4829{
4830 /*
4831 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
4832 */
4833 uint32_t fIntrState = 0;
4834 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
4835 {
4836 /* If inhibition is active, RIP and RFLAGS should've been imported from the VMCS already. */
4837 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
4838
4839 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4840 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
4841 {
4842 if (pCtx->eflags.Bits.u1IF)
4843 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
4844 else
4845 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
4846 }
4847 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
4848 {
4849 /*
4850 * We can clear the inhibit force flag as even if we go back to the recompiler
4851 * without executing guest code in VT-x, the flag's condition to be cleared is
4852 * met and thus the cleared state is correct.
4853 */
4854 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
4855 }
4856 }
4857
4858 /*
4859 * NMIs to the guest are blocked after an NMI is injected until the guest executes an IRET. We only
4860 * bother with virtual-NMI blocking when we have support for virtual NMIs in the CPU, otherwise
4861 * setting this would block host-NMIs and IRET will not clear the blocking.
4862 *
4863 * We always set NMI-exiting so when the host receives an NMI we get a VM-exit.
4864 *
4865 * See Intel spec. 26.6.1 "Interruptibility state". See @bugref{7445}.
4866 */
4867 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4868 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
4869 && CPUMIsGuestNmiBlocking(pVCpu))
4870 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
4871
4872 return fIntrState;
4873}
4874
4875
4876/**
4877 * Exports the exception intercepts required for guest execution in the VMCS.
4878 *
4879 * @returns VBox status code.
4880 * @param pVCpu The cross context virtual CPU structure.
4881 * @param pVmxTransient The VMX-transient structure.
4882 *
4883 * @remarks No-long-jump zone!!!
4884 */
4885static int hmR0VmxExportGuestXcptIntercepts(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
4886{
4887 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
4888 {
4889 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
4890 if ( !pVmxTransient->fIsNestedGuest
4891 && pVCpu->hm.s.fGIMTrapXcptUD)
4892 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
4893 else
4894 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
4895
4896 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
4897 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
4898 }
4899 return VINF_SUCCESS;
4900}
4901
4902
4903/**
4904 * Exports the guest's RIP into the guest-state area in the VMCS.
4905 *
4906 * @returns VBox status code.
4907 * @param pVCpu The cross context virtual CPU structure.
4908 *
4909 * @remarks No-long-jump zone!!!
4910 */
4911static int hmR0VmxExportGuestRip(PVMCPUCC pVCpu)
4912{
4913 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
4914 {
4915 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
4916
4917 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
4918 AssertRC(rc);
4919
4920 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
4921 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
4922 }
4923 return VINF_SUCCESS;
4924}
4925
4926
4927/**
4928 * Exports the guest's RSP into the guest-state area in the VMCS.
4929 *
4930 * @returns VBox status code.
4931 * @param pVCpu The cross context virtual CPU structure.
4932 *
4933 * @remarks No-long-jump zone!!!
4934 */
4935static int hmR0VmxExportGuestRsp(PVMCPUCC pVCpu)
4936{
4937 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
4938 {
4939 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
4940
4941 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
4942 AssertRC(rc);
4943
4944 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
4945 Log4Func(("rsp=%#RX64\n", pVCpu->cpum.GstCtx.rsp));
4946 }
4947 return VINF_SUCCESS;
4948}
4949
4950
4951/**
4952 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
4953 *
4954 * @returns VBox status code.
4955 * @param pVCpu The cross context virtual CPU structure.
4956 * @param pVmxTransient The VMX-transient structure.
4957 *
4958 * @remarks No-long-jump zone!!!
4959 */
4960static int hmR0VmxExportGuestRflags(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
4961{
4962 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
4963 {
4964 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
4965
4966 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
4967 Let us assert it as such and use 32-bit VMWRITE. */
4968 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
4969 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
4970 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
4971 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
4972
4973 /*
4974 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
4975 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
4976 * can run the real-mode guest code under Virtual 8086 mode.
4977 */
4978 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4979 if (pVmcsInfo->RealMode.fRealOnV86Active)
4980 {
4981 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
4982 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
4983 Assert(!pVmxTransient->fIsNestedGuest);
4984 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
4985 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
4986 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
4987 }
4988
4989 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
4990 AssertRC(rc);
4991
4992 /*
4993 * Setup pending debug exceptions if the guest is single-stepping using EFLAGS.TF.
4994 *
4995 * We must avoid setting any automatic debug exceptions delivery when single-stepping
4996 * through the hypervisor debugger using EFLAGS.TF.
4997 */
4998 if ( !pVmxTransient->fIsNestedGuest
4999 && !pVCpu->hm.s.fSingleInstruction
5000 && fEFlags.Bits.u1TF)
5001 {
5002 /** @todo r=ramshankar: Warning!! We ASSUME EFLAGS.TF will not cleared on
5003 * premature trips to ring-3 esp since IEM does not yet handle it. */
5004 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BS);
5005 AssertRC(rc);
5006 }
5007 /* else: for nested-guest currently handling while merging controls. */
5008
5009 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5010 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5011 }
5012 return VINF_SUCCESS;
5013}
5014
5015
5016#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5017/**
5018 * Copies the nested-guest VMCS to the shadow VMCS.
5019 *
5020 * @returns VBox status code.
5021 * @param pVCpu The cross context virtual CPU structure.
5022 * @param pVmcsInfo The VMCS info. object.
5023 *
5024 * @remarks No-long-jump zone!!!
5025 */
5026static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5027{
5028 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5029 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5030
5031 /*
5032 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5033 * current VMCS, as we may try saving guest lazy MSRs.
5034 *
5035 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5036 * calling the import VMCS code which is currently performing the guest MSR reads
5037 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5038 * and the rest of the VMX leave session machinery.
5039 */
5040 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5041
5042 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5043 if (RT_SUCCESS(rc))
5044 {
5045 /*
5046 * Copy all guest read/write VMCS fields.
5047 *
5048 * We don't check for VMWRITE failures here for performance reasons and
5049 * because they are not expected to fail, barring irrecoverable conditions
5050 * like hardware errors.
5051 */
5052 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5053 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5054 {
5055 uint64_t u64Val;
5056 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5057 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5058 VMXWriteVmcs64(uVmcsField, u64Val);
5059 }
5060
5061 /*
5062 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5063 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5064 */
5065 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
5066 {
5067 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
5068 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5069 {
5070 uint64_t u64Val;
5071 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsRoFields[i];
5072 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5073 VMXWriteVmcs64(uVmcsField, u64Val);
5074 }
5075 }
5076
5077 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5078 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5079 }
5080
5081 ASMSetFlags(fEFlags);
5082 return rc;
5083}
5084
5085
5086/**
5087 * Copies the shadow VMCS to the nested-guest VMCS.
5088 *
5089 * @returns VBox status code.
5090 * @param pVCpu The cross context virtual CPU structure.
5091 * @param pVmcsInfo The VMCS info. object.
5092 *
5093 * @remarks Called with interrupts disabled.
5094 */
5095static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5096{
5097 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5098 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5099 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5100
5101 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5102 if (RT_SUCCESS(rc))
5103 {
5104 /*
5105 * Copy guest read/write fields from the shadow VMCS.
5106 * Guest read-only fields cannot be modified, so no need to copy them.
5107 *
5108 * We don't check for VMREAD failures here for performance reasons and
5109 * because they are not expected to fail, barring irrecoverable conditions
5110 * like hardware errors.
5111 */
5112 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5113 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5114 {
5115 uint64_t u64Val;
5116 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5117 VMXReadVmcs64(uVmcsField, &u64Val);
5118 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5119 }
5120
5121 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5122 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5123 }
5124 return rc;
5125}
5126
5127
5128/**
5129 * Enables VMCS shadowing for the given VMCS info. object.
5130 *
5131 * @param pVmcsInfo The VMCS info. object.
5132 *
5133 * @remarks No-long-jump zone!!!
5134 */
5135static void hmR0VmxEnableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5136{
5137 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5138 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5139 {
5140 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5141 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5142 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5143 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs); AssertRC(rc);
5144 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5145 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5146 Log4Func(("Enabled\n"));
5147 }
5148}
5149
5150
5151/**
5152 * Disables VMCS shadowing for the given VMCS info. object.
5153 *
5154 * @param pVmcsInfo The VMCS info. object.
5155 *
5156 * @remarks No-long-jump zone!!!
5157 */
5158static void hmR0VmxDisableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5159{
5160 /*
5161 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5162 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5163 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5164 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5165 *
5166 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5167 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5168 */
5169 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5170 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5171 {
5172 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5173 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5174 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS); AssertRC(rc);
5175 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5176 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5177 Log4Func(("Disabled\n"));
5178 }
5179}
5180#endif
5181
5182
5183/**
5184 * Exports the guest hardware-virtualization state.
5185 *
5186 * @returns VBox status code.
5187 * @param pVCpu The cross context virtual CPU structure.
5188 * @param pVmxTransient The VMX-transient structure.
5189 *
5190 * @remarks No-long-jump zone!!!
5191 */
5192static int hmR0VmxExportGuestHwvirtState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
5193{
5194 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5195 {
5196#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5197 /*
5198 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5199 * VMCS shadowing.
5200 */
5201 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
5202 {
5203 /*
5204 * If the guest hypervisor has loaded a current VMCS and is in VMX root mode,
5205 * copy the guest hypervisor's current VMCS into the shadow VMCS and enable
5206 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5207 *
5208 * We check for VMX root mode here in case the guest executes VMXOFF without
5209 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5210 * not clear the current VMCS pointer.
5211 */
5212 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5213 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5214 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5215 && CPUMIsGuestVmxCurrentVmcsValid(pVCpu, &pVCpu->cpum.GstCtx))
5216 {
5217 /* Paranoia. */
5218 Assert(!pVmxTransient->fIsNestedGuest);
5219
5220 /*
5221 * For performance reasons, also check if the guest hypervisor's current VMCS
5222 * was newly loaded or modified before copying it to the shadow VMCS.
5223 */
5224 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5225 {
5226 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5227 AssertRCReturn(rc, rc);
5228 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5229 }
5230 hmR0VmxEnableVmcsShadowing(pVmcsInfo);
5231 }
5232 else
5233 hmR0VmxDisableVmcsShadowing(pVmcsInfo);
5234 }
5235#else
5236 NOREF(pVmxTransient);
5237#endif
5238 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5239 }
5240 return VINF_SUCCESS;
5241}
5242
5243
5244/**
5245 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5246 *
5247 * The guest FPU state is always pre-loaded hence we don't need to bother about
5248 * sharing FPU related CR0 bits between the guest and host.
5249 *
5250 * @returns VBox status code.
5251 * @param pVCpu The cross context virtual CPU structure.
5252 * @param pVmxTransient The VMX-transient structure.
5253 *
5254 * @remarks No-long-jump zone!!!
5255 */
5256static int hmR0VmxExportGuestCR0(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
5257{
5258 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5259 {
5260 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5261 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5262
5263 /*
5264 * Figure out fixed CR0 bits in VMX operation.
5265 */
5266 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
5267 uint64_t fSetCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5268 uint64_t const fZapCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5269 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5270 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5271 else
5272 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5273
5274 if (!pVmxTransient->fIsNestedGuest)
5275 {
5276 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5277 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5278 uint64_t const u64ShadowCr0 = u64GuestCr0;
5279 Assert(!RT_HI_U32(u64GuestCr0));
5280
5281 /*
5282 * Setup VT-x's view of the guest CR0.
5283 */
5284 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5285 if (pVM->hm.s.fNestedPaging)
5286 {
5287 if (CPUMIsGuestPagingEnabled(pVCpu))
5288 {
5289 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5290 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5291 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5292 }
5293 else
5294 {
5295 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5296 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5297 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5298 }
5299
5300 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5301 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5302 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5303 }
5304 else
5305 {
5306 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5307 u64GuestCr0 |= X86_CR0_WP;
5308 }
5309
5310 /*
5311 * Guest FPU bits.
5312 *
5313 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5314 * using CR0.TS.
5315 *
5316 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5317 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5318 */
5319 u64GuestCr0 |= X86_CR0_NE;
5320
5321 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5322 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5323
5324 /*
5325 * Update exception intercepts.
5326 */
5327 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5328 if (pVmcsInfo->RealMode.fRealOnV86Active)
5329 {
5330 Assert(PDMVmmDevHeapIsEnabled(pVM));
5331 Assert(pVM->hm.s.vmx.pRealModeTSS);
5332 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5333 }
5334 else
5335 {
5336 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5337 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5338 if (fInterceptMF)
5339 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5340 }
5341
5342 /* Additional intercepts for debugging, define these yourself explicitly. */
5343#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5344 uXcptBitmap |= 0
5345 | RT_BIT(X86_XCPT_BP)
5346 | RT_BIT(X86_XCPT_DE)
5347 | RT_BIT(X86_XCPT_NM)
5348 | RT_BIT(X86_XCPT_TS)
5349 | RT_BIT(X86_XCPT_UD)
5350 | RT_BIT(X86_XCPT_NP)
5351 | RT_BIT(X86_XCPT_SS)
5352 | RT_BIT(X86_XCPT_GP)
5353 | RT_BIT(X86_XCPT_PF)
5354 | RT_BIT(X86_XCPT_MF)
5355 ;
5356#elif defined(HMVMX_ALWAYS_TRAP_PF)
5357 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5358#endif
5359 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5360 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5361 Assert(pVM->hm.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5362
5363 /* Apply the hardware specified fixed CR0 bits and enable caching. */
5364 u64GuestCr0 |= fSetCr0;
5365 u64GuestCr0 &= fZapCr0;
5366 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5367
5368 /* Commit the CR0 and related fields to the guest VMCS. */
5369 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5370 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5371 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5372 {
5373 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5374 AssertRC(rc);
5375 }
5376 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5377 {
5378 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5379 AssertRC(rc);
5380 }
5381
5382 /* Update our caches. */
5383 pVmcsInfo->u32ProcCtls = uProcCtls;
5384 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5385
5386 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5387 }
5388 else
5389 {
5390 /*
5391 * With nested-guests, we may have extended the guest/host mask here since we
5392 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5393 * (to read from the nested-guest CR0 read-shadow) than the guest hypervisor
5394 * originally supplied. We must copy those bits from the nested-guest CR0 into
5395 * the nested-guest CR0 read-shadow.
5396 */
5397 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5398 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5399 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(pVCpu, &pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5400 Assert(!RT_HI_U32(u64GuestCr0));
5401 Assert(u64GuestCr0 & X86_CR0_NE);
5402
5403 /*
5404 * Apply the hardware specified fixed CR0 bits and enable caching.
5405 * Note! We could be altering our VMX emulation's fixed bits. We thus
5406 * need to re-apply them while importing CR0.
5407 */
5408 u64GuestCr0 |= fSetCr0;
5409 u64GuestCr0 &= fZapCr0;
5410 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5411
5412 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5413 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5414 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5415
5416 Log4Func(("cr0=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5417 }
5418
5419 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5420 }
5421
5422 return VINF_SUCCESS;
5423}
5424
5425
5426/**
5427 * Exports the guest control registers (CR3, CR4) into the guest-state area
5428 * in the VMCS.
5429 *
5430 * @returns VBox strict status code.
5431 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5432 * without unrestricted guest access and the VMMDev is not presently
5433 * mapped (e.g. EFI32).
5434 *
5435 * @param pVCpu The cross context virtual CPU structure.
5436 * @param pVmxTransient The VMX-transient structure.
5437 *
5438 * @remarks No-long-jump zone!!!
5439 */
5440static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
5441{
5442 int rc = VINF_SUCCESS;
5443 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5444
5445 /*
5446 * Guest CR2.
5447 * It's always loaded in the assembler code. Nothing to do here.
5448 */
5449
5450 /*
5451 * Guest CR3.
5452 */
5453 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5454 {
5455 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5456
5457 if (pVM->hm.s.fNestedPaging)
5458 {
5459 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5460 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5461
5462 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5463 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5464 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5465 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5466
5467 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5468 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5469 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5470
5471 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5472 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5473 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5474 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5475 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5476 || (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5477 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5478
5479 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5480 AssertRC(rc);
5481
5482 uint64_t u64GuestCr3;
5483 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5484 if ( pVM->hm.s.vmx.fUnrestrictedGuest
5485 || CPUMIsGuestPagingEnabledEx(pCtx))
5486 {
5487 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5488 if (CPUMIsGuestInPAEModeEx(pCtx))
5489 {
5490 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5491 AssertRC(rc);
5492 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
5493 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
5494 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
5495 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
5496 }
5497
5498 /*
5499 * The guest's view of its CR3 is unblemished with nested paging when the
5500 * guest is using paging or we have unrestricted guest execution to handle
5501 * the guest when it's not using paging.
5502 */
5503 u64GuestCr3 = pCtx->cr3;
5504 }
5505 else
5506 {
5507 /*
5508 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5509 * thinks it accesses physical memory directly, we use our identity-mapped
5510 * page table to map guest-linear to guest-physical addresses. EPT takes care
5511 * of translating it to host-physical addresses.
5512 */
5513 RTGCPHYS GCPhys;
5514 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5515
5516 /* We obtain it here every time as the guest could have relocated this PCI region. */
5517 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5518 if (RT_SUCCESS(rc))
5519 { /* likely */ }
5520 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5521 {
5522 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5523 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5524 }
5525 else
5526 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5527
5528 u64GuestCr3 = GCPhys;
5529 }
5530
5531 Log4Func(("guest_cr3=%#RX64 (GstN)\n", u64GuestCr3));
5532 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, u64GuestCr3);
5533 AssertRC(rc);
5534 }
5535 else
5536 {
5537 /* Non-nested paging case, just use the hypervisor's CR3. */
5538 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5539
5540 Log4Func(("guest_cr3=%#RX64 (HstN)\n", HCPhysGuestCr3));
5541 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5542 AssertRC(rc);
5543 }
5544
5545 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5546 }
5547
5548 /*
5549 * Guest CR4.
5550 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
5551 */
5552 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
5553 {
5554 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5555 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5556
5557 /*
5558 * Figure out fixed CR4 bits in VMX operation.
5559 */
5560 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
5561 uint64_t const fSetCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5562 uint64_t const fZapCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5563
5564 /*
5565 * With nested-guests, we may have extended the guest/host mask here (since we
5566 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
5567 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
5568 * the guest hypervisor originally supplied. Thus, we should, in essence, copy
5569 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
5570 */
5571 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
5572 uint64_t u64GuestCr4 = pCtx->cr4;
5573 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
5574 ? pCtx->cr4
5575 : CPUMGetGuestVmxMaskedCr4(pVCpu, pCtx, pVmcsInfo->u64Cr4Mask);
5576 Assert(!RT_HI_U32(u64GuestCr4));
5577
5578 /*
5579 * Setup VT-x's view of the guest CR4.
5580 *
5581 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
5582 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
5583 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
5584 *
5585 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
5586 */
5587 if (pVmcsInfo->RealMode.fRealOnV86Active)
5588 {
5589 Assert(pVM->hm.s.vmx.pRealModeTSS);
5590 Assert(PDMVmmDevHeapIsEnabled(pVM));
5591 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
5592 }
5593
5594 if (pVM->hm.s.fNestedPaging)
5595 {
5596 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
5597 && !pVM->hm.s.vmx.fUnrestrictedGuest)
5598 {
5599 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
5600 u64GuestCr4 |= X86_CR4_PSE;
5601 /* Our identity mapping is a 32-bit page directory. */
5602 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5603 }
5604 /* else use guest CR4.*/
5605 }
5606 else
5607 {
5608 Assert(!pVmxTransient->fIsNestedGuest);
5609
5610 /*
5611 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
5612 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
5613 */
5614 switch (pVCpu->hm.s.enmShadowMode)
5615 {
5616 case PGMMODE_REAL: /* Real-mode. */
5617 case PGMMODE_PROTECTED: /* Protected mode without paging. */
5618 case PGMMODE_32_BIT: /* 32-bit paging. */
5619 {
5620 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5621 break;
5622 }
5623
5624 case PGMMODE_PAE: /* PAE paging. */
5625 case PGMMODE_PAE_NX: /* PAE paging with NX. */
5626 {
5627 u64GuestCr4 |= X86_CR4_PAE;
5628 break;
5629 }
5630
5631 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
5632 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
5633#ifdef VBOX_WITH_64_BITS_GUESTS
5634 break;
5635#endif
5636 default:
5637 AssertFailed();
5638 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
5639 }
5640 }
5641
5642 /*
5643 * Apply the hardware specified fixed CR4 bits (mainly CR4.VMXE).
5644 * Note! For nested-guests, we could be altering our VMX emulation's
5645 * fixed bits. We thus need to re-apply them while importing CR4.
5646 */
5647 u64GuestCr4 |= fSetCr4;
5648 u64GuestCr4 &= fZapCr4;
5649
5650 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
5651 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR4, u64GuestCr4); AssertRC(rc);
5652 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4); AssertRC(rc);
5653
5654 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
5655 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
5656
5657 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
5658
5659 Log4Func(("cr4=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
5660 }
5661 return rc;
5662}
5663
5664
5665/**
5666 * Exports the guest debug registers into the guest-state area in the VMCS.
5667 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
5668 *
5669 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
5670 *
5671 * @returns VBox status code.
5672 * @param pVCpu The cross context virtual CPU structure.
5673 * @param pVmxTransient The VMX-transient structure.
5674 *
5675 * @remarks No-long-jump zone!!!
5676 */
5677static int hmR0VmxExportSharedDebugState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
5678{
5679 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5680
5681 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
5682 * stepping. */
5683 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5684 if (pVmxTransient->fIsNestedGuest)
5685 {
5686 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
5687 AssertRC(rc);
5688
5689 /* Always intercept Mov DRx accesses for the nested-guest for now. */
5690 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
5691 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
5692 AssertRC(rc);
5693 return VINF_SUCCESS;
5694 }
5695
5696#ifdef VBOX_STRICT
5697 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
5698 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
5699 {
5700 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
5701 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
5702 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
5703 }
5704#endif
5705
5706 bool fSteppingDB = false;
5707 bool fInterceptMovDRx = false;
5708 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5709 if (pVCpu->hm.s.fSingleInstruction)
5710 {
5711 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
5712 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5713 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
5714 {
5715 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
5716 Assert(fSteppingDB == false);
5717 }
5718 else
5719 {
5720 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
5721 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
5722 pVCpu->hm.s.fClearTrapFlag = true;
5723 fSteppingDB = true;
5724 }
5725 }
5726
5727 uint64_t u64GuestDr7;
5728 if ( fSteppingDB
5729 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
5730 {
5731 /*
5732 * Use the combined guest and host DRx values found in the hypervisor register set
5733 * because the hypervisor debugger has breakpoints active or someone is single stepping
5734 * on the host side without a monitor trap flag.
5735 *
5736 * Note! DBGF expects a clean DR6 state before executing guest code.
5737 */
5738 if (!CPUMIsHyperDebugStateActive(pVCpu))
5739 {
5740 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
5741 Assert(CPUMIsHyperDebugStateActive(pVCpu));
5742 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
5743 }
5744
5745 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
5746 u64GuestDr7 = CPUMGetHyperDR7(pVCpu);
5747 pVCpu->hm.s.fUsingHyperDR7 = true;
5748 fInterceptMovDRx = true;
5749 }
5750 else
5751 {
5752 /*
5753 * If the guest has enabled debug registers, we need to load them prior to
5754 * executing guest code so they'll trigger at the right time.
5755 */
5756 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
5757 {
5758 if (!CPUMIsGuestDebugStateActive(pVCpu))
5759 {
5760 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
5761 Assert(CPUMIsGuestDebugStateActive(pVCpu));
5762 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
5763 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
5764 }
5765 Assert(!fInterceptMovDRx);
5766 }
5767 else if (!CPUMIsGuestDebugStateActive(pVCpu))
5768 {
5769 /*
5770 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
5771 * must intercept #DB in order to maintain a correct DR6 guest value, and
5772 * because we need to intercept it to prevent nested #DBs from hanging the
5773 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
5774 */
5775 fInterceptMovDRx = true;
5776 }
5777
5778 /* Update DR7 with the actual guest value. */
5779 u64GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
5780 pVCpu->hm.s.fUsingHyperDR7 = false;
5781 }
5782
5783 if (fInterceptMovDRx)
5784 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
5785 else
5786 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
5787
5788 /*
5789 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
5790 * monitor-trap flag and update our cache.
5791 */
5792 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5793 {
5794 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5795 AssertRC(rc);
5796 pVmcsInfo->u32ProcCtls = uProcCtls;
5797 }
5798
5799 /*
5800 * Update guest DR7.
5801 */
5802 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, u64GuestDr7);
5803 AssertRC(rc);
5804
5805 /*
5806 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
5807 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
5808 *
5809 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5810 */
5811 if (fSteppingDB)
5812 {
5813 Assert(pVCpu->hm.s.fSingleInstruction);
5814 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
5815
5816 uint32_t fIntrState = 0;
5817 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
5818 AssertRC(rc);
5819
5820 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
5821 {
5822 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
5823 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
5824 AssertRC(rc);
5825 }
5826 }
5827
5828 return VINF_SUCCESS;
5829}
5830
5831
5832#ifdef VBOX_STRICT
5833/**
5834 * Strict function to validate segment registers.
5835 *
5836 * @param pVCpu The cross context virtual CPU structure.
5837 * @param pVmcsInfo The VMCS info. object.
5838 *
5839 * @remarks Will import guest CR0 on strict builds during validation of
5840 * segments.
5841 */
5842static void hmR0VmxValidateSegmentRegs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5843{
5844 /*
5845 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
5846 *
5847 * The reason we check for attribute value 0 in this function and not just the unusable bit is
5848 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
5849 * unusable bit and doesn't change the guest-context value.
5850 */
5851 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5852 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5853 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
5854 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
5855 && ( !CPUMIsGuestInRealModeEx(pCtx)
5856 && !CPUMIsGuestInV86ModeEx(pCtx)))
5857 {
5858 /* Protected mode checks */
5859 /* CS */
5860 Assert(pCtx->cs.Attr.n.u1Present);
5861 Assert(!(pCtx->cs.Attr.u & 0xf00));
5862 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
5863 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
5864 || !(pCtx->cs.Attr.n.u1Granularity));
5865 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
5866 || (pCtx->cs.Attr.n.u1Granularity));
5867 /* CS cannot be loaded with NULL in protected mode. */
5868 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
5869 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
5870 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
5871 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
5872 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
5873 else
5874 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
5875 /* SS */
5876 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
5877 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
5878 if ( !(pCtx->cr0 & X86_CR0_PE)
5879 || pCtx->cs.Attr.n.u4Type == 3)
5880 {
5881 Assert(!pCtx->ss.Attr.n.u2Dpl);
5882 }
5883 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
5884 {
5885 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
5886 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
5887 Assert(pCtx->ss.Attr.n.u1Present);
5888 Assert(!(pCtx->ss.Attr.u & 0xf00));
5889 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
5890 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
5891 || !(pCtx->ss.Attr.n.u1Granularity));
5892 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
5893 || (pCtx->ss.Attr.n.u1Granularity));
5894 }
5895 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
5896 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
5897 {
5898 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5899 Assert(pCtx->ds.Attr.n.u1Present);
5900 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
5901 Assert(!(pCtx->ds.Attr.u & 0xf00));
5902 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
5903 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
5904 || !(pCtx->ds.Attr.n.u1Granularity));
5905 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
5906 || (pCtx->ds.Attr.n.u1Granularity));
5907 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5908 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
5909 }
5910 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
5911 {
5912 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5913 Assert(pCtx->es.Attr.n.u1Present);
5914 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
5915 Assert(!(pCtx->es.Attr.u & 0xf00));
5916 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
5917 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
5918 || !(pCtx->es.Attr.n.u1Granularity));
5919 Assert( !(pCtx->es.u32Limit & 0xfff00000)
5920 || (pCtx->es.Attr.n.u1Granularity));
5921 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5922 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
5923 }
5924 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
5925 {
5926 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5927 Assert(pCtx->fs.Attr.n.u1Present);
5928 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
5929 Assert(!(pCtx->fs.Attr.u & 0xf00));
5930 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
5931 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
5932 || !(pCtx->fs.Attr.n.u1Granularity));
5933 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
5934 || (pCtx->fs.Attr.n.u1Granularity));
5935 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5936 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
5937 }
5938 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
5939 {
5940 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5941 Assert(pCtx->gs.Attr.n.u1Present);
5942 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
5943 Assert(!(pCtx->gs.Attr.u & 0xf00));
5944 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
5945 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
5946 || !(pCtx->gs.Attr.n.u1Granularity));
5947 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
5948 || (pCtx->gs.Attr.n.u1Granularity));
5949 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5950 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
5951 }
5952 /* 64-bit capable CPUs. */
5953 Assert(!RT_HI_U32(pCtx->cs.u64Base));
5954 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
5955 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
5956 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
5957 }
5958 else if ( CPUMIsGuestInV86ModeEx(pCtx)
5959 || ( CPUMIsGuestInRealModeEx(pCtx)
5960 && !pVM->hm.s.vmx.fUnrestrictedGuest))
5961 {
5962 /* Real and v86 mode checks. */
5963 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
5964 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
5965 if (pVmcsInfo->RealMode.fRealOnV86Active)
5966 {
5967 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
5968 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
5969 }
5970 else
5971 {
5972 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
5973 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
5974 }
5975
5976 /* CS */
5977 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
5978 Assert(pCtx->cs.u32Limit == 0xffff);
5979 Assert(u32CSAttr == 0xf3);
5980 /* SS */
5981 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
5982 Assert(pCtx->ss.u32Limit == 0xffff);
5983 Assert(u32SSAttr == 0xf3);
5984 /* DS */
5985 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
5986 Assert(pCtx->ds.u32Limit == 0xffff);
5987 Assert(u32DSAttr == 0xf3);
5988 /* ES */
5989 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
5990 Assert(pCtx->es.u32Limit == 0xffff);
5991 Assert(u32ESAttr == 0xf3);
5992 /* FS */
5993 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
5994 Assert(pCtx->fs.u32Limit == 0xffff);
5995 Assert(u32FSAttr == 0xf3);
5996 /* GS */
5997 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
5998 Assert(pCtx->gs.u32Limit == 0xffff);
5999 Assert(u32GSAttr == 0xf3);
6000 /* 64-bit capable CPUs. */
6001 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6002 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6003 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6004 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6005 }
6006}
6007#endif /* VBOX_STRICT */
6008
6009
6010/**
6011 * Exports a guest segment register into the guest-state area in the VMCS.
6012 *
6013 * @returns VBox status code.
6014 * @param pVCpu The cross context virtual CPU structure.
6015 * @param pVmcsInfo The VMCS info. object.
6016 * @param iSegReg The segment register number (X86_SREG_XXX).
6017 * @param pSelReg Pointer to the segment selector.
6018 *
6019 * @remarks No-long-jump zone!!!
6020 */
6021static int hmR0VmxExportGuestSegReg(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, uint8_t iSegReg, PCCPUMSELREG pSelReg)
6022{
6023 Assert(iSegReg < X86_SREG_COUNT);
6024 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
6025 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
6026 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
6027 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
6028
6029 uint32_t u32Access = pSelReg->Attr.u;
6030 if (pVmcsInfo->RealMode.fRealOnV86Active)
6031 {
6032 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6033 u32Access = 0xf3;
6034 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6035 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6036 RT_NOREF_PV(pVCpu);
6037 }
6038 else
6039 {
6040 /*
6041 * The way to differentiate between whether this is really a null selector or was just
6042 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6043 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6044 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6045 * NULL selectors loaded in protected-mode have their attribute as 0.
6046 */
6047 if (!u32Access)
6048 u32Access = X86DESCATTR_UNUSABLE;
6049 }
6050
6051 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6052 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6053 ("Access bit not set for usable segment. idx=%#x sel=%#x attr %#x\n", idxBase, pSelReg, pSelReg->Attr.u));
6054
6055 /*
6056 * Commit it to the VMCS.
6057 */
6058 int rc = VMXWriteVmcs32(idxSel, pSelReg->Sel); AssertRC(rc);
6059 rc = VMXWriteVmcs32(idxLimit, pSelReg->u32Limit); AssertRC(rc);
6060 rc = VMXWriteVmcsNw(idxBase, pSelReg->u64Base); AssertRC(rc);
6061 rc = VMXWriteVmcs32(idxAttr, u32Access); AssertRC(rc);
6062 return VINF_SUCCESS;
6063}
6064
6065
6066/**
6067 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6068 * area in the VMCS.
6069 *
6070 * @returns VBox status code.
6071 * @param pVCpu The cross context virtual CPU structure.
6072 * @param pVmxTransient The VMX-transient structure.
6073 *
6074 * @remarks Will import guest CR0 on strict builds during validation of
6075 * segments.
6076 * @remarks No-long-jump zone!!!
6077 */
6078static int hmR0VmxExportGuestSegRegsXdtr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6079{
6080 int rc = VERR_INTERNAL_ERROR_5;
6081 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6082 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6083 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6084
6085 /*
6086 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6087 */
6088 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6089 {
6090#ifdef VBOX_WITH_REM
6091 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
6092 {
6093 Assert(!pVmxTransient->fIsNestedGuest);
6094 Assert(pVM->hm.s.vmx.pRealModeTSS);
6095 AssertCompile(PGMMODE_REAL < PGMMODE_PROTECTED);
6096 if ( pVmcsInfo->fWasInRealMode
6097 && PGMGetGuestMode(pVCpu) >= PGMMODE_PROTECTED)
6098 {
6099 /*
6100 * Notify the recompiler must flush its code-cache as the guest -may-
6101 * rewrite code it in real-mode (e.g. OpenBSD 4.0).
6102 */
6103 REMFlushTBs(pVM);
6104 Log4Func(("Switch to protected mode detected!\n"));
6105 pVmcsInfo->fWasInRealMode = false;
6106 }
6107 }
6108#endif
6109 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6110 {
6111 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6112 if (pVmcsInfo->RealMode.fRealOnV86Active)
6113 pVmcsInfo->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6114 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6115 AssertRC(rc);
6116 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6117 }
6118
6119 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6120 {
6121 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6122 if (pVmcsInfo->RealMode.fRealOnV86Active)
6123 pVmcsInfo->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6124 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6125 AssertRC(rc);
6126 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6127 }
6128
6129 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6130 {
6131 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6132 if (pVmcsInfo->RealMode.fRealOnV86Active)
6133 pVmcsInfo->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6134 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6135 AssertRC(rc);
6136 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6137 }
6138
6139 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6140 {
6141 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6142 if (pVmcsInfo->RealMode.fRealOnV86Active)
6143 pVmcsInfo->RealMode.AttrES.u = pCtx->es.Attr.u;
6144 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6145 AssertRC(rc);
6146 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6147 }
6148
6149 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6150 {
6151 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6152 if (pVmcsInfo->RealMode.fRealOnV86Active)
6153 pVmcsInfo->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6154 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6155 AssertRC(rc);
6156 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6157 }
6158
6159 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6160 {
6161 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6162 if (pVmcsInfo->RealMode.fRealOnV86Active)
6163 pVmcsInfo->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6164 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6165 AssertRC(rc);
6166 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6167 }
6168
6169#ifdef VBOX_STRICT
6170 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6171#endif
6172 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6173 pCtx->cs.Attr.u));
6174 }
6175
6176 /*
6177 * Guest TR.
6178 */
6179 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6180 {
6181 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6182
6183 /*
6184 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6185 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6186 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6187 */
6188 uint16_t u16Sel;
6189 uint32_t u32Limit;
6190 uint64_t u64Base;
6191 uint32_t u32AccessRights;
6192 if (!pVmcsInfo->RealMode.fRealOnV86Active)
6193 {
6194 u16Sel = pCtx->tr.Sel;
6195 u32Limit = pCtx->tr.u32Limit;
6196 u64Base = pCtx->tr.u64Base;
6197 u32AccessRights = pCtx->tr.Attr.u;
6198 }
6199 else
6200 {
6201 Assert(!pVmxTransient->fIsNestedGuest);
6202 Assert(pVM->hm.s.vmx.pRealModeTSS);
6203 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6204
6205 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6206 RTGCPHYS GCPhys;
6207 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6208 AssertRCReturn(rc, rc);
6209
6210 X86DESCATTR DescAttr;
6211 DescAttr.u = 0;
6212 DescAttr.n.u1Present = 1;
6213 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6214
6215 u16Sel = 0;
6216 u32Limit = HM_VTX_TSS_SIZE;
6217 u64Base = GCPhys;
6218 u32AccessRights = DescAttr.u;
6219 }
6220
6221 /* Validate. */
6222 Assert(!(u16Sel & RT_BIT(2)));
6223 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6224 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6225 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6226 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6227 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6228 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6229 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6230 Assert( (u32Limit & 0xfff) == 0xfff
6231 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6232 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6233 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6234
6235 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_TR_SEL, u16Sel); AssertRC(rc);
6236 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit); AssertRC(rc);
6237 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights); AssertRC(rc);
6238 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_TR_BASE, u64Base); AssertRC(rc);
6239
6240 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6241 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6242 }
6243
6244 /*
6245 * Guest GDTR.
6246 */
6247 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6248 {
6249 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6250
6251 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt); AssertRC(rc);
6252 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt); AssertRC(rc);
6253
6254 /* Validate. */
6255 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6256
6257 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6258 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6259 }
6260
6261 /*
6262 * Guest LDTR.
6263 */
6264 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6265 {
6266 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6267
6268 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6269 uint32_t u32Access;
6270 if ( !pVmxTransient->fIsNestedGuest
6271 && !pCtx->ldtr.Attr.u)
6272 u32Access = X86DESCATTR_UNUSABLE;
6273 else
6274 u32Access = pCtx->ldtr.Attr.u;
6275
6276 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel); AssertRC(rc);
6277 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit); AssertRC(rc);
6278 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access); AssertRC(rc);
6279 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base); AssertRC(rc);
6280
6281 /* Validate. */
6282 if (!(u32Access & X86DESCATTR_UNUSABLE))
6283 {
6284 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6285 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6286 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6287 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6288 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6289 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6290 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6291 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6292 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6293 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6294 }
6295
6296 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6297 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6298 }
6299
6300 /*
6301 * Guest IDTR.
6302 */
6303 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6304 {
6305 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6306
6307 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt); AssertRC(rc);
6308 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt); AssertRC(rc);
6309
6310 /* Validate. */
6311 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6312
6313 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6314 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6315 }
6316
6317 return VINF_SUCCESS;
6318}
6319
6320
6321/**
6322 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6323 * areas.
6324 *
6325 * These MSRs will automatically be loaded to the host CPU on every successful
6326 * VM-entry and stored from the host CPU on every successful VM-exit.
6327 *
6328 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6329 * actual host MSR values are not- updated here for performance reasons. See
6330 * hmR0VmxExportHostMsrs().
6331 *
6332 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6333 *
6334 * @returns VBox status code.
6335 * @param pVCpu The cross context virtual CPU structure.
6336 * @param pVmxTransient The VMX-transient structure.
6337 *
6338 * @remarks No-long-jump zone!!!
6339 */
6340static int hmR0VmxExportGuestMsrs(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6341{
6342 AssertPtr(pVCpu);
6343 AssertPtr(pVmxTransient);
6344
6345 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6346 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6347
6348 /*
6349 * MSRs that we use the auto-load/store MSR area in the VMCS.
6350 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs(),
6351 * nothing to do here. The host MSR values are updated when it's safe in
6352 * hmR0VmxLazySaveHostMsrs().
6353 *
6354 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6355 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6356 * emulation, nothing to do here.
6357 */
6358 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6359 {
6360 /* No auto-load/store MSRs currently. */
6361 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6362 }
6363
6364 /*
6365 * Guest Sysenter MSRs.
6366 */
6367 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6368 {
6369 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6370
6371 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6372 {
6373 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6374 AssertRC(rc);
6375 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6376 }
6377
6378 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6379 {
6380 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6381 AssertRC(rc);
6382 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6383 }
6384
6385 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6386 {
6387 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6388 AssertRC(rc);
6389 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6390 }
6391 }
6392
6393 /*
6394 * Guest/host EFER MSR.
6395 */
6396 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6397 {
6398 /* Whether we are using the VMCS to swap the EFER MSR must have been
6399 determined earlier while exporting VM-entry/VM-exit controls. */
6400 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6401 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6402
6403 if (hmR0VmxShouldSwapEferMsr(pVCpu))
6404 {
6405 /*
6406 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6407 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6408 */
6409 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
6410 {
6411 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, pCtx->msrEFER);
6412 AssertRC(rc);
6413 }
6414 else
6415 {
6416 /*
6417 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6418 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6419 */
6420 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, pCtx->msrEFER,
6421 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6422 AssertRCReturn(rc, rc);
6423 }
6424 }
6425 else if (!pVM->hm.s.vmx.fSupportsVmcsEfer)
6426 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6427
6428 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6429 }
6430
6431 /*
6432 * Other MSRs.
6433 * Speculation Control (R/W).
6434 */
6435 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6436 {
6437 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6438 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6439 {
6440 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6441 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6442 AssertRCReturn(rc, rc);
6443 }
6444 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6445 }
6446
6447 return VINF_SUCCESS;
6448}
6449
6450
6451/**
6452 * Selects up the appropriate function to run guest code.
6453 *
6454 * @returns VBox status code.
6455 * @param pVCpu The cross context virtual CPU structure.
6456 * @param pVmxTransient The VMX-transient structure.
6457 *
6458 * @remarks No-long-jump zone!!!
6459 */
6460static int hmR0VmxSelectVMRunHandler(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6461{
6462 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6463 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6464
6465 if (CPUMIsGuestInLongModeEx(pCtx))
6466 {
6467#ifndef VBOX_WITH_64_BITS_GUESTS
6468 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
6469#else
6470 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests); /* Guaranteed by hmR3InitFinalizeR0(). */
6471 /* Guest is in long mode, use the 64-bit handler (host is 64-bit). */
6472 pVmcsInfo->pfnStartVM = VMXR0StartVM64;
6473#endif
6474 }
6475 else
6476 {
6477 /* Guest is not in long mode, use the 32-bit handler. */
6478 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
6479 }
6480 Assert(pVmcsInfo->pfnStartVM);
6481 return VINF_SUCCESS;
6482}
6483
6484
6485/**
6486 * Wrapper for running the guest code in VT-x.
6487 *
6488 * @returns VBox status code, no informational status codes.
6489 * @param pVCpu The cross context virtual CPU structure.
6490 * @param pVmxTransient The VMX-transient structure.
6491 *
6492 * @remarks No-long-jump zone!!!
6493 */
6494DECLINLINE(int) hmR0VmxRunGuest(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6495{
6496 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
6497 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6498 pCtx->fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
6499
6500 /** @todo Add stats for VMRESUME vs VMLAUNCH. */
6501
6502 /*
6503 * 64-bit Windows uses XMM registers in the kernel as the Microsoft compiler expresses
6504 * floating-point operations using SSE instructions. Some XMM registers (XMM6-XMM15) are
6505 * callee-saved and thus the need for this XMM wrapper.
6506 *
6507 * See MSDN "Configuring Programs for 64-bit/x64 Software Conventions / Register Usage".
6508 */
6509 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6510 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
6511 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6512#ifdef VBOX_WITH_KERNEL_USING_XMM
6513 int rc = hmR0VMXStartVMWrapXMM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu, pVmcsInfo->pfnStartVM);
6514#else
6515 int rc = pVmcsInfo->pfnStartVM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu);
6516#endif
6517 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
6518 return rc;
6519}
6520
6521
6522/**
6523 * Reports world-switch error and dumps some useful debug info.
6524 *
6525 * @param pVCpu The cross context virtual CPU structure.
6526 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
6527 * @param pVmxTransient The VMX-transient structure (only
6528 * exitReason updated).
6529 */
6530static void hmR0VmxReportWorldSwitchError(PVMCPUCC pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
6531{
6532 Assert(pVCpu);
6533 Assert(pVmxTransient);
6534 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
6535
6536 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
6537 switch (rcVMRun)
6538 {
6539 case VERR_VMX_INVALID_VMXON_PTR:
6540 AssertFailed();
6541 break;
6542 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
6543 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
6544 {
6545 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
6546 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
6547 AssertRC(rc);
6548 hmR0VmxReadExitQualVmcs(pVmxTransient);
6549
6550 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
6551 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
6552 Cannot do it here as we may have been long preempted. */
6553
6554#ifdef VBOX_STRICT
6555 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6556 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
6557 pVmxTransient->uExitReason));
6558 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
6559 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
6560 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
6561 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
6562 else
6563 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
6564 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
6565 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
6566
6567 static struct
6568 {
6569 /** Name of the field to log. */
6570 const char *pszName;
6571 /** The VMCS field. */
6572 uint32_t uVmcsField;
6573 /** Whether host support of this field needs to be checked. */
6574 bool fCheckSupport;
6575 } const s_aVmcsFields[] =
6576 {
6577 { "VMX_VMCS32_CTRL_PIN_EXEC", VMX_VMCS32_CTRL_PIN_EXEC, false },
6578 { "VMX_VMCS32_CTRL_PROC_EXEC", VMX_VMCS32_CTRL_PROC_EXEC, false },
6579 { "VMX_VMCS32_CTRL_PROC_EXEC2", VMX_VMCS32_CTRL_PROC_EXEC2, true },
6580 { "VMX_VMCS32_CTRL_ENTRY", VMX_VMCS32_CTRL_ENTRY, false },
6581 { "VMX_VMCS32_CTRL_EXIT", VMX_VMCS32_CTRL_EXIT, false },
6582 { "VMX_VMCS32_CTRL_CR3_TARGET_COUNT", VMX_VMCS32_CTRL_CR3_TARGET_COUNT, false },
6583 { "VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO", VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, false },
6584 { "VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE", VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, false },
6585 { "VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH", VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, false },
6586 { "VMX_VMCS32_CTRL_TPR_THRESHOLD", VMX_VMCS32_CTRL_TPR_THRESHOLD, false },
6587 { "VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, false },
6588 { "VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, false },
6589 { "VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, false },
6590 { "VMX_VMCS32_CTRL_EXCEPTION_BITMAP", VMX_VMCS32_CTRL_EXCEPTION_BITMAP, false },
6591 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, false },
6592 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, false },
6593 { "VMX_VMCS_CTRL_CR0_MASK", VMX_VMCS_CTRL_CR0_MASK, false },
6594 { "VMX_VMCS_CTRL_CR0_READ_SHADOW", VMX_VMCS_CTRL_CR0_READ_SHADOW, false },
6595 { "VMX_VMCS_CTRL_CR4_MASK", VMX_VMCS_CTRL_CR4_MASK, false },
6596 { "VMX_VMCS_CTRL_CR4_READ_SHADOW", VMX_VMCS_CTRL_CR4_READ_SHADOW, false },
6597 { "VMX_VMCS64_CTRL_EPTP_FULL", VMX_VMCS64_CTRL_EPTP_FULL, true },
6598 { "VMX_VMCS_GUEST_RIP", VMX_VMCS_GUEST_RIP, false },
6599 { "VMX_VMCS_GUEST_RSP", VMX_VMCS_GUEST_RSP, false },
6600 { "VMX_VMCS_GUEST_RFLAGS", VMX_VMCS_GUEST_RFLAGS, false },
6601 { "VMX_VMCS16_VPID", VMX_VMCS16_VPID, true, },
6602 { "VMX_VMCS_HOST_CR0", VMX_VMCS_HOST_CR0, false },
6603 { "VMX_VMCS_HOST_CR3", VMX_VMCS_HOST_CR3, false },
6604 { "VMX_VMCS_HOST_CR4", VMX_VMCS_HOST_CR4, false },
6605 /* The order of selector fields below are fixed! */
6606 { "VMX_VMCS16_HOST_ES_SEL", VMX_VMCS16_HOST_ES_SEL, false },
6607 { "VMX_VMCS16_HOST_CS_SEL", VMX_VMCS16_HOST_CS_SEL, false },
6608 { "VMX_VMCS16_HOST_SS_SEL", VMX_VMCS16_HOST_SS_SEL, false },
6609 { "VMX_VMCS16_HOST_DS_SEL", VMX_VMCS16_HOST_DS_SEL, false },
6610 { "VMX_VMCS16_HOST_FS_SEL", VMX_VMCS16_HOST_FS_SEL, false },
6611 { "VMX_VMCS16_HOST_GS_SEL", VMX_VMCS16_HOST_GS_SEL, false },
6612 { "VMX_VMCS16_HOST_TR_SEL", VMX_VMCS16_HOST_TR_SEL, false },
6613 /* End of ordered selector fields. */
6614 { "VMX_VMCS_HOST_TR_BASE", VMX_VMCS_HOST_TR_BASE, false },
6615 { "VMX_VMCS_HOST_GDTR_BASE", VMX_VMCS_HOST_GDTR_BASE, false },
6616 { "VMX_VMCS_HOST_IDTR_BASE", VMX_VMCS_HOST_IDTR_BASE, false },
6617 { "VMX_VMCS32_HOST_SYSENTER_CS", VMX_VMCS32_HOST_SYSENTER_CS, false },
6618 { "VMX_VMCS_HOST_SYSENTER_EIP", VMX_VMCS_HOST_SYSENTER_EIP, false },
6619 { "VMX_VMCS_HOST_SYSENTER_ESP", VMX_VMCS_HOST_SYSENTER_ESP, false },
6620 { "VMX_VMCS_HOST_RSP", VMX_VMCS_HOST_RSP, false },
6621 { "VMX_VMCS_HOST_RIP", VMX_VMCS_HOST_RIP, false }
6622 };
6623
6624 RTGDTR HostGdtr;
6625 ASMGetGDTR(&HostGdtr);
6626
6627 uint32_t const cVmcsFields = RT_ELEMENTS(s_aVmcsFields);
6628 for (uint32_t i = 0; i < cVmcsFields; i++)
6629 {
6630 uint32_t const uVmcsField = s_aVmcsFields[i].uVmcsField;
6631
6632 bool fSupported;
6633 if (!s_aVmcsFields[i].fCheckSupport)
6634 fSupported = true;
6635 else
6636 {
6637 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6638 switch (uVmcsField)
6639 {
6640 case VMX_VMCS64_CTRL_EPTP_FULL: fSupported = pVM->hm.s.fNestedPaging; break;
6641 case VMX_VMCS16_VPID: fSupported = pVM->hm.s.vmx.fVpid; break;
6642 case VMX_VMCS32_CTRL_PROC_EXEC2:
6643 fSupported = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
6644 break;
6645 default:
6646 AssertMsgFailedReturnVoid(("Failed to provide VMCS field support for %#RX32\n", uVmcsField));
6647 }
6648 }
6649
6650 if (fSupported)
6651 {
6652 uint8_t const uWidth = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_WIDTH);
6653 switch (uWidth)
6654 {
6655 case VMX_VMCSFIELD_WIDTH_16BIT:
6656 {
6657 uint16_t u16Val;
6658 rc = VMXReadVmcs16(uVmcsField, &u16Val);
6659 AssertRC(rc);
6660 Log4(("%-40s = %#RX16\n", s_aVmcsFields[i].pszName, u16Val));
6661
6662 if ( uVmcsField >= VMX_VMCS16_HOST_ES_SEL
6663 && uVmcsField <= VMX_VMCS16_HOST_TR_SEL)
6664 {
6665 if (u16Val < HostGdtr.cbGdt)
6666 {
6667 /* Order of selectors in s_apszSel is fixed and matches the order in s_aVmcsFields. */
6668 static const char * const s_apszSel[] = { "Host ES", "Host CS", "Host SS", "Host DS",
6669 "Host FS", "Host GS", "Host TR" };
6670 uint8_t const idxSel = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_INDEX);
6671 Assert(idxSel < RT_ELEMENTS(s_apszSel));
6672 PCX86DESCHC pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u16Val & X86_SEL_MASK));
6673 hmR0DumpDescriptor(pDesc, u16Val, s_apszSel[idxSel]);
6674 }
6675 else
6676 Log4((" Selector value exceeds GDT limit!\n"));
6677 }
6678 break;
6679 }
6680
6681 case VMX_VMCSFIELD_WIDTH_32BIT:
6682 {
6683 uint32_t u32Val;
6684 rc = VMXReadVmcs32(uVmcsField, &u32Val);
6685 AssertRC(rc);
6686 Log4(("%-40s = %#RX32\n", s_aVmcsFields[i].pszName, u32Val));
6687 break;
6688 }
6689
6690 case VMX_VMCSFIELD_WIDTH_64BIT:
6691 case VMX_VMCSFIELD_WIDTH_NATURAL:
6692 {
6693 uint64_t u64Val;
6694 rc = VMXReadVmcs64(uVmcsField, &u64Val);
6695 AssertRC(rc);
6696 Log4(("%-40s = %#RX64\n", s_aVmcsFields[i].pszName, u64Val));
6697 break;
6698 }
6699 }
6700 }
6701 }
6702
6703 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
6704 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
6705 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
6706 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
6707 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
6708 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
6709#endif /* VBOX_STRICT */
6710 break;
6711 }
6712
6713 default:
6714 /* Impossible */
6715 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
6716 break;
6717 }
6718}
6719
6720
6721/**
6722 * Sets up the usage of TSC-offsetting and updates the VMCS.
6723 *
6724 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
6725 * VMX-preemption timer.
6726 *
6727 * @returns VBox status code.
6728 * @param pVCpu The cross context virtual CPU structure.
6729 * @param pVmxTransient The VMX-transient structure.
6730 *
6731 * @remarks No-long-jump zone!!!
6732 */
6733static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6734{
6735 bool fOffsettedTsc;
6736 bool fParavirtTsc;
6737 uint64_t uTscOffset;
6738 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6739 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6740
6741 if (pVM->hm.s.vmx.fUsePreemptTimer)
6742 {
6743 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc);
6744
6745 /* Make sure the returned values have sane upper and lower boundaries. */
6746 uint64_t u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
6747 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second */
6748 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
6749 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
6750
6751 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
6752 * preemption timers here. We probably need to clamp the preemption timer,
6753 * after converting the timer value to the host. */
6754 uint32_t const cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
6755 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
6756 AssertRC(rc);
6757 }
6758 else
6759 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
6760
6761 if (fParavirtTsc)
6762 {
6763 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
6764 information before every VM-entry, hence disable it for performance sake. */
6765#if 0
6766 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
6767 AssertRC(rc);
6768#endif
6769 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
6770 }
6771
6772 if ( fOffsettedTsc
6773 && RT_LIKELY(!pVCpu->hm.s.fDebugWantRdTscExit))
6774 {
6775 if (pVmxTransient->fIsNestedGuest)
6776 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
6777 hmR0VmxSetTscOffsetVmcs(pVmcsInfo, uTscOffset);
6778 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
6779 }
6780 else
6781 {
6782 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
6783 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
6784 }
6785}
6786
6787
6788/**
6789 * Gets the IEM exception flags for the specified vector and IDT vectoring /
6790 * VM-exit interruption info type.
6791 *
6792 * @returns The IEM exception flags.
6793 * @param uVector The event vector.
6794 * @param uVmxEventType The VMX event type.
6795 *
6796 * @remarks This function currently only constructs flags required for
6797 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
6798 * and CR2 aspects of an exception are not included).
6799 */
6800static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
6801{
6802 uint32_t fIemXcptFlags;
6803 switch (uVmxEventType)
6804 {
6805 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
6806 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
6807 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
6808 break;
6809
6810 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
6811 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
6812 break;
6813
6814 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
6815 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
6816 break;
6817
6818 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
6819 {
6820 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
6821 if (uVector == X86_XCPT_BP)
6822 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
6823 else if (uVector == X86_XCPT_OF)
6824 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
6825 else
6826 {
6827 fIemXcptFlags = 0;
6828 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
6829 }
6830 break;
6831 }
6832
6833 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
6834 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
6835 break;
6836
6837 default:
6838 fIemXcptFlags = 0;
6839 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
6840 break;
6841 }
6842 return fIemXcptFlags;
6843}
6844
6845
6846/**
6847 * Sets an event as a pending event to be injected into the guest.
6848 *
6849 * @param pVCpu The cross context virtual CPU structure.
6850 * @param u32IntInfo The VM-entry interruption-information field.
6851 * @param cbInstr The VM-entry instruction length in bytes (for software
6852 * interrupts, exceptions and privileged software
6853 * exceptions).
6854 * @param u32ErrCode The VM-entry exception error code.
6855 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
6856 * page-fault.
6857 */
6858DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPUCC pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
6859 RTGCUINTPTR GCPtrFaultAddress)
6860{
6861 Assert(!pVCpu->hm.s.Event.fPending);
6862 pVCpu->hm.s.Event.fPending = true;
6863 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
6864 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
6865 pVCpu->hm.s.Event.cbInstr = cbInstr;
6866 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
6867}
6868
6869
6870/**
6871 * Sets an external interrupt as pending-for-injection into the VM.
6872 *
6873 * @param pVCpu The cross context virtual CPU structure.
6874 * @param u8Interrupt The external interrupt vector.
6875 */
6876DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPUCC pVCpu, uint8_t u8Interrupt)
6877{
6878 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
6879 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
6880 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6881 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6882 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6883}
6884
6885
6886/**
6887 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
6888 *
6889 * @param pVCpu The cross context virtual CPU structure.
6890 */
6891DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPUCC pVCpu)
6892{
6893 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
6894 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
6895 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6896 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6897 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6898}
6899
6900
6901/**
6902 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
6903 *
6904 * @param pVCpu The cross context virtual CPU structure.
6905 */
6906DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPUCC pVCpu)
6907{
6908 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
6909 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6910 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
6911 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6912 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6913}
6914
6915
6916/**
6917 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
6918 *
6919 * @param pVCpu The cross context virtual CPU structure.
6920 */
6921DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPUCC pVCpu)
6922{
6923 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
6924 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6925 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6926 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6927 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6928}
6929
6930
6931/**
6932 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
6933 *
6934 * @param pVCpu The cross context virtual CPU structure.
6935 */
6936DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPUCC pVCpu)
6937{
6938 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
6939 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6940 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6941 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6942 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6943}
6944
6945
6946#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
6947/**
6948 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
6949 *
6950 * @param pVCpu The cross context virtual CPU structure.
6951 * @param u32ErrCode The error code for the general-protection exception.
6952 */
6953DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPUCC pVCpu, uint32_t u32ErrCode)
6954{
6955 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
6956 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6957 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
6958 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6959 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
6960}
6961
6962
6963/**
6964 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
6965 *
6966 * @param pVCpu The cross context virtual CPU structure.
6967 * @param u32ErrCode The error code for the stack exception.
6968 */
6969DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPUCC pVCpu, uint32_t u32ErrCode)
6970{
6971 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
6972 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6973 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
6974 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6975 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
6976}
6977#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
6978
6979
6980/**
6981 * Fixes up attributes for the specified segment register.
6982 *
6983 * @param pVCpu The cross context virtual CPU structure.
6984 * @param pSelReg The segment register that needs fixing.
6985 * @param idxSel The VMCS field for the corresponding segment register.
6986 */
6987static void hmR0VmxFixUnusableSegRegAttr(PVMCPUCC pVCpu, PCPUMSELREG pSelReg, uint32_t idxSel)
6988{
6989 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
6990
6991 /*
6992 * If VT-x marks the segment as unusable, most other bits remain undefined:
6993 * - For CS the L, D and G bits have meaning.
6994 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
6995 * - For the remaining data segments no bits are defined.
6996 *
6997 * The present bit and the unusable bit has been observed to be set at the
6998 * same time (the selector was supposed to be invalid as we started executing
6999 * a V8086 interrupt in ring-0).
7000 *
7001 * What should be important for the rest of the VBox code, is that the P bit is
7002 * cleared. Some of the other VBox code recognizes the unusable bit, but
7003 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7004 * safe side here, we'll strip off P and other bits we don't care about. If
7005 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7006 *
7007 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7008 */
7009#ifdef VBOX_STRICT
7010 uint32_t const uAttr = pSelReg->Attr.u;
7011#endif
7012
7013 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7014 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7015 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7016
7017#ifdef VBOX_STRICT
7018 VMMRZCallRing3Disable(pVCpu);
7019 Log4Func(("Unusable %#x: sel=%#x attr=%#x -> %#x\n", idxSel, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7020# ifdef DEBUG_bird
7021 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7022 ("%#x: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7023 idxSel, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7024# endif
7025 VMMRZCallRing3Enable(pVCpu);
7026 NOREF(uAttr);
7027#endif
7028 RT_NOREF2(pVCpu, idxSel);
7029}
7030
7031
7032/**
7033 * Imports a guest segment register from the current VMCS into the guest-CPU
7034 * context.
7035 *
7036 * @param pVCpu The cross context virtual CPU structure.
7037 * @param iSegReg The segment register number (X86_SREG_XXX).
7038 *
7039 * @remarks Called with interrupts and/or preemption disabled.
7040 */
7041static void hmR0VmxImportGuestSegReg(PVMCPUCC pVCpu, uint8_t iSegReg)
7042{
7043 Assert(iSegReg < X86_SREG_COUNT);
7044
7045 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
7046 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
7047 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
7048 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
7049
7050 uint16_t u16Sel;
7051 uint64_t u64Base;
7052 uint32_t u32Limit, u32Attr;
7053 int rc = VMXReadVmcs16(idxSel, &u16Sel); AssertRC(rc);
7054 rc = VMXReadVmcs32(idxLimit, &u32Limit); AssertRC(rc);
7055 rc = VMXReadVmcs32(idxAttr, &u32Attr); AssertRC(rc);
7056 rc = VMXReadVmcsNw(idxBase, &u64Base); AssertRC(rc);
7057
7058 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7059 pSelReg->Sel = u16Sel;
7060 pSelReg->ValidSel = u16Sel;
7061 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7062 pSelReg->u32Limit = u32Limit;
7063 pSelReg->u64Base = u64Base;
7064 pSelReg->Attr.u = u32Attr;
7065 if (u32Attr & X86DESCATTR_UNUSABLE)
7066 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, idxSel);
7067}
7068
7069
7070/**
7071 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7072 *
7073 * @param pVCpu The cross context virtual CPU structure.
7074 *
7075 * @remarks Called with interrupts and/or preemption disabled.
7076 */
7077static void hmR0VmxImportGuestLdtr(PVMCPUCC pVCpu)
7078{
7079 uint16_t u16Sel;
7080 uint64_t u64Base;
7081 uint32_t u32Limit, u32Attr;
7082 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, &u16Sel); AssertRC(rc);
7083 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit); AssertRC(rc);
7084 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7085 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, &u64Base); AssertRC(rc);
7086
7087 pVCpu->cpum.GstCtx.ldtr.Sel = u16Sel;
7088 pVCpu->cpum.GstCtx.ldtr.ValidSel = u16Sel;
7089 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7090 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7091 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7092 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7093 if (u32Attr & X86DESCATTR_UNUSABLE)
7094 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, VMX_VMCS16_GUEST_LDTR_SEL);
7095}
7096
7097
7098/**
7099 * Imports the guest TR from the current VMCS into the guest-CPU context.
7100 *
7101 * @param pVCpu The cross context virtual CPU structure.
7102 *
7103 * @remarks Called with interrupts and/or preemption disabled.
7104 */
7105static void hmR0VmxImportGuestTr(PVMCPUCC pVCpu)
7106{
7107 uint16_t u16Sel;
7108 uint64_t u64Base;
7109 uint32_t u32Limit, u32Attr;
7110 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_TR_SEL, &u16Sel); AssertRC(rc);
7111 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit); AssertRC(rc);
7112 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7113 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_TR_BASE, &u64Base); AssertRC(rc);
7114
7115 pVCpu->cpum.GstCtx.tr.Sel = u16Sel;
7116 pVCpu->cpum.GstCtx.tr.ValidSel = u16Sel;
7117 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7118 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7119 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7120 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7121 /* TR is the only selector that can never be unusable. */
7122 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7123}
7124
7125
7126/**
7127 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7128 *
7129 * @param pVCpu The cross context virtual CPU structure.
7130 *
7131 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7132 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7133 * instead!!!
7134 */
7135static void hmR0VmxImportGuestRip(PVMCPUCC pVCpu)
7136{
7137 uint64_t u64Val;
7138 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7139 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7140 {
7141 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
7142 AssertRC(rc);
7143
7144 pCtx->rip = u64Val;
7145 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7146 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7147 }
7148}
7149
7150
7151/**
7152 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7153 *
7154 * @param pVCpu The cross context virtual CPU structure.
7155 * @param pVmcsInfo The VMCS info. object.
7156 *
7157 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7158 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7159 * instead!!!
7160 */
7161static void hmR0VmxImportGuestRFlags(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7162{
7163 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7164 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7165 {
7166 uint64_t u64Val;
7167 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
7168 AssertRC(rc);
7169
7170 pCtx->rflags.u64 = u64Val;
7171 if (pVmcsInfo->RealMode.fRealOnV86Active)
7172 {
7173 pCtx->eflags.Bits.u1VM = 0;
7174 pCtx->eflags.Bits.u2IOPL = pVmcsInfo->RealMode.Eflags.Bits.u2IOPL;
7175 }
7176 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7177 }
7178}
7179
7180
7181/**
7182 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7183 * context.
7184 *
7185 * @param pVCpu The cross context virtual CPU structure.
7186 * @param pVmcsInfo The VMCS info. object.
7187 *
7188 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7189 * do not log!
7190 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7191 * instead!!!
7192 */
7193static void hmR0VmxImportGuestIntrState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7194{
7195 uint32_t u32Val;
7196 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val); AssertRC(rc);
7197 if (!u32Val)
7198 {
7199 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7200 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7201 CPUMSetGuestNmiBlocking(pVCpu, false);
7202 }
7203 else
7204 {
7205 /*
7206 * We must import RIP here to set our EM interrupt-inhibited state.
7207 * We also import RFLAGS as our code that evaluates pending interrupts
7208 * before VM-entry requires it.
7209 */
7210 hmR0VmxImportGuestRip(pVCpu);
7211 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7212
7213 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
7214 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
7215 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7216 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7217
7218 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
7219 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
7220 }
7221}
7222
7223
7224/**
7225 * Worker for VMXR0ImportStateOnDemand.
7226 *
7227 * @returns VBox status code.
7228 * @param pVCpu The cross context virtual CPU structure.
7229 * @param pVmcsInfo The VMCS info. object.
7230 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7231 */
7232static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
7233{
7234 int rc = VINF_SUCCESS;
7235 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7236 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7237 uint32_t u32Val;
7238
7239 /*
7240 * Note! This is hack to workaround a mysterious BSOD observed with release builds
7241 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
7242 * neither are other host platforms.
7243 *
7244 * Committing this temporarily as it prevents BSOD.
7245 *
7246 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
7247 */
7248#ifdef RT_OS_WINDOWS
7249 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
7250 return VERR_HM_IPE_1;
7251#endif
7252
7253 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
7254
7255 /*
7256 * We disable interrupts to make the updating of the state and in particular
7257 * the fExtrn modification atomic wrt to preemption hooks.
7258 */
7259 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
7260
7261 fWhat &= pCtx->fExtrn;
7262 if (fWhat)
7263 {
7264 do
7265 {
7266 if (fWhat & CPUMCTX_EXTRN_RIP)
7267 hmR0VmxImportGuestRip(pVCpu);
7268
7269 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
7270 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7271
7272 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
7273 hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
7274
7275 if (fWhat & CPUMCTX_EXTRN_RSP)
7276 {
7277 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RSP, &pCtx->rsp);
7278 AssertRC(rc);
7279 }
7280
7281 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
7282 {
7283 bool const fRealOnV86Active = pVmcsInfo->RealMode.fRealOnV86Active;
7284 if (fWhat & CPUMCTX_EXTRN_CS)
7285 {
7286 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
7287 hmR0VmxImportGuestRip(pVCpu);
7288 if (fRealOnV86Active)
7289 pCtx->cs.Attr.u = pVmcsInfo->RealMode.AttrCS.u;
7290 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
7291 }
7292 if (fWhat & CPUMCTX_EXTRN_SS)
7293 {
7294 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
7295 if (fRealOnV86Active)
7296 pCtx->ss.Attr.u = pVmcsInfo->RealMode.AttrSS.u;
7297 }
7298 if (fWhat & CPUMCTX_EXTRN_DS)
7299 {
7300 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
7301 if (fRealOnV86Active)
7302 pCtx->ds.Attr.u = pVmcsInfo->RealMode.AttrDS.u;
7303 }
7304 if (fWhat & CPUMCTX_EXTRN_ES)
7305 {
7306 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
7307 if (fRealOnV86Active)
7308 pCtx->es.Attr.u = pVmcsInfo->RealMode.AttrES.u;
7309 }
7310 if (fWhat & CPUMCTX_EXTRN_FS)
7311 {
7312 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
7313 if (fRealOnV86Active)
7314 pCtx->fs.Attr.u = pVmcsInfo->RealMode.AttrFS.u;
7315 }
7316 if (fWhat & CPUMCTX_EXTRN_GS)
7317 {
7318 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
7319 if (fRealOnV86Active)
7320 pCtx->gs.Attr.u = pVmcsInfo->RealMode.AttrGS.u;
7321 }
7322 }
7323
7324 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
7325 {
7326 if (fWhat & CPUMCTX_EXTRN_LDTR)
7327 hmR0VmxImportGuestLdtr(pVCpu);
7328
7329 if (fWhat & CPUMCTX_EXTRN_GDTR)
7330 {
7331 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &pCtx->gdtr.pGdt); AssertRC(rc);
7332 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val); AssertRC(rc);
7333 pCtx->gdtr.cbGdt = u32Val;
7334 }
7335
7336 /* Guest IDTR. */
7337 if (fWhat & CPUMCTX_EXTRN_IDTR)
7338 {
7339 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &pCtx->idtr.pIdt); AssertRC(rc);
7340 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val); AssertRC(rc);
7341 pCtx->idtr.cbIdt = u32Val;
7342 }
7343
7344 /* Guest TR. */
7345 if (fWhat & CPUMCTX_EXTRN_TR)
7346 {
7347 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
7348 don't need to import that one. */
7349 if (!pVmcsInfo->RealMode.fRealOnV86Active)
7350 hmR0VmxImportGuestTr(pVCpu);
7351 }
7352 }
7353
7354 if (fWhat & CPUMCTX_EXTRN_DR7)
7355 {
7356 if (!pVCpu->hm.s.fUsingHyperDR7)
7357 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_DR7, &pCtx->dr[7]); AssertRC(rc);
7358 }
7359
7360 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
7361 {
7362 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip); AssertRC(rc);
7363 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp); AssertRC(rc);
7364 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val); AssertRC(rc);
7365 pCtx->SysEnter.cs = u32Val;
7366 }
7367
7368 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
7369 {
7370 if ( pVM->hm.s.fAllow64BitGuests
7371 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7372 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
7373 }
7374
7375 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
7376 {
7377 if ( pVM->hm.s.fAllow64BitGuests
7378 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7379 {
7380 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
7381 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
7382 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
7383 }
7384 }
7385
7386 if (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
7387 {
7388 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
7389 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
7390 Assert(pMsrs);
7391 Assert(cMsrs <= VMX_MISC_MAX_MSRS(pVM->hm.s.vmx.Msrs.u64Misc));
7392 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
7393 for (uint32_t i = 0; i < cMsrs; i++)
7394 {
7395 uint32_t const idMsr = pMsrs[i].u32Msr;
7396 switch (idMsr)
7397 {
7398 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
7399 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
7400 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
7401 default:
7402 {
7403 pCtx->fExtrn = 0;
7404 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
7405 ASMSetFlags(fEFlags);
7406 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
7407 return VERR_HM_UNEXPECTED_LD_ST_MSR;
7408 }
7409 }
7410 }
7411 }
7412
7413 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
7414 {
7415 if (fWhat & CPUMCTX_EXTRN_CR0)
7416 {
7417 uint64_t u64Cr0;
7418 uint64_t u64Shadow;
7419 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Cr0); AssertRC(rc);
7420 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow); AssertRC(rc);
7421 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7422 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7423#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7424 /*
7425 * Reapply the nested-guest's CR0 fixed bits that might have been altered while
7426 * exporting the nested-guest CR0 for executing using hardware-assisted VMX.
7427 */
7428 if (CPUMIsGuestInVmxNonRootMode(pCtx))
7429 {
7430 u64Cr0 |= pCtx->hwvirt.vmx.Msrs.u64Cr0Fixed0;
7431 u64Cr0 &= pCtx->hwvirt.vmx.Msrs.u64Cr0Fixed1;
7432 }
7433#endif
7434 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
7435 CPUMSetGuestCR0(pVCpu, u64Cr0);
7436 VMMRZCallRing3Enable(pVCpu);
7437 }
7438
7439 if (fWhat & CPUMCTX_EXTRN_CR4)
7440 {
7441 uint64_t u64Cr4;
7442 uint64_t u64Shadow;
7443 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64Cr4); AssertRC(rc);
7444 rc |= VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow); AssertRC(rc);
7445 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7446 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7447#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7448 /*
7449 * Reapply the nested-guest's CR4 fixed bits that might have been altered while
7450 * exporting the nested-guest CR4 for executing using hardware-assisted VMX.
7451 */
7452 if (CPUMIsGuestInVmxNonRootMode(pCtx))
7453 {
7454 u64Cr4 |= pCtx->hwvirt.vmx.Msrs.u64Cr4Fixed0;
7455 u64Cr4 &= pCtx->hwvirt.vmx.Msrs.u64Cr4Fixed1;
7456 }
7457#endif
7458 pCtx->cr4 = u64Cr4;
7459 }
7460
7461 if (fWhat & CPUMCTX_EXTRN_CR3)
7462 {
7463 /* CR0.PG bit changes are always intercepted, so it's up to date. */
7464 if ( pVM->hm.s.vmx.fUnrestrictedGuest
7465 || ( pVM->hm.s.fNestedPaging
7466 && CPUMIsGuestPagingEnabledEx(pCtx)))
7467 {
7468 uint64_t u64Cr3;
7469 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR3, &u64Cr3); AssertRC(rc);
7470 if (pCtx->cr3 != u64Cr3)
7471 {
7472 pCtx->cr3 = u64Cr3;
7473 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
7474 }
7475
7476 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
7477 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
7478 if (CPUMIsGuestInPAEModeEx(pCtx))
7479 {
7480 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
7481 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
7482 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
7483 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
7484 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
7485 }
7486 }
7487 }
7488 }
7489
7490#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7491 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
7492 {
7493 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
7494 && !CPUMIsGuestInVmxNonRootMode(pCtx))
7495 {
7496 Assert(CPUMIsGuestInVmxRootMode(pCtx));
7497 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
7498 if (RT_SUCCESS(rc))
7499 { /* likely */ }
7500 else
7501 break;
7502 }
7503 }
7504#endif
7505 } while (0);
7506
7507 if (RT_SUCCESS(rc))
7508 {
7509 /* Update fExtrn. */
7510 pCtx->fExtrn &= ~fWhat;
7511
7512 /* If everything has been imported, clear the HM keeper bit. */
7513 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
7514 {
7515 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
7516 Assert(!pCtx->fExtrn);
7517 }
7518 }
7519 }
7520 else
7521 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
7522
7523 /*
7524 * Restore interrupts.
7525 */
7526 ASMSetFlags(fEFlags);
7527
7528 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
7529
7530 if (RT_SUCCESS(rc))
7531 { /* likely */ }
7532 else
7533 return rc;
7534
7535 /*
7536 * Honor any pending CR3 updates.
7537 *
7538 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> hmR0VmxCallRing3Callback()
7539 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
7540 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
7541 *
7542 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
7543 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
7544 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
7545 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
7546 *
7547 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
7548 */
7549 if (VMMRZCallRing3IsEnabled(pVCpu))
7550 {
7551 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
7552 {
7553 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
7554 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
7555 }
7556
7557 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
7558 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
7559
7560 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
7561 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
7562 }
7563
7564 return VINF_SUCCESS;
7565}
7566
7567
7568/**
7569 * Saves the guest state from the VMCS into the guest-CPU context.
7570 *
7571 * @returns VBox status code.
7572 * @param pVCpu The cross context virtual CPU structure.
7573 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7574 */
7575VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPUCC pVCpu, uint64_t fWhat)
7576{
7577 AssertPtr(pVCpu);
7578 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7579 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
7580}
7581
7582
7583/**
7584 * Check per-VM and per-VCPU force flag actions that require us to go back to
7585 * ring-3 for one reason or another.
7586 *
7587 * @returns Strict VBox status code (i.e. informational status codes too)
7588 * @retval VINF_SUCCESS if we don't have any actions that require going back to
7589 * ring-3.
7590 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
7591 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
7592 * interrupts)
7593 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
7594 * all EMTs to be in ring-3.
7595 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
7596 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
7597 * to the EM loop.
7598 *
7599 * @param pVCpu The cross context virtual CPU structure.
7600 * @param fStepping Whether we are single-stepping the guest using the
7601 * hypervisor debugger.
7602 *
7603 * @remarks This might cause nested-guest VM-exits, caller must check if the guest
7604 * is no longer in VMX non-root mode.
7605 */
7606static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPUCC pVCpu, bool fStepping)
7607{
7608 Assert(VMMRZCallRing3IsEnabled(pVCpu));
7609
7610 /*
7611 * Update pending interrupts into the APIC's IRR.
7612 */
7613 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
7614 APICUpdatePendingInterrupts(pVCpu);
7615
7616 /*
7617 * Anything pending? Should be more likely than not if we're doing a good job.
7618 */
7619 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7620 if ( !fStepping
7621 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
7622 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
7623 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
7624 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
7625 return VINF_SUCCESS;
7626
7627 /* Pending PGM C3 sync. */
7628 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
7629 {
7630 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7631 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
7632 VBOXSTRICTRC rcStrict = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
7633 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
7634 if (rcStrict != VINF_SUCCESS)
7635 {
7636 AssertRC(VBOXSTRICTRC_VAL(rcStrict));
7637 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict)));
7638 return rcStrict;
7639 }
7640 }
7641
7642 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
7643 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
7644 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
7645 {
7646 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
7647 int rc = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
7648 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc));
7649 return rc;
7650 }
7651
7652 /* Pending VM request packets, such as hardware interrupts. */
7653 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
7654 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
7655 {
7656 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
7657 Log4Func(("Pending VM request forcing us back to ring-3\n"));
7658 return VINF_EM_PENDING_REQUEST;
7659 }
7660
7661 /* Pending PGM pool flushes. */
7662 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
7663 {
7664 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
7665 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
7666 return VINF_PGM_POOL_FLUSH_PENDING;
7667 }
7668
7669 /* Pending DMA requests. */
7670 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
7671 {
7672 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
7673 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
7674 return VINF_EM_RAW_TO_R3;
7675 }
7676
7677#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7678 /* Pending nested-guest APIC-write (has highest priority among nested-guest FFs). */
7679 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
7680 {
7681 Log4Func(("Pending nested-guest APIC-write\n"));
7682 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitApicWrite(pVCpu);
7683 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
7684 return rcStrict;
7685 }
7686 /** @todo VMCPU_FF_VMX_MTF, VMCPU_FF_VMX_PREEMPT_TIMER */
7687#endif
7688
7689 return VINF_SUCCESS;
7690}
7691
7692
7693/**
7694 * Converts any TRPM trap into a pending HM event. This is typically used when
7695 * entering from ring-3 (not longjmp returns).
7696 *
7697 * @param pVCpu The cross context virtual CPU structure.
7698 */
7699static void hmR0VmxTrpmTrapToPendingEvent(PVMCPUCC pVCpu)
7700{
7701 Assert(TRPMHasTrap(pVCpu));
7702 Assert(!pVCpu->hm.s.Event.fPending);
7703
7704 uint8_t uVector;
7705 TRPMEVENT enmTrpmEvent;
7706 RTGCUINT uErrCode;
7707 RTGCUINTPTR GCPtrFaultAddress;
7708 uint8_t cbInstr;
7709
7710 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr);
7711 AssertRC(rc);
7712
7713 uint32_t u32IntInfo;
7714 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
7715 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent);
7716
7717 rc = TRPMResetTrap(pVCpu);
7718 AssertRC(rc);
7719 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
7720 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
7721
7722 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
7723}
7724
7725
7726/**
7727 * Converts the pending HM event into a TRPM trap.
7728 *
7729 * @param pVCpu The cross context virtual CPU structure.
7730 */
7731static void hmR0VmxPendingEventToTrpmTrap(PVMCPUCC pVCpu)
7732{
7733 Assert(pVCpu->hm.s.Event.fPending);
7734
7735 /* If a trap was already pending, we did something wrong! */
7736 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
7737
7738 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
7739 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
7740 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
7741
7742 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
7743
7744 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
7745 AssertRC(rc);
7746
7747 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
7748 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
7749
7750 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
7751 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
7752 else if (VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo) == VMX_IDT_VECTORING_INFO_TYPE_SW_INT)
7753 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
7754
7755 /* We're now done converting the pending event. */
7756 pVCpu->hm.s.Event.fPending = false;
7757}
7758
7759
7760/**
7761 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
7762 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
7763 *
7764 * @param pVCpu The cross context virtual CPU structure.
7765 * @param pVmcsInfo The VMCS info. object.
7766 */
7767static void hmR0VmxSetIntWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
7768{
7769 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
7770 {
7771 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
7772 {
7773 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
7774 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7775 AssertRC(rc);
7776 }
7777 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
7778}
7779
7780
7781/**
7782 * Clears the interrupt-window exiting control in the VMCS.
7783 *
7784 * @param pVmcsInfo The VMCS info. object.
7785 */
7786DECLINLINE(void) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
7787{
7788 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
7789 {
7790 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
7791 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7792 AssertRC(rc);
7793 }
7794}
7795
7796
7797/**
7798 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
7799 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
7800 *
7801 * @param pVCpu The cross context virtual CPU structure.
7802 * @param pVmcsInfo The VMCS info. object.
7803 */
7804static void hmR0VmxSetNmiWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
7805{
7806 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
7807 {
7808 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
7809 {
7810 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
7811 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7812 AssertRC(rc);
7813 Log4Func(("Setup NMI-window exiting\n"));
7814 }
7815 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
7816}
7817
7818
7819/**
7820 * Clears the NMI-window exiting control in the VMCS.
7821 *
7822 * @param pVmcsInfo The VMCS info. object.
7823 */
7824DECLINLINE(void) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
7825{
7826 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
7827 {
7828 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
7829 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7830 AssertRC(rc);
7831 }
7832}
7833
7834
7835/**
7836 * Does the necessary state syncing before returning to ring-3 for any reason
7837 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
7838 *
7839 * @returns VBox status code.
7840 * @param pVCpu The cross context virtual CPU structure.
7841 * @param fImportState Whether to import the guest state from the VMCS back
7842 * to the guest-CPU context.
7843 *
7844 * @remarks No-long-jmp zone!!!
7845 */
7846static int hmR0VmxLeave(PVMCPUCC pVCpu, bool fImportState)
7847{
7848 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
7849 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
7850
7851 RTCPUID const idCpu = RTMpCpuId();
7852 Log4Func(("HostCpuId=%u\n", idCpu));
7853
7854 /*
7855 * !!! IMPORTANT !!!
7856 * If you modify code here, check whether hmR0VmxCallRing3Callback() needs to be updated too.
7857 */
7858
7859 /* Save the guest state if necessary. */
7860 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7861 if (fImportState)
7862 {
7863 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
7864 AssertRCReturn(rc, rc);
7865 }
7866
7867 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
7868 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
7869 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
7870
7871 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
7872#ifdef VBOX_STRICT
7873 if (CPUMIsHyperDebugStateActive(pVCpu))
7874 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
7875#endif
7876 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
7877 Assert(!CPUMIsGuestDebugStateActive(pVCpu) && !CPUMIsGuestDebugStateActivePending(pVCpu));
7878 Assert(!CPUMIsHyperDebugStateActive(pVCpu) && !CPUMIsHyperDebugStateActivePending(pVCpu));
7879
7880 /* Restore host-state bits that VT-x only restores partially. */
7881 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
7882 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
7883 {
7884 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags, idCpu));
7885 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
7886 }
7887 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
7888
7889 /* Restore the lazy host MSRs as we're leaving VT-x context. */
7890 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
7891 {
7892 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
7893 if (!fImportState)
7894 {
7895 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
7896 AssertRCReturn(rc, rc);
7897 }
7898 hmR0VmxLazyRestoreHostMsrs(pVCpu);
7899 Assert(!pVCpu->hm.s.vmx.fLazyMsrs);
7900 }
7901 else
7902 pVCpu->hm.s.vmx.fLazyMsrs = 0;
7903
7904 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
7905 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
7906
7907 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
7908 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
7909 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
7910 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
7911 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
7912 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
7913 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
7914 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
7915 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
7916 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
7917
7918 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
7919
7920 /** @todo This partially defeats the purpose of having preemption hooks.
7921 * The problem is, deregistering the hooks should be moved to a place that
7922 * lasts until the EMT is about to be destroyed not everytime while leaving HM
7923 * context.
7924 */
7925 int rc = hmR0VmxClearVmcs(pVmcsInfo);
7926 AssertRCReturn(rc, rc);
7927
7928#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7929 /*
7930 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
7931 * clear a shadow VMCS before allowing that VMCS to become active on another
7932 * logical processor. We may or may not be importing guest state which clears
7933 * it, so cover for it here.
7934 *
7935 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
7936 */
7937 if ( pVmcsInfo->pvShadowVmcs
7938 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
7939 {
7940 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
7941 AssertRCReturn(rc, rc);
7942 }
7943
7944 /*
7945 * Flag that we need to re-import the host state if we switch to this VMCS before
7946 * executing guest or nested-guest code.
7947 */
7948 pVmcsInfo->idHostCpu = NIL_RTCPUID;
7949#endif
7950
7951 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
7952 NOREF(idCpu);
7953 return VINF_SUCCESS;
7954}
7955
7956
7957/**
7958 * Leaves the VT-x session.
7959 *
7960 * @returns VBox status code.
7961 * @param pVCpu The cross context virtual CPU structure.
7962 *
7963 * @remarks No-long-jmp zone!!!
7964 */
7965static int hmR0VmxLeaveSession(PVMCPUCC pVCpu)
7966{
7967 HM_DISABLE_PREEMPT(pVCpu);
7968 HMVMX_ASSERT_CPU_SAFE(pVCpu);
7969 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
7970 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
7971
7972 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
7973 and done this from the VMXR0ThreadCtxCallback(). */
7974 if (!pVCpu->hm.s.fLeaveDone)
7975 {
7976 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
7977 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
7978 pVCpu->hm.s.fLeaveDone = true;
7979 }
7980 Assert(!pVCpu->cpum.GstCtx.fExtrn);
7981
7982 /*
7983 * !!! IMPORTANT !!!
7984 * If you modify code here, make sure to check whether hmR0VmxCallRing3Callback() needs to be updated too.
7985 */
7986
7987 /* Deregister hook now that we've left HM context before re-enabling preemption. */
7988 /** @todo Deregistering here means we need to VMCLEAR always
7989 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
7990 * for calling VMMR0ThreadCtxHookDisable here! */
7991 VMMR0ThreadCtxHookDisable(pVCpu);
7992
7993 /* Leave HM context. This takes care of local init (term). */
7994 int rc = HMR0LeaveCpu(pVCpu);
7995
7996 HM_RESTORE_PREEMPT();
7997 return rc;
7998}
7999
8000
8001/**
8002 * Does the necessary state syncing before doing a longjmp to ring-3.
8003 *
8004 * @returns VBox status code.
8005 * @param pVCpu The cross context virtual CPU structure.
8006 *
8007 * @remarks No-long-jmp zone!!!
8008 */
8009DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPUCC pVCpu)
8010{
8011 return hmR0VmxLeaveSession(pVCpu);
8012}
8013
8014
8015/**
8016 * Take necessary actions before going back to ring-3.
8017 *
8018 * An action requires us to go back to ring-3. This function does the necessary
8019 * steps before we can safely return to ring-3. This is not the same as longjmps
8020 * to ring-3, this is voluntary and prepares the guest so it may continue
8021 * executing outside HM (recompiler/IEM).
8022 *
8023 * @returns VBox status code.
8024 * @param pVCpu The cross context virtual CPU structure.
8025 * @param rcExit The reason for exiting to ring-3. Can be
8026 * VINF_VMM_UNKNOWN_RING3_CALL.
8027 */
8028static int hmR0VmxExitToRing3(PVMCPUCC pVCpu, VBOXSTRICTRC rcExit)
8029{
8030 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8031
8032 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8033 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8034 {
8035 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8036 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8037 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
8038 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8039 }
8040
8041 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8042 VMMRZCallRing3Disable(pVCpu);
8043 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8044
8045 /*
8046 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8047 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8048 *
8049 * This is because execution may continue from ring-3 and we would need to inject
8050 * the event from there (hence place it back in TRPM).
8051 */
8052 if (pVCpu->hm.s.Event.fPending)
8053 {
8054 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8055 Assert(!pVCpu->hm.s.Event.fPending);
8056
8057 /* Clear the events from the VMCS. */
8058 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0);
8059 AssertRC(rc);
8060 }
8061#ifdef VBOX_STRICT
8062 else
8063 {
8064 /*
8065 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8066 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8067 * occasionally, see @bugref{9180#c42}.
8068 *
8069 * However, if the VM-entry failed, any VM entry-interruption info. field would
8070 * be left unmodified as the event would not have been injected to the guest. In
8071 * such cases, don't assert, we're not going to continue guest execution anyway.
8072 */
8073 uint32_t uExitReason;
8074 uint32_t uEntryIntInfo;
8075 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8076 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8077 AssertRC(rc);
8078 Assert(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo));
8079 }
8080#endif
8081
8082 /*
8083 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8084 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8085 * (e.g. TPR below threshold).
8086 */
8087 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8088 {
8089 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8090 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8091 }
8092
8093 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8094 and if we're injecting an event we should have a TRPM trap pending. */
8095 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8096#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8097 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8098#endif
8099
8100 /* Save guest state and restore host state bits. */
8101 int rc = hmR0VmxLeaveSession(pVCpu);
8102 AssertRCReturn(rc, rc);
8103 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8104
8105 /* Thread-context hooks are unregistered at this point!!! */
8106
8107 /* Sync recompiler state. */
8108 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8109 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8110 | CPUM_CHANGED_LDTR
8111 | CPUM_CHANGED_GDTR
8112 | CPUM_CHANGED_IDTR
8113 | CPUM_CHANGED_TR
8114 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8115 if ( pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging
8116 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8117 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8118
8119 Assert(!pVCpu->hm.s.fClearTrapFlag);
8120
8121 /* Update the exit-to-ring 3 reason. */
8122 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8123
8124 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8125 if ( rcExit != VINF_EM_RAW_INTERRUPT
8126 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8127 {
8128 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8129 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8130 }
8131
8132 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8133
8134 /* We do -not- want any longjmp notifications after this! We must return to ring-3 ASAP. */
8135 VMMRZCallRing3RemoveNotification(pVCpu);
8136 VMMRZCallRing3Enable(pVCpu);
8137
8138 return rc;
8139}
8140
8141
8142/**
8143 * VMMRZCallRing3() callback wrapper which saves the guest state before we
8144 * longjump to ring-3 and possibly get preempted.
8145 *
8146 * @returns VBox status code.
8147 * @param pVCpu The cross context virtual CPU structure.
8148 * @param enmOperation The operation causing the ring-3 longjump.
8149 * @param pvUser User argument, currently unused, NULL.
8150 */
8151static DECLCALLBACK(int) hmR0VmxCallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation, void *pvUser)
8152{
8153 RT_NOREF(pvUser);
8154 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
8155 {
8156 /*
8157 * !!! IMPORTANT !!!
8158 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
8159 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
8160 */
8161 VMMRZCallRing3RemoveNotification(pVCpu);
8162 VMMRZCallRing3Disable(pVCpu);
8163 RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
8164 RTThreadPreemptDisable(&PreemptState);
8165
8166 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8167 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8168 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8169 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8170
8171 /* Restore host-state bits that VT-x only restores partially. */
8172 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8173 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8174 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8175 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8176
8177 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8178 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8179 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8180
8181 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8182 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8183 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8184
8185 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
8186 cleared as part of importing the guest state above. */
8187 hmR0VmxClearVmcs(pVmcsInfo);
8188
8189 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
8190 VMMR0ThreadCtxHookDisable(pVCpu);
8191 HMR0LeaveCpu(pVCpu);
8192 RTThreadPreemptRestore(&PreemptState);
8193 return VINF_SUCCESS;
8194 }
8195
8196 Assert(pVCpu);
8197 Assert(pvUser);
8198 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8199 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8200
8201 VMMRZCallRing3Disable(pVCpu);
8202 Assert(VMMR0IsLogFlushDisabled(pVCpu));
8203
8204 Log4Func(("-> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
8205
8206 int rc = hmR0VmxLongJmpToRing3(pVCpu);
8207 AssertRCReturn(rc, rc);
8208
8209 VMMRZCallRing3Enable(pVCpu);
8210 return VINF_SUCCESS;
8211}
8212
8213
8214/**
8215 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
8216 * stack.
8217 *
8218 * @returns Strict VBox status code (i.e. informational status codes too).
8219 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
8220 * @param pVCpu The cross context virtual CPU structure.
8221 * @param uValue The value to push to the guest stack.
8222 */
8223static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPUCC pVCpu, uint16_t uValue)
8224{
8225 /*
8226 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
8227 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
8228 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
8229 */
8230 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8231 if (pCtx->sp == 1)
8232 return VINF_EM_RESET;
8233 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
8234 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
8235 AssertRC(rc);
8236 return rc;
8237}
8238
8239
8240/**
8241 * Injects an event into the guest upon VM-entry by updating the relevant fields
8242 * in the VM-entry area in the VMCS.
8243 *
8244 * @returns Strict VBox status code (i.e. informational status codes too).
8245 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
8246 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
8247 *
8248 * @param pVCpu The cross context virtual CPU structure.
8249 * @param pVmxTransient The VMX-transient structure.
8250 * @param pEvent The event being injected.
8251 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
8252 * will be updated if necessary. This cannot not be NULL.
8253 * @param fStepping Whether we're single-stepping guest execution and should
8254 * return VINF_EM_DBG_STEPPED if the event is injected
8255 * directly (registers modified by us, not by hardware on
8256 * VM-entry).
8257 */
8258static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
8259 uint32_t *pfIntrState)
8260{
8261 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
8262 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
8263 Assert(pfIntrState);
8264
8265 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8266 uint32_t u32IntInfo = pEvent->u64IntInfo;
8267 uint32_t const u32ErrCode = pEvent->u32ErrCode;
8268 uint32_t const cbInstr = pEvent->cbInstr;
8269 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
8270 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
8271 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
8272
8273#ifdef VBOX_STRICT
8274 /*
8275 * Validate the error-code-valid bit for hardware exceptions.
8276 * No error codes for exceptions in real-mode.
8277 *
8278 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8279 */
8280 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8281 && !CPUMIsGuestInRealModeEx(pCtx))
8282 {
8283 switch (uVector)
8284 {
8285 case X86_XCPT_PF:
8286 case X86_XCPT_DF:
8287 case X86_XCPT_TS:
8288 case X86_XCPT_NP:
8289 case X86_XCPT_SS:
8290 case X86_XCPT_GP:
8291 case X86_XCPT_AC:
8292 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
8293 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
8294 RT_FALL_THRU();
8295 default:
8296 break;
8297 }
8298 }
8299
8300 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
8301 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
8302 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8303#endif
8304
8305 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
8306
8307 /*
8308 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
8309 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
8310 * interrupt handler in the (real-mode) guest.
8311 *
8312 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
8313 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
8314 */
8315 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
8316 {
8317 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest)
8318 {
8319 /*
8320 * For CPUs with unrestricted guest execution enabled and with the guest
8321 * in real-mode, we must not set the deliver-error-code bit.
8322 *
8323 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
8324 */
8325 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
8326 }
8327 else
8328 {
8329 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
8330 Assert(PDMVmmDevHeapIsEnabled(pVM));
8331 Assert(pVM->hm.s.vmx.pRealModeTSS);
8332 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
8333
8334 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
8335 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8336 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
8337 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
8338 AssertRCReturn(rc2, rc2);
8339
8340 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
8341 size_t const cbIdtEntry = sizeof(X86IDTR16);
8342 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
8343 {
8344 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
8345 if (uVector == X86_XCPT_DF)
8346 return VINF_EM_RESET;
8347
8348 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
8349 No error codes for exceptions in real-mode. */
8350 if (uVector == X86_XCPT_GP)
8351 {
8352 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
8353 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8354 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8355 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8356 HMEVENT EventXcptDf;
8357 RT_ZERO(EventXcptDf);
8358 EventXcptDf.u64IntInfo = uXcptDfInfo;
8359 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
8360 }
8361
8362 /*
8363 * If we're injecting an event with no valid IDT entry, inject a #GP.
8364 * No error codes for exceptions in real-mode.
8365 *
8366 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8367 */
8368 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
8369 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8370 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8371 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8372 HMEVENT EventXcptGp;
8373 RT_ZERO(EventXcptGp);
8374 EventXcptGp.u64IntInfo = uXcptGpInfo;
8375 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
8376 }
8377
8378 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
8379 uint16_t uGuestIp = pCtx->ip;
8380 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
8381 {
8382 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
8383 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
8384 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8385 }
8386 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
8387 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8388
8389 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
8390 X86IDTR16 IdtEntry;
8391 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
8392 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
8393 AssertRCReturn(rc2, rc2);
8394
8395 /* Construct the stack frame for the interrupt/exception handler. */
8396 VBOXSTRICTRC rcStrict;
8397 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
8398 if (rcStrict == VINF_SUCCESS)
8399 {
8400 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
8401 if (rcStrict == VINF_SUCCESS)
8402 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
8403 }
8404
8405 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
8406 if (rcStrict == VINF_SUCCESS)
8407 {
8408 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
8409 pCtx->rip = IdtEntry.offSel;
8410 pCtx->cs.Sel = IdtEntry.uSel;
8411 pCtx->cs.ValidSel = IdtEntry.uSel;
8412 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
8413 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
8414 && uVector == X86_XCPT_PF)
8415 pCtx->cr2 = GCPtrFault;
8416
8417 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
8418 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
8419 | HM_CHANGED_GUEST_RSP);
8420
8421 /*
8422 * If we delivered a hardware exception (other than an NMI) and if there was
8423 * block-by-STI in effect, we should clear it.
8424 */
8425 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
8426 {
8427 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
8428 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
8429 Log4Func(("Clearing inhibition due to STI\n"));
8430 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
8431 }
8432
8433 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
8434 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
8435
8436 /*
8437 * The event has been truly dispatched to the guest. Mark it as no longer pending so
8438 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
8439 */
8440 pVCpu->hm.s.Event.fPending = false;
8441
8442 /*
8443 * If we eventually support nested-guest execution without unrestricted guest execution,
8444 * we should set fInterceptEvents here.
8445 */
8446 Assert(!pVmxTransient->fIsNestedGuest);
8447
8448 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
8449 if (fStepping)
8450 rcStrict = VINF_EM_DBG_STEPPED;
8451 }
8452 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
8453 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
8454 return rcStrict;
8455 }
8456 }
8457
8458 /*
8459 * Validate.
8460 */
8461 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
8462 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
8463
8464 /*
8465 * Inject the event into the VMCS.
8466 */
8467 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
8468 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8469 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
8470 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
8471 AssertRC(rc);
8472
8473 /*
8474 * Update guest CR2 if this is a page-fault.
8475 */
8476 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
8477 pCtx->cr2 = GCPtrFault;
8478
8479 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
8480 return VINF_SUCCESS;
8481}
8482
8483
8484/**
8485 * Evaluates the event to be delivered to the guest and sets it as the pending
8486 * event.
8487 *
8488 * @returns Strict VBox status code (i.e. informational status codes too).
8489 * @param pVCpu The cross context virtual CPU structure.
8490 * @param pVmxTransient The VMX-transient structure.
8491 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
8492 */
8493static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
8494{
8495 Assert(pfIntrState);
8496 Assert(!TRPMHasTrap(pVCpu));
8497
8498 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8499 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8500 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
8501
8502 /*
8503 * Get the current interruptibility-state of the guest or nested-guest and
8504 * then figure out what needs to be injected.
8505 */
8506 uint32_t const fIntrState = hmR0VmxGetGuestIntrState(pVCpu, pVmxTransient);
8507 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
8508 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
8509 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
8510
8511 /* We don't support block-by-SMI yet.*/
8512 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI));
8513
8514 /* Block-by-STI must not be set when interrupts are disabled. */
8515 if (fBlockSti)
8516 {
8517 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
8518 Assert(pCtx->eflags.Bits.u1IF);
8519 }
8520
8521 /* Update interruptibility state to the caller. */
8522 *pfIntrState = fIntrState;
8523
8524 /*
8525 * Toggling of interrupt force-flags here is safe since we update TRPM on
8526 * premature exits to ring-3 before executing guest code, see hmR0VmxExitToRing3().
8527 * We must NOT restore these force-flags.
8528 */
8529
8530 /** @todo SMI. SMIs take priority over NMIs. */
8531
8532 /*
8533 * Check if an NMI is pending and if the guest or nested-guest can receive them.
8534 * NMIs take priority over external interrupts.
8535 */
8536 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
8537 {
8538 /* On some CPUs block-by-STI also blocks NMIs. See Intel spec. 26.3.1.5 "Checks On Guest Non-Register State". */
8539 if ( !pVCpu->hm.s.Event.fPending
8540 && !fBlockNmi
8541 && !fBlockSti
8542 && !fBlockMovSS)
8543 {
8544#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8545 if ( fIsNestedGuest
8546 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_NMI_EXIT))
8547 return IEMExecVmxVmexitXcptNmi(pVCpu);
8548#endif
8549 hmR0VmxSetPendingXcptNmi(pVCpu);
8550 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
8551 Log4Func(("Pending NMI\n"));
8552 }
8553 else if (!fIsNestedGuest)
8554 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
8555 /* else: for nested-guests, NMI-window exiting will be picked up when merging VMCS controls. */
8556 }
8557 /*
8558 * Check if an external interrupt (PIC/APIC) is pending and if the guest or nested-guest
8559 * can receive them. Once PDMGetInterrupt() returns a valid interrupt we -must- deliver
8560 * the interrupt. We can no longer re-request it from the APIC.
8561 */
8562 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
8563 && !pVCpu->hm.s.fSingleInstruction)
8564 {
8565 Assert(!DBGFIsStepping(pVCpu));
8566 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
8567 AssertRCReturn(rc, rc);
8568
8569 bool const fBlockInt = !(pCtx->eflags.u32 & X86_EFL_IF);
8570 if ( !pVCpu->hm.s.Event.fPending
8571 && !fBlockInt
8572 && !fBlockSti
8573 && !fBlockMovSS)
8574 {
8575#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8576 if ( fIsNestedGuest
8577 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8578 && !CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8579 {
8580 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
8581 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8582 return rcStrict;
8583 }
8584#endif
8585 uint8_t u8Interrupt;
8586 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
8587 if (RT_SUCCESS(rc))
8588 {
8589#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8590 if ( fIsNestedGuest
8591 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8592 && CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8593 {
8594 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
8595 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8596 return rcStrict;
8597 }
8598#endif
8599 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
8600 Log4Func(("Pending external interrupt vector %#x\n", u8Interrupt));
8601 }
8602 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
8603 {
8604 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
8605
8606 if ( !fIsNestedGuest
8607 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
8608 hmR0VmxApicSetTprThreshold(pVmcsInfo, u8Interrupt >> 4);
8609 /* else: for nested-guests, TPR threshold is picked up while merging VMCS controls. */
8610
8611 /*
8612 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
8613 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
8614 * need to re-set this force-flag here.
8615 */
8616 }
8617 else
8618 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
8619 }
8620 else if (!fIsNestedGuest)
8621 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
8622 /* else: for nested-guests, interrupt-window exiting will be picked up when merging VMCS controls. */
8623 }
8624
8625 return VINF_SUCCESS;
8626}
8627
8628
8629/**
8630 * Injects any pending events into the guest if the guest is in a state to
8631 * receive them.
8632 *
8633 * @returns Strict VBox status code (i.e. informational status codes too).
8634 * @param pVCpu The cross context virtual CPU structure.
8635 * @param pVmxTransient The VMX-transient structure.
8636 * @param fIntrState The VT-x guest-interruptibility state.
8637 * @param fStepping Whether we are single-stepping the guest using the
8638 * hypervisor debugger and should return
8639 * VINF_EM_DBG_STEPPED if the event was dispatched
8640 * directly.
8641 */
8642static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
8643{
8644 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8645 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8646
8647 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
8648 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
8649
8650 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
8651 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
8652 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
8653 Assert(!TRPMHasTrap(pVCpu));
8654
8655 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
8656 if (pVCpu->hm.s.Event.fPending)
8657 {
8658 /*
8659 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
8660 * pending even while injecting an event and in this case, we want a VM-exit as soon as
8661 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
8662 *
8663 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
8664 */
8665 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
8666#ifdef VBOX_STRICT
8667 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
8668 {
8669 bool const fBlockInt = !(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
8670 Assert(!fBlockInt);
8671 Assert(!fBlockSti);
8672 Assert(!fBlockMovSS);
8673 }
8674 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
8675 {
8676 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
8677 Assert(!fBlockSti);
8678 Assert(!fBlockMovSS);
8679 Assert(!fBlockNmi);
8680 }
8681#endif
8682 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
8683 uIntType));
8684
8685 /*
8686 * Inject the event and get any changes to the guest-interruptibility state.
8687 *
8688 * The guest-interruptibility state may need to be updated if we inject the event
8689 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
8690 */
8691 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
8692 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
8693
8694 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
8695 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
8696 else
8697 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
8698 }
8699
8700 /*
8701 * Update the guest-interruptibility state.
8702 *
8703 * This is required for the real-on-v86 software interrupt injection case above, as well as
8704 * updates to the guest state from ring-3 or IEM/REM.
8705 */
8706 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
8707 AssertRC(rc);
8708
8709 /*
8710 * There's no need to clear the VM-entry interruption-information field here if we're not
8711 * injecting anything. VT-x clears the valid bit on every VM-exit.
8712 *
8713 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
8714 */
8715
8716 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
8717 NOREF(fBlockMovSS); NOREF(fBlockSti);
8718 return rcStrict;
8719}
8720
8721
8722/**
8723 * Enters the VT-x session.
8724 *
8725 * @returns VBox status code.
8726 * @param pVCpu The cross context virtual CPU structure.
8727 */
8728VMMR0DECL(int) VMXR0Enter(PVMCPUCC pVCpu)
8729{
8730 AssertPtr(pVCpu);
8731 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
8732 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8733
8734 LogFlowFunc(("pVCpu=%p\n", pVCpu));
8735 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
8736 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
8737
8738#ifdef VBOX_STRICT
8739 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
8740 RTCCUINTREG uHostCr4 = ASMGetCR4();
8741 if (!(uHostCr4 & X86_CR4_VMXE))
8742 {
8743 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
8744 return VERR_VMX_X86_CR4_VMXE_CLEARED;
8745 }
8746#endif
8747
8748 /*
8749 * Load the appropriate VMCS as the current and active one.
8750 */
8751 PVMXVMCSINFO pVmcsInfo;
8752 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
8753 if (!fInNestedGuestMode)
8754 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
8755 else
8756 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
8757 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
8758 if (RT_SUCCESS(rc))
8759 {
8760 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
8761 pVCpu->hm.s.fLeaveDone = false;
8762 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
8763
8764 /*
8765 * Do the EMT scheduled L1D flush here if needed.
8766 */
8767 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
8768 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
8769 else if (pVCpu->CTX_SUFF(pVM)->hm.s.fMdsClearOnSched)
8770 hmR0MdsClear();
8771 }
8772 return rc;
8773}
8774
8775
8776/**
8777 * The thread-context callback (only on platforms which support it).
8778 *
8779 * @param enmEvent The thread-context event.
8780 * @param pVCpu The cross context virtual CPU structure.
8781 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
8782 * @thread EMT(pVCpu)
8783 */
8784VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit)
8785{
8786 AssertPtr(pVCpu);
8787 RT_NOREF1(fGlobalInit);
8788
8789 switch (enmEvent)
8790 {
8791 case RTTHREADCTXEVENT_OUT:
8792 {
8793 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8794 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
8795 VMCPU_ASSERT_EMT(pVCpu);
8796
8797 /* No longjmps (logger flushes, locks) in this fragile context. */
8798 VMMRZCallRing3Disable(pVCpu);
8799 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
8800
8801 /* Restore host-state (FPU, debug etc.) */
8802 if (!pVCpu->hm.s.fLeaveDone)
8803 {
8804 /*
8805 * Do -not- import the guest-state here as we might already be in the middle of importing
8806 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
8807 */
8808 hmR0VmxLeave(pVCpu, false /* fImportState */);
8809 pVCpu->hm.s.fLeaveDone = true;
8810 }
8811
8812 /* Leave HM context, takes care of local init (term). */
8813 int rc = HMR0LeaveCpu(pVCpu);
8814 AssertRC(rc);
8815
8816 /* Restore longjmp state. */
8817 VMMRZCallRing3Enable(pVCpu);
8818 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
8819 break;
8820 }
8821
8822 case RTTHREADCTXEVENT_IN:
8823 {
8824 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8825 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
8826 VMCPU_ASSERT_EMT(pVCpu);
8827
8828 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
8829 VMMRZCallRing3Disable(pVCpu);
8830 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
8831
8832 /* Initialize the bare minimum state required for HM. This takes care of
8833 initializing VT-x if necessary (onlined CPUs, local init etc.) */
8834 int rc = hmR0EnterCpu(pVCpu);
8835 AssertRC(rc);
8836 Assert( (pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
8837 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
8838
8839 /* Load the active VMCS as the current one. */
8840 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8841 rc = hmR0VmxLoadVmcs(pVmcsInfo);
8842 AssertRC(rc);
8843 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
8844 pVCpu->hm.s.fLeaveDone = false;
8845
8846 /* Do the EMT scheduled L1D flush if needed. */
8847 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
8848 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
8849
8850 /* Restore longjmp state. */
8851 VMMRZCallRing3Enable(pVCpu);
8852 break;
8853 }
8854
8855 default:
8856 break;
8857 }
8858}
8859
8860
8861/**
8862 * Exports the host state into the VMCS host-state area.
8863 * Sets up the VM-exit MSR-load area.
8864 *
8865 * The CPU state will be loaded from these fields on every successful VM-exit.
8866 *
8867 * @returns VBox status code.
8868 * @param pVCpu The cross context virtual CPU structure.
8869 *
8870 * @remarks No-long-jump zone!!!
8871 */
8872static int hmR0VmxExportHostState(PVMCPUCC pVCpu)
8873{
8874 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8875
8876 int rc = VINF_SUCCESS;
8877 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
8878 {
8879 hmR0VmxExportHostControlRegs();
8880
8881 rc = hmR0VmxExportHostSegmentRegs(pVCpu);
8882 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8883
8884 hmR0VmxExportHostMsrs(pVCpu);
8885
8886 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
8887 }
8888 return rc;
8889}
8890
8891
8892/**
8893 * Saves the host state in the VMCS host-state.
8894 *
8895 * @returns VBox status code.
8896 * @param pVCpu The cross context virtual CPU structure.
8897 *
8898 * @remarks No-long-jump zone!!!
8899 */
8900VMMR0DECL(int) VMXR0ExportHostState(PVMCPUCC pVCpu)
8901{
8902 AssertPtr(pVCpu);
8903 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8904
8905 /*
8906 * Export the host state here while entering HM context.
8907 * When thread-context hooks are used, we might get preempted and have to re-save the host
8908 * state but most of the time we won't be, so do it here before we disable interrupts.
8909 */
8910 return hmR0VmxExportHostState(pVCpu);
8911}
8912
8913
8914/**
8915 * Exports the guest state into the VMCS guest-state area.
8916 *
8917 * The will typically be done before VM-entry when the guest-CPU state and the
8918 * VMCS state may potentially be out of sync.
8919 *
8920 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
8921 * VM-entry controls.
8922 * Sets up the appropriate VMX non-root function to execute guest code based on
8923 * the guest CPU mode.
8924 *
8925 * @returns VBox strict status code.
8926 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
8927 * without unrestricted guest execution and the VMMDev is not presently
8928 * mapped (e.g. EFI32).
8929 *
8930 * @param pVCpu The cross context virtual CPU structure.
8931 * @param pVmxTransient The VMX-transient structure.
8932 *
8933 * @remarks No-long-jump zone!!!
8934 */
8935static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
8936{
8937 AssertPtr(pVCpu);
8938 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8939 LogFlowFunc(("pVCpu=%p\n", pVCpu));
8940
8941 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
8942
8943 /*
8944 * Determine real-on-v86 mode.
8945 * Used when the guest is in real-mode and unrestricted guest execution is not used.
8946 */
8947 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8948 if ( pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
8949 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
8950 pVmcsInfo->RealMode. fRealOnV86Active = false;
8951 else
8952 {
8953 Assert(!pVmxTransient->fIsNestedGuest);
8954 pVmcsInfo->RealMode.fRealOnV86Active = true;
8955 }
8956
8957 /*
8958 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
8959 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
8960 */
8961 /** @todo r=ramshankar: Move hmR0VmxSelectVMRunHandler inside
8962 * hmR0VmxExportGuestEntryExitCtls and do it conditionally. There shouldn't
8963 * be a need to evaluate this everytime since I'm pretty sure we intercept
8964 * all guest paging mode changes. */
8965 int rc = hmR0VmxSelectVMRunHandler(pVCpu, pVmxTransient);
8966 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8967
8968 rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
8969 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8970
8971 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
8972 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8973
8974 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
8975 if (rcStrict == VINF_SUCCESS)
8976 { /* likely */ }
8977 else
8978 {
8979 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
8980 return rcStrict;
8981 }
8982
8983 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
8984 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8985
8986 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
8987 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8988
8989 rc = hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
8990 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8991
8992 rc = hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
8993 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8994
8995 rc = hmR0VmxExportGuestRip(pVCpu);
8996 rc |= hmR0VmxExportGuestRsp(pVCpu);
8997 rc |= hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
8998 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8999
9000 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9001 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9002
9003 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9004 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9005 | HM_CHANGED_GUEST_CR2
9006 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9007 | HM_CHANGED_GUEST_X87
9008 | HM_CHANGED_GUEST_SSE_AVX
9009 | HM_CHANGED_GUEST_OTHER_XSAVE
9010 | HM_CHANGED_GUEST_XCRx
9011 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9012 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9013 | HM_CHANGED_GUEST_TSC_AUX
9014 | HM_CHANGED_GUEST_OTHER_MSRS
9015 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9016
9017 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9018 return rc;
9019}
9020
9021
9022/**
9023 * Exports the state shared between the host and guest into the VMCS.
9024 *
9025 * @param pVCpu The cross context virtual CPU structure.
9026 * @param pVmxTransient The VMX-transient structure.
9027 *
9028 * @remarks No-long-jump zone!!!
9029 */
9030static void hmR0VmxExportSharedState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9031{
9032 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9033 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9034
9035 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9036 {
9037 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9038 AssertRC(rc);
9039 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9040
9041 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9042 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9043 {
9044 rc = hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9045 AssertRC(rc);
9046 }
9047 }
9048
9049 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9050 {
9051 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9052 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9053 }
9054
9055 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9056 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9057}
9058
9059
9060/**
9061 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9062 *
9063 * @returns Strict VBox status code (i.e. informational status codes too).
9064 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9065 * without unrestricted guest execution and the VMMDev is not presently
9066 * mapped (e.g. EFI32).
9067 *
9068 * @param pVCpu The cross context virtual CPU structure.
9069 * @param pVmxTransient The VMX-transient structure.
9070 *
9071 * @remarks No-long-jump zone!!!
9072 */
9073static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9074{
9075 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9076 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9077 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9078
9079#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9080 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9081#endif
9082
9083 /*
9084 * For many exits it's only RIP that changes and hence try to export it first
9085 * without going through a lot of change flag checks.
9086 */
9087 VBOXSTRICTRC rcStrict;
9088 uint64_t fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9089 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
9090 if ((fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)) == HM_CHANGED_GUEST_RIP)
9091 {
9092 rcStrict = hmR0VmxExportGuestRip(pVCpu);
9093 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9094 { /* likely */}
9095 else
9096 AssertMsgFailedReturn(("Failed to export guest RIP! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)), rcStrict);
9097 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9098 }
9099 else if (fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9100 {
9101 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9102 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9103 { /* likely */}
9104 else
9105 {
9106 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9107 VBOXSTRICTRC_VAL(rcStrict)));
9108 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9109 return rcStrict;
9110 }
9111 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9112 }
9113 else
9114 rcStrict = VINF_SUCCESS;
9115
9116#ifdef VBOX_STRICT
9117 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9118 fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9119 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
9120 AssertMsg(!(fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)),
9121 ("fCtxChanged=%#RX64\n", fCtxChanged));
9122#endif
9123 return rcStrict;
9124}
9125
9126
9127/**
9128 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9129 * and update error record fields accordingly.
9130 *
9131 * @returns VMX_IGS_* error codes.
9132 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9133 * wrong with the guest state.
9134 *
9135 * @param pVCpu The cross context virtual CPU structure.
9136 * @param pVmcsInfo The VMCS info. object.
9137 *
9138 * @remarks This function assumes our cache of the VMCS controls
9139 * are valid, i.e. hmR0VmxCheckVmcsCtls() succeeded.
9140 */
9141static uint32_t hmR0VmxCheckGuestState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9142{
9143#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9144#define HMVMX_CHECK_BREAK(expr, err) do { \
9145 if (!(expr)) { uError = (err); break; } \
9146 } while (0)
9147
9148 int rc;
9149 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9150 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9151 uint32_t uError = VMX_IGS_ERROR;
9152 uint32_t u32Val;
9153 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuest;
9154
9155 do
9156 {
9157 /*
9158 * CR0.
9159 */
9160 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9161 uint64_t fSetCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9162 uint64_t const fZapCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9163 /* Exceptions for unrestricted guest execution for fixed CR0 bits (PE, PG).
9164 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
9165 if (fUnrestrictedGuest)
9166 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
9167
9168 uint64_t u64GuestCr0;
9169 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64GuestCr0);
9170 AssertRC(rc);
9171 HMVMX_CHECK_BREAK((u64GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
9172 HMVMX_CHECK_BREAK(!(u64GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
9173 if ( !fUnrestrictedGuest
9174 && (u64GuestCr0 & X86_CR0_PG)
9175 && !(u64GuestCr0 & X86_CR0_PE))
9176 {
9177 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
9178 }
9179
9180 /*
9181 * CR4.
9182 */
9183 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9184 uint64_t const fSetCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9185 uint64_t const fZapCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9186
9187 uint64_t u64GuestCr4;
9188 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64GuestCr4);
9189 AssertRC(rc);
9190 HMVMX_CHECK_BREAK((u64GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
9191 HMVMX_CHECK_BREAK(!(u64GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
9192
9193 /*
9194 * IA32_DEBUGCTL MSR.
9195 */
9196 uint64_t u64Val;
9197 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
9198 AssertRC(rc);
9199 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9200 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
9201 {
9202 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
9203 }
9204 uint64_t u64DebugCtlMsr = u64Val;
9205
9206#ifdef VBOX_STRICT
9207 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
9208 AssertRC(rc);
9209 Assert(u32Val == pVmcsInfo->u32EntryCtls);
9210#endif
9211 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
9212
9213 /*
9214 * RIP and RFLAGS.
9215 */
9216 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
9217 AssertRC(rc);
9218 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
9219 if ( !fLongModeGuest
9220 || !pCtx->cs.Attr.n.u1Long)
9221 {
9222 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
9223 }
9224 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
9225 * must be identical if the "IA-32e mode guest" VM-entry
9226 * control is 1 and CS.L is 1. No check applies if the
9227 * CPU supports 64 linear-address bits. */
9228
9229 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
9230 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
9231 AssertRC(rc);
9232 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
9233 VMX_IGS_RFLAGS_RESERVED);
9234 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
9235 uint32_t const u32Eflags = u64Val;
9236
9237 if ( fLongModeGuest
9238 || ( fUnrestrictedGuest
9239 && !(u64GuestCr0 & X86_CR0_PE)))
9240 {
9241 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
9242 }
9243
9244 uint32_t u32EntryInfo;
9245 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
9246 AssertRC(rc);
9247 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9248 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
9249
9250 /*
9251 * 64-bit checks.
9252 */
9253 if (fLongModeGuest)
9254 {
9255 HMVMX_CHECK_BREAK(u64GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
9256 HMVMX_CHECK_BREAK(u64GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
9257 }
9258
9259 if ( !fLongModeGuest
9260 && (u64GuestCr4 & X86_CR4_PCIDE))
9261 {
9262 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
9263 }
9264
9265 /** @todo CR3 field must be such that bits 63:52 and bits in the range
9266 * 51:32 beyond the processor's physical-address width are 0. */
9267
9268 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9269 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
9270 {
9271 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
9272 }
9273
9274 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
9275 AssertRC(rc);
9276 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
9277
9278 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
9279 AssertRC(rc);
9280 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
9281
9282 /*
9283 * PERF_GLOBAL MSR.
9284 */
9285 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
9286 {
9287 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
9288 AssertRC(rc);
9289 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
9290 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
9291 }
9292
9293 /*
9294 * PAT MSR.
9295 */
9296 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
9297 {
9298 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
9299 AssertRC(rc);
9300 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
9301 for (unsigned i = 0; i < 8; i++)
9302 {
9303 uint8_t u8Val = (u64Val & 0xff);
9304 if ( u8Val != 0 /* UC */
9305 && u8Val != 1 /* WC */
9306 && u8Val != 4 /* WT */
9307 && u8Val != 5 /* WP */
9308 && u8Val != 6 /* WB */
9309 && u8Val != 7 /* UC- */)
9310 {
9311 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
9312 }
9313 u64Val >>= 8;
9314 }
9315 }
9316
9317 /*
9318 * EFER MSR.
9319 */
9320 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
9321 {
9322 Assert(pVM->hm.s.vmx.fSupportsVmcsEfer);
9323 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
9324 AssertRC(rc);
9325 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
9326 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
9327 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
9328 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
9329 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
9330 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
9331 * iemVmxVmentryCheckGuestState(). */
9332 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9333 || !(u64GuestCr0 & X86_CR0_PG)
9334 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
9335 VMX_IGS_EFER_LMA_LME_MISMATCH);
9336 }
9337
9338 /*
9339 * Segment registers.
9340 */
9341 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9342 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
9343 if (!(u32Eflags & X86_EFL_VM))
9344 {
9345 /* CS */
9346 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
9347 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
9348 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
9349 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
9350 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9351 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
9352 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9353 /* CS cannot be loaded with NULL in protected mode. */
9354 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
9355 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
9356 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
9357 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
9358 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
9359 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
9360 else if (pVM->hm.s.vmx.fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
9361 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
9362 else
9363 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
9364
9365 /* SS */
9366 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9367 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
9368 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
9369 if ( !(pCtx->cr0 & X86_CR0_PE)
9370 || pCtx->cs.Attr.n.u4Type == 3)
9371 {
9372 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
9373 }
9374 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
9375 {
9376 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
9377 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
9378 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
9379 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
9380 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
9381 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9382 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
9383 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9384 }
9385
9386 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
9387 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
9388 {
9389 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
9390 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
9391 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9392 || pCtx->ds.Attr.n.u4Type > 11
9393 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9394 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
9395 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
9396 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
9397 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9398 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
9399 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9400 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9401 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
9402 }
9403 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
9404 {
9405 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
9406 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
9407 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9408 || pCtx->es.Attr.n.u4Type > 11
9409 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9410 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
9411 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
9412 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
9413 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9414 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
9415 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9416 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9417 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
9418 }
9419 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
9420 {
9421 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
9422 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
9423 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9424 || pCtx->fs.Attr.n.u4Type > 11
9425 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
9426 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
9427 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
9428 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
9429 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9430 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
9431 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9432 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9433 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
9434 }
9435 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
9436 {
9437 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
9438 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
9439 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9440 || pCtx->gs.Attr.n.u4Type > 11
9441 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
9442 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
9443 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
9444 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
9445 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9446 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
9447 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9448 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9449 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
9450 }
9451 /* 64-bit capable CPUs. */
9452 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9453 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9454 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9455 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9456 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9457 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9458 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9459 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9460 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9461 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9462 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9463 }
9464 else
9465 {
9466 /* V86 mode checks. */
9467 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
9468 if (pVmcsInfo->RealMode.fRealOnV86Active)
9469 {
9470 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
9471 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
9472 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
9473 }
9474 else
9475 {
9476 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
9477 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
9478 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
9479 }
9480
9481 /* CS */
9482 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
9483 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
9484 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
9485 /* SS */
9486 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
9487 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
9488 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
9489 /* DS */
9490 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
9491 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
9492 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
9493 /* ES */
9494 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
9495 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
9496 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
9497 /* FS */
9498 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
9499 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
9500 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
9501 /* GS */
9502 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
9503 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
9504 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
9505 /* 64-bit capable CPUs. */
9506 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9507 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9508 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9509 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9510 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9511 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9512 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9513 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9514 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9515 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9516 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9517 }
9518
9519 /*
9520 * TR.
9521 */
9522 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
9523 /* 64-bit capable CPUs. */
9524 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
9525 if (fLongModeGuest)
9526 {
9527 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
9528 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
9529 }
9530 else
9531 {
9532 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
9533 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
9534 VMX_IGS_TR_ATTR_TYPE_INVALID);
9535 }
9536 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
9537 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
9538 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
9539 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
9540 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9541 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
9542 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9543 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
9544
9545 /*
9546 * GDTR and IDTR (64-bit capable checks).
9547 */
9548 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
9549 AssertRC(rc);
9550 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
9551
9552 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
9553 AssertRC(rc);
9554 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
9555
9556 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
9557 AssertRC(rc);
9558 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9559
9560 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
9561 AssertRC(rc);
9562 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9563
9564 /*
9565 * Guest Non-Register State.
9566 */
9567 /* Activity State. */
9568 uint32_t u32ActivityState;
9569 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
9570 AssertRC(rc);
9571 HMVMX_CHECK_BREAK( !u32ActivityState
9572 || (u32ActivityState & RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
9573 VMX_IGS_ACTIVITY_STATE_INVALID);
9574 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
9575 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
9576 uint32_t u32IntrState;
9577 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
9578 AssertRC(rc);
9579 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
9580 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9581 {
9582 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
9583 }
9584
9585 /** @todo Activity state and injecting interrupts. Left as a todo since we
9586 * currently don't use activity states but ACTIVE. */
9587
9588 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9589 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
9590
9591 /* Guest interruptibility-state. */
9592 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
9593 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
9594 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9595 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
9596 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
9597 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9598 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
9599 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9600 {
9601 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9602 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9603 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
9604 }
9605 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
9606 {
9607 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9608 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
9609 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9610 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
9611 }
9612 /** @todo Assumes the processor is not in SMM. */
9613 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9614 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
9615 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9616 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9617 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
9618 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
9619 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
9620 {
9621 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI),
9622 VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
9623 }
9624
9625 /* Pending debug exceptions. */
9626 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
9627 AssertRC(rc);
9628 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
9629 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
9630 u32Val = u64Val; /* For pending debug exceptions checks below. */
9631
9632 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9633 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
9634 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
9635 {
9636 if ( (u32Eflags & X86_EFL_TF)
9637 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
9638 {
9639 /* Bit 14 is PendingDebug.BS. */
9640 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
9641 }
9642 if ( !(u32Eflags & X86_EFL_TF)
9643 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
9644 {
9645 /* Bit 14 is PendingDebug.BS. */
9646 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
9647 }
9648 }
9649
9650 /* VMCS link pointer. */
9651 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
9652 AssertRC(rc);
9653 if (u64Val != UINT64_C(0xffffffffffffffff))
9654 {
9655 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
9656 /** @todo Bits beyond the processor's physical-address width MBZ. */
9657 /** @todo SMM checks. */
9658 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
9659 Assert(pVmcsInfo->pvShadowVmcs);
9660 VMXVMCSREVID VmcsRevId;
9661 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
9662 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID),
9663 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
9664 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
9665 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
9666 }
9667
9668 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
9669 * not using nested paging? */
9670 if ( pVM->hm.s.fNestedPaging
9671 && !fLongModeGuest
9672 && CPUMIsGuestInPAEModeEx(pCtx))
9673 {
9674 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
9675 AssertRC(rc);
9676 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9677
9678 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
9679 AssertRC(rc);
9680 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9681
9682 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
9683 AssertRC(rc);
9684 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9685
9686 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
9687 AssertRC(rc);
9688 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9689 }
9690
9691 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
9692 if (uError == VMX_IGS_ERROR)
9693 uError = VMX_IGS_REASON_NOT_FOUND;
9694 } while (0);
9695
9696 pVCpu->hm.s.u32HMError = uError;
9697 return uError;
9698
9699#undef HMVMX_ERROR_BREAK
9700#undef HMVMX_CHECK_BREAK
9701}
9702
9703
9704/**
9705 * Map the APIC-access page for virtualizing APIC accesses.
9706 *
9707 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
9708 * this not done as part of exporting guest state, see @bugref{8721}.
9709 *
9710 * @returns VBox status code.
9711 * @param pVCpu The cross context virtual CPU structure.
9712 */
9713static int hmR0VmxMapHCApicAccessPage(PVMCPUCC pVCpu)
9714{
9715 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9716 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
9717
9718 Assert(PDMHasApic(pVM));
9719 Assert(u64MsrApicBase);
9720
9721 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
9722 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
9723
9724 /* Unalias the existing mapping. */
9725 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
9726 AssertRCReturn(rc, rc);
9727
9728 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
9729 Assert(pVM->hm.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
9730 rc = IOMMMIOMapMMIOHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hm.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
9731 AssertRCReturn(rc, rc);
9732
9733 /* Update the per-VCPU cache of the APIC base MSR. */
9734 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
9735 return VINF_SUCCESS;
9736}
9737
9738
9739/**
9740 * Worker function passed to RTMpOnSpecific() that is to be called on the target
9741 * CPU.
9742 *
9743 * @param idCpu The ID for the CPU the function is called on.
9744 * @param pvUser1 Null, not used.
9745 * @param pvUser2 Null, not used.
9746 */
9747static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
9748{
9749 RT_NOREF3(idCpu, pvUser1, pvUser2);
9750 VMXDispatchHostNmi();
9751}
9752
9753
9754/**
9755 * Dispatching an NMI on the host CPU that received it.
9756 *
9757 * @returns VBox status code.
9758 * @param pVCpu The cross context virtual CPU structure.
9759 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
9760 * executing when receiving the host NMI in VMX non-root
9761 * operation.
9762 */
9763static int hmR0VmxExitHostNmi(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9764{
9765 RTCPUID const idCpu = pVmcsInfo->idHostCpu;
9766
9767 /*
9768 * We don't want to delay dispatching the NMI any more than we have to. However,
9769 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
9770 * after executing guest or nested-guest code for the following reasons:
9771 *
9772 * - We would need to perform VMREADs with interrupts disabled and is orders of
9773 * magnitude worse when we run as a guest hypervisor without VMCS shadowing
9774 * supported by the host hypervisor.
9775 *
9776 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
9777 * longer period of time just for handling an edge case like host NMIs which do
9778 * not occur nearly as frequently as other VM-exits.
9779 *
9780 * Let's cover the most likely scenario first. Check if we are on the target CPU
9781 * and dispatch the NMI right away. This should be much faster than calling into
9782 * RTMpOnSpecific() machinery.
9783 */
9784 bool fDispatched = false;
9785 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
9786 if (idCpu == RTMpCpuId())
9787 {
9788 VMXDispatchHostNmi();
9789 fDispatched = true;
9790 }
9791 ASMSetFlags(fEFlags);
9792 if (fDispatched)
9793 {
9794 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
9795 return VINF_SUCCESS;
9796 }
9797
9798 /*
9799 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
9800 * there should be no race or recursion even if we are unlucky enough to be preempted
9801 * (to the target CPU) without dispatching the host NMI above.
9802 */
9803 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
9804 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
9805}
9806
9807
9808#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9809/**
9810 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
9811 * nested-guest using hardware-assisted VMX.
9812 *
9813 * @param pVCpu The cross context virtual CPU structure.
9814 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
9815 * @param pVmcsInfoGst The guest VMCS info. object.
9816 */
9817static void hmR0VmxMergeMsrBitmapNested(PCVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
9818{
9819 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
9820 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
9821 Assert(pu64MsrBitmap);
9822
9823 /*
9824 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
9825 * MSR that is intercepted by the guest is also intercepted while executing the
9826 * nested-guest using hardware-assisted VMX.
9827 *
9828 * Note! If the nested-guest is not using an MSR bitmap, ever MSR must cause a
9829 * nested-guest VM-exit even if the outer guest is not intercepting some
9830 * MSRs. We cannot assume the caller has initialized the nested-guest
9831 * MSR bitmap in this case.
9832 *
9833 * The guest hypervisor may also switch whether it uses MSR bitmaps for
9834 * each VM-entry, hence initializing it once per-VM while setting up the
9835 * nested-guest VMCS is not sufficient.
9836 */
9837 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
9838 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
9839 {
9840 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
9841 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
9842 Assert(pu64MsrBitmapNstGst);
9843 Assert(pu64MsrBitmapGst);
9844
9845 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
9846 for (uint32_t i = 0; i < cFrags; i++)
9847 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
9848 }
9849 else
9850 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
9851}
9852
9853
9854/**
9855 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
9856 * hardware-assisted VMX execution of the nested-guest.
9857 *
9858 * For a guest, we don't modify these controls once we set up the VMCS and hence
9859 * this function is never called.
9860 *
9861 * For nested-guests since the guest hypervisor provides these controls on every
9862 * nested-guest VM-entry and could potentially change them everytime we need to
9863 * merge them before every nested-guest VM-entry.
9864 *
9865 * @returns VBox status code.
9866 * @param pVCpu The cross context virtual CPU structure.
9867 */
9868static int hmR0VmxMergeVmcsNested(PVMCPUCC pVCpu)
9869{
9870 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9871 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
9872 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
9873 Assert(pVmcsNstGst);
9874
9875 /*
9876 * Merge the controls with the requirements of the guest VMCS.
9877 *
9878 * We do not need to validate the nested-guest VMX features specified in the nested-guest
9879 * VMCS with the features supported by the physical CPU as it's already done by the
9880 * VMLAUNCH/VMRESUME instruction emulation.
9881 *
9882 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
9883 * derived from the VMX features supported by the physical CPU.
9884 */
9885
9886 /* Pin-based VM-execution controls. */
9887 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
9888
9889 /* Processor-based VM-execution controls. */
9890 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
9891 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
9892 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
9893 | VMX_PROC_CTLS_USE_TPR_SHADOW
9894 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
9895
9896 /* Secondary processor-based VM-execution controls. */
9897 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
9898 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
9899 | VMX_PROC_CTLS2_INVPCID
9900 | VMX_PROC_CTLS2_VMCS_SHADOWING
9901 | VMX_PROC_CTLS2_RDTSCP
9902 | VMX_PROC_CTLS2_XSAVES_XRSTORS
9903 | VMX_PROC_CTLS2_APIC_REG_VIRT
9904 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
9905 | VMX_PROC_CTLS2_VMFUNC));
9906
9907 /*
9908 * VM-entry controls:
9909 * These controls contains state that depends on the nested-guest state (primarily
9910 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
9911 * VM-exit. Although the guest hypervisor cannot change it, we need to in order to
9912 * properly continue executing the nested-guest if the EFER MSR changes but does not
9913 * cause a nested-guest VM-exits.
9914 *
9915 * VM-exit controls:
9916 * These controls specify the host state on return. We cannot use the controls from
9917 * the guest hypervisor state as is as it would contain the guest state rather than
9918 * the host state. Since the host state is subject to change (e.g. preemption, trips
9919 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
9920 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
9921 *
9922 * VM-entry MSR-load:
9923 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
9924 * context by the VMLAUNCH/VMRESUME instruction emulation.
9925 *
9926 * VM-exit MSR-store:
9927 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
9928 * back into the VM-exit MSR-store area.
9929 *
9930 * VM-exit MSR-load areas:
9931 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
9932 * can entirely ignore what the guest hypervisor wants to load here.
9933 */
9934
9935 /*
9936 * Exception bitmap.
9937 *
9938 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
9939 * here (and avoid doing anything while exporting nested-guest state), but to keep the
9940 * code more flexible if intercepting exceptions become more dynamic in the future we do
9941 * it as part of exporting the nested-guest state.
9942 */
9943 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
9944
9945 /*
9946 * CR0/CR4 guest/host mask.
9947 *
9948 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
9949 * cause VM-exits, so we need to merge them here.
9950 */
9951 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
9952 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
9953
9954 /*
9955 * Page-fault error-code mask and match.
9956 *
9957 * Although we require unrestricted guest execution (and thereby nested-paging) for
9958 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
9959 * normally intercept #PFs, it might intercept them for debugging purposes.
9960 *
9961 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
9962 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
9963 */
9964 uint32_t u32XcptPFMask;
9965 uint32_t u32XcptPFMatch;
9966 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
9967 {
9968 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
9969 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
9970 }
9971 else
9972 {
9973 u32XcptPFMask = 0;
9974 u32XcptPFMatch = 0;
9975 }
9976
9977 /*
9978 * Pause-Loop exiting.
9979 */
9980 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
9981 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
9982
9983 /*
9984 * Pending debug exceptions.
9985 * Currently just copy whatever the nested-guest provides us.
9986 */
9987 uint64_t const uPendingDbgXcpt = pVmcsNstGst->u64GuestPendingDbgXcpt.u;
9988
9989 /*
9990 * I/O Bitmap.
9991 *
9992 * We do not use the I/O bitmap that may be provided by the guest hypervisor as we always
9993 * intercept all I/O port accesses.
9994 */
9995 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
9996 Assert(!(u32ProcCtls & VMX_PROC_CTLS_USE_IO_BITMAPS));
9997
9998 /*
9999 * VMCS shadowing.
10000 *
10001 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10002 * enabled while executing the nested-guest.
10003 */
10004 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10005
10006 /*
10007 * APIC-access page.
10008 */
10009 RTHCPHYS HCPhysApicAccess;
10010 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10011 {
10012 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
10013 RTGCPHYS const GCPhysApicAccess = pVmcsNstGst->u64AddrApicAccess.u;
10014
10015 /** @todo NSTVMX: This is not really correct but currently is required to make
10016 * things work. We need to re-enable the page handler when we fallback to
10017 * IEM execution of the nested-guest! */
10018 PGMHandlerPhysicalPageTempOff(pVM, GCPhysApicAccess, GCPhysApicAccess);
10019
10020 void *pvPage;
10021 PGMPAGEMAPLOCK PgLockApicAccess;
10022 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysApicAccess, &pvPage, &PgLockApicAccess);
10023 if (RT_SUCCESS(rc))
10024 {
10025 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysApicAccess, &HCPhysApicAccess);
10026 AssertMsgRCReturn(rc, ("Failed to get host-physical address for APIC-access page at %#RGp\n", GCPhysApicAccess), rc);
10027
10028 /** @todo Handle proper releasing of page-mapping lock later. */
10029 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockApicAccess);
10030 }
10031 else
10032 return rc;
10033 }
10034 else
10035 HCPhysApicAccess = 0;
10036
10037 /*
10038 * Virtual-APIC page and TPR threshold.
10039 */
10040 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
10041 RTHCPHYS HCPhysVirtApic;
10042 uint32_t u32TprThreshold;
10043 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10044 {
10045 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW);
10046 RTGCPHYS const GCPhysVirtApic = pVmcsNstGst->u64AddrVirtApic.u;
10047
10048 void *pvPage;
10049 PGMPAGEMAPLOCK PgLockVirtApic;
10050 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysVirtApic, &pvPage, &PgLockVirtApic);
10051 if (RT_SUCCESS(rc))
10052 {
10053 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysVirtApic, &HCPhysVirtApic);
10054 AssertMsgRCReturn(rc, ("Failed to get host-physical address for virtual-APIC page at %#RGp\n", GCPhysVirtApic), rc);
10055
10056 /** @todo Handle proper releasing of page-mapping lock later. */
10057 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockVirtApic);
10058 }
10059 else
10060 return rc;
10061
10062 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10063 }
10064 else
10065 {
10066 HCPhysVirtApic = 0;
10067 u32TprThreshold = 0;
10068
10069 /*
10070 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10071 * used by the guest hypervisor. Preventing MMIO accesses to the physical APIC will
10072 * be taken care of by EPT/shadow paging.
10073 */
10074 if (pVM->hm.s.fAllow64BitGuests)
10075 {
10076 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10077 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10078 }
10079 }
10080
10081 /*
10082 * Validate basic assumptions.
10083 */
10084 Assert(pVM->hm.s.vmx.fAllowUnrestricted);
10085 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10086 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10087
10088 /*
10089 * Commit it to the nested-guest VMCS.
10090 */
10091 int rc = VINF_SUCCESS;
10092 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10093 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10094 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10095 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10096 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10097 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10098 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10099 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10100 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10101 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10102 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10103 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10104 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10105 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10106 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10107 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10108 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10109 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10110 {
10111 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10112 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10113 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10114 }
10115 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10116 {
10117 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10118 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
10119 }
10120 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10121 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
10122 rc |= VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, uPendingDbgXcpt);
10123 AssertRC(rc);
10124
10125 /*
10126 * Update the nested-guest VMCS cache.
10127 */
10128 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10129 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10130 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10131 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10132 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10133 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10134 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10135 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10136 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10137
10138 /*
10139 * We need to flush the TLB if we are switching the APIC-access page address.
10140 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
10141 */
10142 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10143 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = true;
10144
10145 /*
10146 * MSR bitmap.
10147 *
10148 * The MSR bitmap address has already been initialized while setting up the nested-guest
10149 * VMCS, here we need to merge the MSR bitmaps.
10150 */
10151 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10152 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10153
10154 return VINF_SUCCESS;
10155}
10156#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10157
10158
10159/**
10160 * Does the preparations before executing guest code in VT-x.
10161 *
10162 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10163 * recompiler/IEM. We must be cautious what we do here regarding committing
10164 * guest-state information into the VMCS assuming we assuredly execute the
10165 * guest in VT-x mode.
10166 *
10167 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10168 * the common-state (TRPM/forceflags), we must undo those changes so that the
10169 * recompiler/IEM can (and should) use them when it resumes guest execution.
10170 * Otherwise such operations must be done when we can no longer exit to ring-3.
10171 *
10172 * @returns Strict VBox status code (i.e. informational status codes too).
10173 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10174 * have been disabled.
10175 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10176 * pending events).
10177 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10178 * double-fault into the guest.
10179 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10180 * dispatched directly.
10181 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10182 *
10183 * @param pVCpu The cross context virtual CPU structure.
10184 * @param pVmxTransient The VMX-transient structure.
10185 * @param fStepping Whether we are single-stepping the guest in the
10186 * hypervisor debugger. Makes us ignore some of the reasons
10187 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
10188 * if event dispatching took place.
10189 */
10190static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
10191{
10192 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10193
10194 Log4Func(("fIsNested=%RTbool fStepping=%RTbool\n", pVmxTransient->fIsNestedGuest, fStepping));
10195
10196#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
10197 if (pVmxTransient->fIsNestedGuest)
10198 {
10199 RT_NOREF2(pVCpu, fStepping);
10200 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
10201 return VINF_EM_RESCHEDULE_REM;
10202 }
10203#endif
10204
10205#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
10206 PGMRZDynMapFlushAutoSet(pVCpu);
10207#endif
10208
10209 /*
10210 * Check and process force flag actions, some of which might require us to go back to ring-3.
10211 */
10212 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, fStepping);
10213 if (rcStrict == VINF_SUCCESS)
10214 {
10215 /* FFs don't get set all the time. */
10216#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10217 if ( pVmxTransient->fIsNestedGuest
10218 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10219 {
10220 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10221 return VINF_VMX_VMEXIT;
10222 }
10223#endif
10224 }
10225 else
10226 return rcStrict;
10227
10228 /*
10229 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
10230 */
10231 /** @todo Doing this from ring-3 after VM setup phase causes a
10232 * VERR_IOM_MMIO_RANGE_NOT_FOUND guru while booting Visa 64 SMP VM. No
10233 * idea why atm. */
10234 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10235 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
10236 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10237 && PDMHasApic(pVM))
10238 {
10239 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
10240 AssertRCReturn(rc, rc);
10241 }
10242
10243#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10244 /*
10245 * Merge guest VMCS controls with the nested-guest VMCS controls.
10246 *
10247 * Even if we have not executed the guest prior to this (e.g. when resuming from a
10248 * saved state), we should be okay with merging controls as we initialize the
10249 * guest VMCS controls as part of VM setup phase.
10250 */
10251 if ( pVmxTransient->fIsNestedGuest
10252 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
10253 {
10254 int rc = hmR0VmxMergeVmcsNested(pVCpu);
10255 AssertRCReturn(rc, rc);
10256 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
10257 }
10258#endif
10259
10260 /*
10261 * Evaluate events to be injected into the guest.
10262 *
10263 * Events in TRPM can be injected without inspecting the guest state.
10264 * If any new events (interrupts/NMI) are pending currently, we try to set up the
10265 * guest to cause a VM-exit the next time they are ready to receive the event.
10266 *
10267 * With nested-guests, evaluating pending events may cause VM-exits.
10268 */
10269 if (TRPMHasTrap(pVCpu))
10270 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
10271
10272 uint32_t fIntrState;
10273 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
10274
10275#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10276 /*
10277 * While evaluating pending events if something failed (unlikely) or if we were
10278 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
10279 */
10280 if (rcStrict != VINF_SUCCESS)
10281 return rcStrict;
10282 if ( pVmxTransient->fIsNestedGuest
10283 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10284 {
10285 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10286 return VINF_VMX_VMEXIT;
10287 }
10288#else
10289 Assert(rcStrict == VINF_SUCCESS);
10290#endif
10291
10292 /*
10293 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
10294 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
10295 * also result in triple-faulting the VM.
10296 *
10297 * With nested-guests, the above does not apply since unrestricted guest execution is a
10298 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
10299 */
10300 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
10301 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10302 { /* likely */ }
10303 else
10304 {
10305 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
10306 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
10307 return rcStrict;
10308 }
10309
10310 /*
10311 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
10312 * import CR3 themselves. We will need to update them here, as even as late as the above
10313 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
10314 * the below force flags to be set.
10315 */
10316 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
10317 {
10318 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
10319 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
10320 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
10321 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
10322 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10323 }
10324 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
10325 {
10326 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
10327 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10328 }
10329
10330#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10331 /* Paranoia. */
10332 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10333#endif
10334
10335 /*
10336 * No longjmps to ring-3 from this point on!!!
10337 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
10338 * This also disables flushing of the R0-logger instance (if any).
10339 */
10340 VMMRZCallRing3Disable(pVCpu);
10341
10342 /*
10343 * Export the guest state bits.
10344 *
10345 * We cannot perform longjmps while loading the guest state because we do not preserve the
10346 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
10347 * CPU migration.
10348 *
10349 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
10350 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
10351 */
10352 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
10353 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10354 { /* likely */ }
10355 else
10356 {
10357 VMMRZCallRing3Enable(pVCpu);
10358 return rcStrict;
10359 }
10360
10361 /*
10362 * We disable interrupts so that we don't miss any interrupts that would flag preemption
10363 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
10364 * preemption disabled for a while. Since this is purely to aid the
10365 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
10366 * disable interrupt on NT.
10367 *
10368 * We need to check for force-flags that could've possible been altered since we last
10369 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
10370 * see @bugref{6398}).
10371 *
10372 * We also check a couple of other force-flags as a last opportunity to get the EMT back
10373 * to ring-3 before executing guest code.
10374 */
10375 pVmxTransient->fEFlags = ASMIntDisableFlags();
10376
10377 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
10378 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
10379 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
10380 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
10381 {
10382 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
10383 {
10384#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10385 /*
10386 * If we are executing a nested-guest make sure that we should intercept subsequent
10387 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
10388 * the VM-exit instruction emulation happy.
10389 */
10390 if (pVmxTransient->fIsNestedGuest)
10391 pVCpu->cpum.GstCtx.hwvirt.vmx.fInterceptEvents = true;
10392#endif
10393
10394 /*
10395 * We've injected any pending events. This is really the point of no return (to ring-3).
10396 *
10397 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
10398 * returns from this function, so do -not- enable them here.
10399 */
10400 pVCpu->hm.s.Event.fPending = false;
10401 return VINF_SUCCESS;
10402 }
10403
10404 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
10405 rcStrict = VINF_EM_RAW_INTERRUPT;
10406 }
10407 else
10408 {
10409 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
10410 rcStrict = VINF_EM_RAW_TO_R3;
10411 }
10412
10413 ASMSetFlags(pVmxTransient->fEFlags);
10414 VMMRZCallRing3Enable(pVCpu);
10415
10416 return rcStrict;
10417}
10418
10419
10420/**
10421 * Final preparations before executing guest code using hardware-assisted VMX.
10422 *
10423 * We can no longer get preempted to a different host CPU and there are no returns
10424 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
10425 * failures), this function is not intended to fail sans unrecoverable hardware
10426 * errors.
10427 *
10428 * @param pVCpu The cross context virtual CPU structure.
10429 * @param pVmxTransient The VMX-transient structure.
10430 *
10431 * @remarks Called with preemption disabled.
10432 * @remarks No-long-jump zone!!!
10433 */
10434static void hmR0VmxPreRunGuestCommitted(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
10435{
10436 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10437 Assert(VMMR0IsLogFlushDisabled(pVCpu));
10438 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
10439 Assert(!pVCpu->hm.s.Event.fPending);
10440
10441 /*
10442 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
10443 */
10444 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10445 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
10446
10447 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10448 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10449 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
10450 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
10451
10452 if (!CPUMIsGuestFPUStateActive(pVCpu))
10453 {
10454 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10455 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
10456 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
10457 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10458 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
10459 }
10460
10461 /*
10462 * Re-export the host state bits as we may've been preempted (only happens when
10463 * thread-context hooks are used or when the VM start function changes) or if
10464 * the host CR0 is modified while loading the guest FPU state above.
10465 *
10466 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
10467 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
10468 * see @bugref{8432}.
10469 *
10470 * This may also happen when switching to/from a nested-guest VMCS without leaving
10471 * ring-0.
10472 */
10473 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
10474 {
10475 hmR0VmxExportHostState(pVCpu);
10476 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
10477 }
10478 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
10479
10480 /*
10481 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
10482 */
10483 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
10484 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
10485 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
10486
10487 /*
10488 * Store status of the shared guest/host debug state at the time of VM-entry.
10489 */
10490 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
10491 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
10492
10493 /*
10494 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
10495 * more than one conditional check. The post-run side of our code shall determine
10496 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
10497 */
10498 if (pVmcsInfo->pbVirtApic)
10499 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
10500
10501 /*
10502 * Update the host MSRs values in the VM-exit MSR-load area.
10503 */
10504 if (!pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs)
10505 {
10506 if (pVmcsInfo->cExitMsrLoad > 0)
10507 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
10508 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = true;
10509 }
10510
10511 /*
10512 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
10513 * VMX-preemption timer based on the next virtual sync clock deadline.
10514 */
10515 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
10516 || idCurrentCpu != pVCpu->hm.s.idLastCpu)
10517 {
10518 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
10519 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
10520 }
10521
10522 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
10523 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
10524 if (!fIsRdtscIntercepted)
10525 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
10526 else
10527 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
10528
10529 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
10530 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
10531 Assert(idCurrentCpu == pVCpu->hm.s.idLastCpu);
10532 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Update the error reporting info. with the current host CPU. */
10533 pVmcsInfo->idHostCpu = idCurrentCpu; /* Update the CPU for which we updated host-state in this VMCS. */
10534
10535 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
10536
10537 TMNotifyStartOfExecution(pVM, pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
10538 as we're about to start executing the guest . */
10539
10540 /*
10541 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
10542 *
10543 * This is done this late as updating the TSC offsetting/preemption timer above
10544 * figures out if we can skip intercepting RDTSCP by calculating the number of
10545 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
10546 */
10547 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
10548 && !fIsRdtscIntercepted)
10549 {
10550 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
10551
10552 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
10553 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
10554 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
10555 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
10556 AssertRC(rc);
10557 Assert(!pVmxTransient->fRemoveTscAuxMsr);
10558 pVmxTransient->fRemoveTscAuxMsr = true;
10559 }
10560
10561#ifdef VBOX_STRICT
10562 Assert(pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs);
10563 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
10564 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo);
10565 AssertRC(hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
10566#endif
10567
10568#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
10569 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
10570 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
10571 * see @bugref{9180#c54}. */
10572 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
10573 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
10574 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
10575#endif
10576}
10577
10578
10579/**
10580 * First C routine invoked after running guest code using hardware-assisted VMX.
10581 *
10582 * @param pVCpu The cross context virtual CPU structure.
10583 * @param pVmxTransient The VMX-transient structure.
10584 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
10585 *
10586 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
10587 *
10588 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
10589 * unconditionally when it is safe to do so.
10590 */
10591static void hmR0VmxPostRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
10592{
10593 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
10594
10595 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
10596 ASMAtomicIncU32(&pVCpu->hm.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
10597 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
10598 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
10599 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
10600 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
10601
10602 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10603 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
10604 {
10605 uint64_t uGstTsc;
10606 if (!pVmxTransient->fIsNestedGuest)
10607 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10608 else
10609 {
10610 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10611 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
10612 }
10613 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
10614 }
10615
10616 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
10617 TMNotifyEndOfExecution(pVCpu->CTX_SUFF(pVM), pVCpu); /* Notify TM that the guest is no longer running. */
10618 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10619
10620 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
10621 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
10622#ifdef VBOX_STRICT
10623 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
10624#endif
10625 Assert(!ASMIntAreEnabled());
10626 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
10627 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10628
10629#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
10630 /*
10631 * Clean all the VMCS fields in the transient structure before reading
10632 * anything from the VMCS.
10633 */
10634 pVmxTransient->uExitReason = 0;
10635 pVmxTransient->uExitIntErrorCode = 0;
10636 pVmxTransient->uExitQual = 0;
10637 pVmxTransient->uGuestLinearAddr = 0;
10638 pVmxTransient->uExitIntInfo = 0;
10639 pVmxTransient->cbInstr = 0;
10640 pVmxTransient->ExitInstrInfo.u = 0;
10641 pVmxTransient->uEntryIntInfo = 0;
10642 pVmxTransient->uEntryXcptErrorCode = 0;
10643 pVmxTransient->cbEntryInstr = 0;
10644 pVmxTransient->uIdtVectoringInfo = 0;
10645 pVmxTransient->uIdtVectoringErrorCode = 0;
10646#endif
10647
10648 /*
10649 * Save the basic VM-exit reason and check if the VM-entry failed.
10650 * See Intel spec. 24.9.1 "Basic VM-exit Information".
10651 */
10652 uint32_t uExitReason;
10653 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
10654 AssertRC(rc);
10655 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
10656 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
10657
10658 /*
10659 * Log the VM-exit before logging anything else as otherwise it might be a
10660 * tad confusing what happens before and after the world-switch.
10661 */
10662 HMVMX_LOG_EXIT(pVCpu, uExitReason);
10663
10664 /*
10665 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
10666 * bitmap permissions, if it was added before VM-entry.
10667 */
10668 if (pVmxTransient->fRemoveTscAuxMsr)
10669 {
10670 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
10671 pVmxTransient->fRemoveTscAuxMsr = false;
10672 }
10673
10674 /*
10675 * Check if VMLAUNCH/VMRESUME succeeded.
10676 * If this failed, we cause a guru meditation and cease further execution.
10677 *
10678 * However, if we are executing a nested-guest we might fail if we use the
10679 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
10680 */
10681 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
10682 {
10683 /*
10684 * Update the VM-exit history array here even if the VM-entry failed due to:
10685 * - Invalid guest state.
10686 * - MSR loading.
10687 * - Machine-check event.
10688 *
10689 * In any of the above cases we will still have a "valid" VM-exit reason
10690 * despite @a fVMEntryFailed being false.
10691 *
10692 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
10693 *
10694 * Note! We don't have CS or RIP at this point. Will probably address that later
10695 * by amending the history entry added here.
10696 */
10697 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
10698 UINT64_MAX, uHostTsc);
10699
10700 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
10701 {
10702 VMMRZCallRing3Enable(pVCpu);
10703
10704 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10705 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10706
10707#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
10708 hmR0VmxReadAllRoFieldsVmcs(pVmxTransient);
10709#endif
10710#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
10711 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
10712 AssertRC(rc);
10713#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
10714 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_RFLAGS);
10715 AssertRC(rc);
10716#else
10717 /*
10718 * Import the guest-interruptibility state always as we need it while evaluating
10719 * injecting events on re-entry.
10720 *
10721 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
10722 * checking for real-mode while exporting the state because all bits that cause
10723 * mode changes wrt CR0 are intercepted.
10724 */
10725 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_HM_VMX_INT_STATE);
10726 AssertRC(rc);
10727#endif
10728
10729 /*
10730 * Sync the TPR shadow with our APIC state.
10731 */
10732 if ( !pVmxTransient->fIsNestedGuest
10733 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
10734 {
10735 Assert(pVmcsInfo->pbVirtApic);
10736 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
10737 {
10738 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
10739 AssertRC(rc);
10740 ASMAtomicOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
10741 }
10742 }
10743
10744 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10745 return;
10746 }
10747 }
10748#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10749 else if (pVmxTransient->fIsNestedGuest)
10750 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
10751#endif
10752 else
10753 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
10754
10755 VMMRZCallRing3Enable(pVCpu);
10756}
10757
10758
10759/**
10760 * Runs the guest code using hardware-assisted VMX the normal way.
10761 *
10762 * @returns VBox status code.
10763 * @param pVCpu The cross context virtual CPU structure.
10764 * @param pcLoops Pointer to the number of executed loops.
10765 */
10766static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPUCC pVCpu, uint32_t *pcLoops)
10767{
10768 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
10769 Assert(pcLoops);
10770 Assert(*pcLoops <= cMaxResumeLoops);
10771 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10772
10773#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10774 /*
10775 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
10776 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
10777 * guest VMCS while entering the VMX ring-0 session.
10778 */
10779 if (pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
10780 {
10781 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
10782 if (RT_SUCCESS(rc))
10783 { /* likely */ }
10784 else
10785 {
10786 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
10787 return rc;
10788 }
10789 }
10790#endif
10791
10792 VMXTRANSIENT VmxTransient;
10793 RT_ZERO(VmxTransient);
10794 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
10795
10796 /* Paranoia. */
10797 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfo);
10798
10799 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
10800 for (;;)
10801 {
10802 Assert(!HMR0SuspendPending());
10803 HMVMX_ASSERT_CPU_SAFE(pVCpu);
10804 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
10805
10806 /*
10807 * Preparatory work for running nested-guest code, this may force us to
10808 * return to ring-3.
10809 *
10810 * Warning! This bugger disables interrupts on VINF_SUCCESS!
10811 */
10812 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
10813 if (rcStrict != VINF_SUCCESS)
10814 break;
10815
10816 /* Interrupts are disabled at this point! */
10817 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
10818 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
10819 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
10820 /* Interrupts are re-enabled at this point! */
10821
10822 /*
10823 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
10824 */
10825 if (RT_SUCCESS(rcRun))
10826 { /* very likely */ }
10827 else
10828 {
10829 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
10830 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
10831 return rcRun;
10832 }
10833
10834 /*
10835 * Profile the VM-exit.
10836 */
10837 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
10838 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
10839 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
10840 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
10841 HMVMX_START_EXIT_DISPATCH_PROF();
10842
10843 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
10844
10845 /*
10846 * Handle the VM-exit.
10847 */
10848#ifdef HMVMX_USE_FUNCTION_TABLE
10849 rcStrict = g_apfnVMExitHandlers[VmxTransient.uExitReason](pVCpu, &VmxTransient);
10850#else
10851 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
10852#endif
10853 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
10854 if (rcStrict == VINF_SUCCESS)
10855 {
10856 if (++(*pcLoops) <= cMaxResumeLoops)
10857 continue;
10858 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
10859 rcStrict = VINF_EM_RAW_INTERRUPT;
10860 }
10861 break;
10862 }
10863
10864 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
10865 return rcStrict;
10866}
10867
10868
10869#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10870/**
10871 * Runs the nested-guest code using hardware-assisted VMX.
10872 *
10873 * @returns VBox status code.
10874 * @param pVCpu The cross context virtual CPU structure.
10875 * @param pcLoops Pointer to the number of executed loops.
10876 *
10877 * @sa hmR0VmxRunGuestCodeNormal.
10878 */
10879static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPUCC pVCpu, uint32_t *pcLoops)
10880{
10881 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
10882 Assert(pcLoops);
10883 Assert(*pcLoops <= cMaxResumeLoops);
10884 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10885
10886 /*
10887 * Switch to the nested-guest VMCS as we may have transitioned from executing the
10888 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
10889 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
10890 */
10891 if (!pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
10892 {
10893 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
10894 if (RT_SUCCESS(rc))
10895 { /* likely */ }
10896 else
10897 {
10898 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
10899 return rc;
10900 }
10901 }
10902
10903 VMXTRANSIENT VmxTransient;
10904 RT_ZERO(VmxTransient);
10905 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
10906 VmxTransient.fIsNestedGuest = true;
10907
10908 /* Paranoia. */
10909 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfoNstGst);
10910
10911 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
10912 for (;;)
10913 {
10914 Assert(!HMR0SuspendPending());
10915 HMVMX_ASSERT_CPU_SAFE(pVCpu);
10916 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
10917
10918 /*
10919 * Preparatory work for running guest code, this may force us to
10920 * return to ring-3.
10921 *
10922 * Warning! This bugger disables interrupts on VINF_SUCCESS!
10923 */
10924 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
10925 if (rcStrict != VINF_SUCCESS)
10926 break;
10927
10928 /* Interrupts are disabled at this point! */
10929 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
10930 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
10931 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
10932 /* Interrupts are re-enabled at this point! */
10933
10934 /*
10935 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
10936 */
10937 if (RT_SUCCESS(rcRun))
10938 { /* very likely */ }
10939 else
10940 {
10941 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
10942 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
10943 return rcRun;
10944 }
10945
10946 /*
10947 * Profile the VM-exit.
10948 */
10949 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
10950 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
10951 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
10952 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
10953 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
10954 HMVMX_START_EXIT_DISPATCH_PROF();
10955
10956 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
10957
10958 /*
10959 * Handle the VM-exit.
10960 */
10961 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
10962 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
10963 if (rcStrict == VINF_SUCCESS)
10964 {
10965 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10966 {
10967 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10968 rcStrict = VINF_VMX_VMEXIT;
10969 }
10970 else
10971 {
10972 if (++(*pcLoops) <= cMaxResumeLoops)
10973 continue;
10974 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
10975 rcStrict = VINF_EM_RAW_INTERRUPT;
10976 }
10977 }
10978 else
10979 Assert(rcStrict != VINF_VMX_VMEXIT);
10980 break;
10981 }
10982
10983 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
10984 return rcStrict;
10985}
10986#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10987
10988
10989/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
10990 * probes.
10991 *
10992 * The following few functions and associated structure contains the bloat
10993 * necessary for providing detailed debug events and dtrace probes as well as
10994 * reliable host side single stepping. This works on the principle of
10995 * "subclassing" the normal execution loop and workers. We replace the loop
10996 * method completely and override selected helpers to add necessary adjustments
10997 * to their core operation.
10998 *
10999 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11000 * any performance for debug and analysis features.
11001 *
11002 * @{
11003 */
11004
11005/**
11006 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11007 * the debug run loop.
11008 */
11009typedef struct VMXRUNDBGSTATE
11010{
11011 /** The RIP we started executing at. This is for detecting that we stepped. */
11012 uint64_t uRipStart;
11013 /** The CS we started executing with. */
11014 uint16_t uCsStart;
11015
11016 /** Whether we've actually modified the 1st execution control field. */
11017 bool fModifiedProcCtls : 1;
11018 /** Whether we've actually modified the 2nd execution control field. */
11019 bool fModifiedProcCtls2 : 1;
11020 /** Whether we've actually modified the exception bitmap. */
11021 bool fModifiedXcptBitmap : 1;
11022
11023 /** We desire the modified the CR0 mask to be cleared. */
11024 bool fClearCr0Mask : 1;
11025 /** We desire the modified the CR4 mask to be cleared. */
11026 bool fClearCr4Mask : 1;
11027 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11028 uint32_t fCpe1Extra;
11029 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11030 uint32_t fCpe1Unwanted;
11031 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11032 uint32_t fCpe2Extra;
11033 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11034 uint32_t bmXcptExtra;
11035 /** The sequence number of the Dtrace provider settings the state was
11036 * configured against. */
11037 uint32_t uDtraceSettingsSeqNo;
11038 /** VM-exits to check (one bit per VM-exit). */
11039 uint32_t bmExitsToCheck[3];
11040
11041 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11042 uint32_t fProcCtlsInitial;
11043 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11044 uint32_t fProcCtls2Initial;
11045 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11046 uint32_t bmXcptInitial;
11047} VMXRUNDBGSTATE;
11048AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11049typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11050
11051
11052/**
11053 * Initializes the VMXRUNDBGSTATE structure.
11054 *
11055 * @param pVCpu The cross context virtual CPU structure of the
11056 * calling EMT.
11057 * @param pVmxTransient The VMX-transient structure.
11058 * @param pDbgState The debug state to initialize.
11059 */
11060static void hmR0VmxRunDebugStateInit(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11061{
11062 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11063 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11064
11065 pDbgState->fModifiedProcCtls = false;
11066 pDbgState->fModifiedProcCtls2 = false;
11067 pDbgState->fModifiedXcptBitmap = false;
11068 pDbgState->fClearCr0Mask = false;
11069 pDbgState->fClearCr4Mask = false;
11070 pDbgState->fCpe1Extra = 0;
11071 pDbgState->fCpe1Unwanted = 0;
11072 pDbgState->fCpe2Extra = 0;
11073 pDbgState->bmXcptExtra = 0;
11074 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11075 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11076 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11077}
11078
11079
11080/**
11081 * Updates the VMSC fields with changes requested by @a pDbgState.
11082 *
11083 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11084 * immediately before executing guest code, i.e. when interrupts are disabled.
11085 * We don't check status codes here as we cannot easily assert or return in the
11086 * latter case.
11087 *
11088 * @param pVCpu The cross context virtual CPU structure.
11089 * @param pVmxTransient The VMX-transient structure.
11090 * @param pDbgState The debug state.
11091 */
11092static void hmR0VmxPreRunGuestDebugStateApply(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11093{
11094 /*
11095 * Ensure desired flags in VMCS control fields are set.
11096 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11097 *
11098 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11099 * there should be no stale data in pCtx at this point.
11100 */
11101 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11102 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11103 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11104 {
11105 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11106 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11107 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11108 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11109 pDbgState->fModifiedProcCtls = true;
11110 }
11111
11112 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11113 {
11114 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11115 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11116 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11117 pDbgState->fModifiedProcCtls2 = true;
11118 }
11119
11120 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11121 {
11122 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11123 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11124 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11125 pDbgState->fModifiedXcptBitmap = true;
11126 }
11127
11128 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11129 {
11130 pVmcsInfo->u64Cr0Mask = 0;
11131 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, 0);
11132 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11133 }
11134
11135 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11136 {
11137 pVmcsInfo->u64Cr4Mask = 0;
11138 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, 0);
11139 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11140 }
11141
11142 NOREF(pVCpu);
11143}
11144
11145
11146/**
11147 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11148 * re-entry next time around.
11149 *
11150 * @returns Strict VBox status code (i.e. informational status codes too).
11151 * @param pVCpu The cross context virtual CPU structure.
11152 * @param pVmxTransient The VMX-transient structure.
11153 * @param pDbgState The debug state.
11154 * @param rcStrict The return code from executing the guest using single
11155 * stepping.
11156 */
11157static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11158 VBOXSTRICTRC rcStrict)
11159{
11160 /*
11161 * Restore VM-exit control settings as we may not reenter this function the
11162 * next time around.
11163 */
11164 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11165
11166 /* We reload the initial value, trigger what we can of recalculations the
11167 next time around. From the looks of things, that's all that's required atm. */
11168 if (pDbgState->fModifiedProcCtls)
11169 {
11170 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11171 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11172 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
11173 AssertRC(rc2);
11174 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
11175 }
11176
11177 /* We're currently the only ones messing with this one, so just restore the
11178 cached value and reload the field. */
11179 if ( pDbgState->fModifiedProcCtls2
11180 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
11181 {
11182 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
11183 AssertRC(rc2);
11184 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
11185 }
11186
11187 /* If we've modified the exception bitmap, we restore it and trigger
11188 reloading and partial recalculation the next time around. */
11189 if (pDbgState->fModifiedXcptBitmap)
11190 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
11191
11192 return rcStrict;
11193}
11194
11195
11196/**
11197 * Configures VM-exit controls for current DBGF and DTrace settings.
11198 *
11199 * This updates @a pDbgState and the VMCS execution control fields to reflect
11200 * the necessary VM-exits demanded by DBGF and DTrace.
11201 *
11202 * @param pVCpu The cross context virtual CPU structure.
11203 * @param pVmxTransient The VMX-transient structure. May update
11204 * fUpdatedTscOffsettingAndPreemptTimer.
11205 * @param pDbgState The debug state.
11206 */
11207static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11208{
11209 /*
11210 * Take down the dtrace serial number so we can spot changes.
11211 */
11212 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
11213 ASMCompilerBarrier();
11214
11215 /*
11216 * We'll rebuild most of the middle block of data members (holding the
11217 * current settings) as we go along here, so start by clearing it all.
11218 */
11219 pDbgState->bmXcptExtra = 0;
11220 pDbgState->fCpe1Extra = 0;
11221 pDbgState->fCpe1Unwanted = 0;
11222 pDbgState->fCpe2Extra = 0;
11223 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
11224 pDbgState->bmExitsToCheck[i] = 0;
11225
11226 /*
11227 * Software interrupts (INT XXh) - no idea how to trigger these...
11228 */
11229 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11230 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
11231 || VBOXVMM_INT_SOFTWARE_ENABLED())
11232 {
11233 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11234 }
11235
11236 /*
11237 * INT3 breakpoints - triggered by #BP exceptions.
11238 */
11239 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
11240 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11241
11242 /*
11243 * Exception bitmap and XCPT events+probes.
11244 */
11245 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
11246 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
11247 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
11248
11249 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
11250 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
11251 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11252 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
11253 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
11254 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
11255 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
11256 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
11257 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
11258 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
11259 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
11260 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
11261 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
11262 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
11263 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
11264 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
11265 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
11266 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
11267
11268 if (pDbgState->bmXcptExtra)
11269 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11270
11271 /*
11272 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
11273 *
11274 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
11275 * So, when adding/changing/removing please don't forget to update it.
11276 *
11277 * Some of the macros are picking up local variables to save horizontal space,
11278 * (being able to see it in a table is the lesser evil here).
11279 */
11280#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
11281 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
11282 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
11283#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
11284 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11285 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11286 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11287 } else do { } while (0)
11288#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
11289 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11290 { \
11291 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
11292 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11293 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11294 } else do { } while (0)
11295#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
11296 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11297 { \
11298 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
11299 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11300 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11301 } else do { } while (0)
11302#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
11303 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11304 { \
11305 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
11306 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11307 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11308 } else do { } while (0)
11309
11310 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
11311 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
11312 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
11313 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
11314 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
11315
11316 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
11317 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
11318 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
11319 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
11320 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
11321 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
11322 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
11323 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
11324 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
11325 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
11326 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
11327 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
11328 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
11329 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
11330 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
11331 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
11332 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
11333 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
11334 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
11335 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
11336 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
11337 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
11338 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
11339 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
11340 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
11341 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
11342 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
11343 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
11344 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
11345 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
11346 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
11347 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
11348 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
11349 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
11350 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
11351 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
11352
11353 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
11354 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11355 {
11356 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
11357 | CPUMCTX_EXTRN_APIC_TPR);
11358 AssertRC(rc);
11359
11360#if 0 /** @todo fix me */
11361 pDbgState->fClearCr0Mask = true;
11362 pDbgState->fClearCr4Mask = true;
11363#endif
11364 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
11365 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
11366 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11367 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
11368 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
11369 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
11370 require clearing here and in the loop if we start using it. */
11371 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
11372 }
11373 else
11374 {
11375 if (pDbgState->fClearCr0Mask)
11376 {
11377 pDbgState->fClearCr0Mask = false;
11378 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
11379 }
11380 if (pDbgState->fClearCr4Mask)
11381 {
11382 pDbgState->fClearCr4Mask = false;
11383 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
11384 }
11385 }
11386 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
11387 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
11388
11389 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
11390 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
11391 {
11392 /** @todo later, need to fix handler as it assumes this won't usually happen. */
11393 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
11394 }
11395 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
11396 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
11397
11398 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
11399 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
11400 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
11401 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
11402 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
11403 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
11404 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
11405 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
11406#if 0 /** @todo too slow, fix handler. */
11407 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
11408#endif
11409 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
11410
11411 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
11412 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
11413 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
11414 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
11415 {
11416 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11417 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
11418 }
11419 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11420 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11421 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11422 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11423
11424 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
11425 || IS_EITHER_ENABLED(pVM, INSTR_STR)
11426 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
11427 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
11428 {
11429 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11430 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
11431 }
11432 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
11433 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
11434 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
11435 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
11436
11437 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
11438 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
11439 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
11440 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
11441 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
11442 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
11443 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
11444 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
11445 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
11446 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
11447 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
11448 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
11449 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
11450 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
11451 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
11452 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
11453 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
11454 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
11455 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
11456 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
11457 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
11458 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
11459
11460#undef IS_EITHER_ENABLED
11461#undef SET_ONLY_XBM_IF_EITHER_EN
11462#undef SET_CPE1_XBM_IF_EITHER_EN
11463#undef SET_CPEU_XBM_IF_EITHER_EN
11464#undef SET_CPE2_XBM_IF_EITHER_EN
11465
11466 /*
11467 * Sanitize the control stuff.
11468 */
11469 pDbgState->fCpe2Extra &= pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1;
11470 if (pDbgState->fCpe2Extra)
11471 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
11472 pDbgState->fCpe1Extra &= pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1;
11473 pDbgState->fCpe1Unwanted &= ~pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0;
11474 if (pVCpu->hm.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
11475 {
11476 pVCpu->hm.s.fDebugWantRdTscExit ^= true;
11477 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
11478 }
11479
11480 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
11481 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
11482 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
11483 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
11484}
11485
11486
11487/**
11488 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
11489 * appropriate.
11490 *
11491 * The caller has checked the VM-exit against the
11492 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
11493 * already, so we don't have to do that either.
11494 *
11495 * @returns Strict VBox status code (i.e. informational status codes too).
11496 * @param pVCpu The cross context virtual CPU structure.
11497 * @param pVmxTransient The VMX-transient structure.
11498 * @param uExitReason The VM-exit reason.
11499 *
11500 * @remarks The name of this function is displayed by dtrace, so keep it short
11501 * and to the point. No longer than 33 chars long, please.
11502 */
11503static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
11504{
11505 /*
11506 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
11507 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
11508 *
11509 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
11510 * does. Must add/change/remove both places. Same ordering, please.
11511 *
11512 * Added/removed events must also be reflected in the next section
11513 * where we dispatch dtrace events.
11514 */
11515 bool fDtrace1 = false;
11516 bool fDtrace2 = false;
11517 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
11518 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
11519 uint32_t uEventArg = 0;
11520#define SET_EXIT(a_EventSubName) \
11521 do { \
11522 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11523 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11524 } while (0)
11525#define SET_BOTH(a_EventSubName) \
11526 do { \
11527 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
11528 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11529 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
11530 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11531 } while (0)
11532 switch (uExitReason)
11533 {
11534 case VMX_EXIT_MTF:
11535 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
11536
11537 case VMX_EXIT_XCPT_OR_NMI:
11538 {
11539 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
11540 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
11541 {
11542 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
11543 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
11544 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
11545 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
11546 {
11547 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
11548 {
11549 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
11550 uEventArg = pVmxTransient->uExitIntErrorCode;
11551 }
11552 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
11553 switch (enmEvent1)
11554 {
11555 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
11556 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
11557 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
11558 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
11559 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
11560 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
11561 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
11562 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
11563 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
11564 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
11565 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
11566 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
11567 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
11568 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
11569 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
11570 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
11571 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
11572 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
11573 default: break;
11574 }
11575 }
11576 else
11577 AssertFailed();
11578 break;
11579
11580 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
11581 uEventArg = idxVector;
11582 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
11583 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
11584 break;
11585 }
11586 break;
11587 }
11588
11589 case VMX_EXIT_TRIPLE_FAULT:
11590 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
11591 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
11592 break;
11593 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
11594 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
11595 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
11596 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
11597 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
11598
11599 /* Instruction specific VM-exits: */
11600 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
11601 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
11602 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
11603 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
11604 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
11605 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
11606 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
11607 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
11608 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
11609 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
11610 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
11611 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
11612 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
11613 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
11614 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
11615 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
11616 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
11617 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
11618 case VMX_EXIT_MOV_CRX:
11619 hmR0VmxReadExitQualVmcs(pVmxTransient);
11620 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
11621 SET_BOTH(CRX_READ);
11622 else
11623 SET_BOTH(CRX_WRITE);
11624 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
11625 break;
11626 case VMX_EXIT_MOV_DRX:
11627 hmR0VmxReadExitQualVmcs(pVmxTransient);
11628 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
11629 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
11630 SET_BOTH(DRX_READ);
11631 else
11632 SET_BOTH(DRX_WRITE);
11633 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
11634 break;
11635 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
11636 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
11637 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
11638 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
11639 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
11640 case VMX_EXIT_GDTR_IDTR_ACCESS:
11641 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
11642 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
11643 {
11644 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
11645 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
11646 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
11647 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
11648 }
11649 break;
11650
11651 case VMX_EXIT_LDTR_TR_ACCESS:
11652 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
11653 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
11654 {
11655 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
11656 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
11657 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
11658 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
11659 }
11660 break;
11661
11662 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
11663 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
11664 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
11665 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
11666 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
11667 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
11668 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
11669 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
11670 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
11671 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
11672 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
11673
11674 /* Events that aren't relevant at this point. */
11675 case VMX_EXIT_EXT_INT:
11676 case VMX_EXIT_INT_WINDOW:
11677 case VMX_EXIT_NMI_WINDOW:
11678 case VMX_EXIT_TPR_BELOW_THRESHOLD:
11679 case VMX_EXIT_PREEMPT_TIMER:
11680 case VMX_EXIT_IO_INSTR:
11681 break;
11682
11683 /* Errors and unexpected events. */
11684 case VMX_EXIT_INIT_SIGNAL:
11685 case VMX_EXIT_SIPI:
11686 case VMX_EXIT_IO_SMI:
11687 case VMX_EXIT_SMI:
11688 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
11689 case VMX_EXIT_ERR_MSR_LOAD:
11690 case VMX_EXIT_ERR_MACHINE_CHECK:
11691 case VMX_EXIT_PML_FULL:
11692 case VMX_EXIT_VIRTUALIZED_EOI:
11693 break;
11694
11695 default:
11696 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
11697 break;
11698 }
11699#undef SET_BOTH
11700#undef SET_EXIT
11701
11702 /*
11703 * Dtrace tracepoints go first. We do them here at once so we don't
11704 * have to copy the guest state saving and stuff a few dozen times.
11705 * Down side is that we've got to repeat the switch, though this time
11706 * we use enmEvent since the probes are a subset of what DBGF does.
11707 */
11708 if (fDtrace1 || fDtrace2)
11709 {
11710 hmR0VmxReadExitQualVmcs(pVmxTransient);
11711 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11712 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
11713 switch (enmEvent1)
11714 {
11715 /** @todo consider which extra parameters would be helpful for each probe. */
11716 case DBGFEVENT_END: break;
11717 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
11718 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
11719 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
11720 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
11721 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
11722 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
11723 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
11724 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
11725 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
11726 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
11727 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
11728 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
11729 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
11730 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
11731 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
11732 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
11733 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
11734 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
11735 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11736 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
11737 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
11738 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
11739 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
11740 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
11741 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
11742 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
11743 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
11744 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11745 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11746 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11747 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11748 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
11749 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
11750 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
11751 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
11752 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
11753 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
11754 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
11755 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
11756 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
11757 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
11758 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
11759 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
11760 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
11761 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
11762 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
11763 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
11764 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
11765 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
11766 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
11767 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
11768 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
11769 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
11770 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
11771 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
11772 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
11773 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
11774 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
11775 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
11776 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
11777 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
11778 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
11779 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
11780 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
11781 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
11782 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
11783 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
11784 }
11785 switch (enmEvent2)
11786 {
11787 /** @todo consider which extra parameters would be helpful for each probe. */
11788 case DBGFEVENT_END: break;
11789 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
11790 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
11791 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
11792 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
11793 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
11794 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
11795 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
11796 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
11797 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
11798 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11799 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11800 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11801 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11802 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
11803 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
11804 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
11805 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
11806 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
11807 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
11808 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
11809 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
11810 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
11811 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
11812 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
11813 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
11814 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
11815 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
11816 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
11817 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
11818 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
11819 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
11820 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
11821 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
11822 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
11823 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
11824 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
11825 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
11826 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
11827 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
11828 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
11829 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
11830 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
11831 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
11832 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
11833 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
11834 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
11835 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
11836 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
11837 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
11838 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
11839 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
11840 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
11841 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
11842 }
11843 }
11844
11845 /*
11846 * Fire of the DBGF event, if enabled (our check here is just a quick one,
11847 * the DBGF call will do a full check).
11848 *
11849 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
11850 * Note! If we have to events, we prioritize the first, i.e. the instruction
11851 * one, in order to avoid event nesting.
11852 */
11853 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11854 if ( enmEvent1 != DBGFEVENT_END
11855 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
11856 {
11857 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
11858 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
11859 if (rcStrict != VINF_SUCCESS)
11860 return rcStrict;
11861 }
11862 else if ( enmEvent2 != DBGFEVENT_END
11863 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
11864 {
11865 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
11866 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
11867 if (rcStrict != VINF_SUCCESS)
11868 return rcStrict;
11869 }
11870
11871 return VINF_SUCCESS;
11872}
11873
11874
11875/**
11876 * Single-stepping VM-exit filtering.
11877 *
11878 * This is preprocessing the VM-exits and deciding whether we've gotten far
11879 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
11880 * handling is performed.
11881 *
11882 * @returns Strict VBox status code (i.e. informational status codes too).
11883 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
11884 * @param pVmxTransient The VMX-transient structure.
11885 * @param pDbgState The debug state.
11886 */
11887DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11888{
11889 /*
11890 * Expensive (saves context) generic dtrace VM-exit probe.
11891 */
11892 uint32_t const uExitReason = pVmxTransient->uExitReason;
11893 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
11894 { /* more likely */ }
11895 else
11896 {
11897 hmR0VmxReadExitQualVmcs(pVmxTransient);
11898 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11899 AssertRC(rc);
11900 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
11901 }
11902
11903 /*
11904 * Check for host NMI, just to get that out of the way.
11905 */
11906 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
11907 { /* normally likely */ }
11908 else
11909 {
11910 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
11911 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
11912 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
11913 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
11914 }
11915
11916 /*
11917 * Check for single stepping event if we're stepping.
11918 */
11919 if (pVCpu->hm.s.fSingleInstruction)
11920 {
11921 switch (uExitReason)
11922 {
11923 case VMX_EXIT_MTF:
11924 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
11925
11926 /* Various events: */
11927 case VMX_EXIT_XCPT_OR_NMI:
11928 case VMX_EXIT_EXT_INT:
11929 case VMX_EXIT_TRIPLE_FAULT:
11930 case VMX_EXIT_INT_WINDOW:
11931 case VMX_EXIT_NMI_WINDOW:
11932 case VMX_EXIT_TASK_SWITCH:
11933 case VMX_EXIT_TPR_BELOW_THRESHOLD:
11934 case VMX_EXIT_APIC_ACCESS:
11935 case VMX_EXIT_EPT_VIOLATION:
11936 case VMX_EXIT_EPT_MISCONFIG:
11937 case VMX_EXIT_PREEMPT_TIMER:
11938
11939 /* Instruction specific VM-exits: */
11940 case VMX_EXIT_CPUID:
11941 case VMX_EXIT_GETSEC:
11942 case VMX_EXIT_HLT:
11943 case VMX_EXIT_INVD:
11944 case VMX_EXIT_INVLPG:
11945 case VMX_EXIT_RDPMC:
11946 case VMX_EXIT_RDTSC:
11947 case VMX_EXIT_RSM:
11948 case VMX_EXIT_VMCALL:
11949 case VMX_EXIT_VMCLEAR:
11950 case VMX_EXIT_VMLAUNCH:
11951 case VMX_EXIT_VMPTRLD:
11952 case VMX_EXIT_VMPTRST:
11953 case VMX_EXIT_VMREAD:
11954 case VMX_EXIT_VMRESUME:
11955 case VMX_EXIT_VMWRITE:
11956 case VMX_EXIT_VMXOFF:
11957 case VMX_EXIT_VMXON:
11958 case VMX_EXIT_MOV_CRX:
11959 case VMX_EXIT_MOV_DRX:
11960 case VMX_EXIT_IO_INSTR:
11961 case VMX_EXIT_RDMSR:
11962 case VMX_EXIT_WRMSR:
11963 case VMX_EXIT_MWAIT:
11964 case VMX_EXIT_MONITOR:
11965 case VMX_EXIT_PAUSE:
11966 case VMX_EXIT_GDTR_IDTR_ACCESS:
11967 case VMX_EXIT_LDTR_TR_ACCESS:
11968 case VMX_EXIT_INVEPT:
11969 case VMX_EXIT_RDTSCP:
11970 case VMX_EXIT_INVVPID:
11971 case VMX_EXIT_WBINVD:
11972 case VMX_EXIT_XSETBV:
11973 case VMX_EXIT_RDRAND:
11974 case VMX_EXIT_INVPCID:
11975 case VMX_EXIT_VMFUNC:
11976 case VMX_EXIT_RDSEED:
11977 case VMX_EXIT_XSAVES:
11978 case VMX_EXIT_XRSTORS:
11979 {
11980 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
11981 AssertRCReturn(rc, rc);
11982 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
11983 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
11984 return VINF_EM_DBG_STEPPED;
11985 break;
11986 }
11987
11988 /* Errors and unexpected events: */
11989 case VMX_EXIT_INIT_SIGNAL:
11990 case VMX_EXIT_SIPI:
11991 case VMX_EXIT_IO_SMI:
11992 case VMX_EXIT_SMI:
11993 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
11994 case VMX_EXIT_ERR_MSR_LOAD:
11995 case VMX_EXIT_ERR_MACHINE_CHECK:
11996 case VMX_EXIT_PML_FULL:
11997 case VMX_EXIT_VIRTUALIZED_EOI:
11998 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
11999 break;
12000
12001 default:
12002 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12003 break;
12004 }
12005 }
12006
12007 /*
12008 * Check for debugger event breakpoints and dtrace probes.
12009 */
12010 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12011 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12012 {
12013 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12014 if (rcStrict != VINF_SUCCESS)
12015 return rcStrict;
12016 }
12017
12018 /*
12019 * Normal processing.
12020 */
12021#ifdef HMVMX_USE_FUNCTION_TABLE
12022 return g_apfnVMExitHandlers[uExitReason](pVCpu, pVmxTransient);
12023#else
12024 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12025#endif
12026}
12027
12028
12029/**
12030 * Single steps guest code using hardware-assisted VMX.
12031 *
12032 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12033 * but single-stepping through the hypervisor debugger.
12034 *
12035 * @returns Strict VBox status code (i.e. informational status codes too).
12036 * @param pVCpu The cross context virtual CPU structure.
12037 * @param pcLoops Pointer to the number of executed loops.
12038 *
12039 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12040 */
12041static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPUCC pVCpu, uint32_t *pcLoops)
12042{
12043 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
12044 Assert(pcLoops);
12045 Assert(*pcLoops <= cMaxResumeLoops);
12046
12047 VMXTRANSIENT VmxTransient;
12048 RT_ZERO(VmxTransient);
12049 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12050
12051 /* Set HMCPU indicators. */
12052 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12053 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12054 pVCpu->hm.s.fDebugWantRdTscExit = false;
12055 pVCpu->hm.s.fUsingDebugLoop = true;
12056
12057 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12058 VMXRUNDBGSTATE DbgState;
12059 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12060 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12061
12062 /*
12063 * The loop.
12064 */
12065 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12066 for (;;)
12067 {
12068 Assert(!HMR0SuspendPending());
12069 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12070 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12071 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12072
12073 /* Set up VM-execution controls the next two can respond to. */
12074 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12075
12076 /*
12077 * Preparatory work for running guest code, this may force us to
12078 * return to ring-3.
12079 *
12080 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12081 */
12082 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12083 if (rcStrict != VINF_SUCCESS)
12084 break;
12085
12086 /* Interrupts are disabled at this point! */
12087 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12088
12089 /* Override any obnoxious code in the above two calls. */
12090 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12091
12092 /*
12093 * Finally execute the guest.
12094 */
12095 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12096
12097 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12098 /* Interrupts are re-enabled at this point! */
12099
12100 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12101 if (RT_SUCCESS(rcRun))
12102 { /* very likely */ }
12103 else
12104 {
12105 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12106 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12107 return rcRun;
12108 }
12109
12110 /* Profile the VM-exit. */
12111 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12112 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12113 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12114 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12115 HMVMX_START_EXIT_DISPATCH_PROF();
12116
12117 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12118
12119 /*
12120 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12121 */
12122 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12123 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12124 if (rcStrict != VINF_SUCCESS)
12125 break;
12126 if (++(*pcLoops) > cMaxResumeLoops)
12127 {
12128 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12129 rcStrict = VINF_EM_RAW_INTERRUPT;
12130 break;
12131 }
12132
12133 /*
12134 * Stepping: Did the RIP change, if so, consider it a single step.
12135 * Otherwise, make sure one of the TFs gets set.
12136 */
12137 if (fStepping)
12138 {
12139 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12140 AssertRC(rc);
12141 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12142 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12143 {
12144 rcStrict = VINF_EM_DBG_STEPPED;
12145 break;
12146 }
12147 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12148 }
12149
12150 /*
12151 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12152 */
12153 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12154 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12155 }
12156
12157 /*
12158 * Clear the X86_EFL_TF if necessary.
12159 */
12160 if (pVCpu->hm.s.fClearTrapFlag)
12161 {
12162 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12163 AssertRC(rc);
12164 pVCpu->hm.s.fClearTrapFlag = false;
12165 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12166 }
12167 /** @todo there seems to be issues with the resume flag when the monitor trap
12168 * flag is pending without being used. Seen early in bios init when
12169 * accessing APIC page in protected mode. */
12170
12171 /*
12172 * Restore VM-exit control settings as we may not re-enter this function the
12173 * next time around.
12174 */
12175 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
12176
12177 /* Restore HMCPU indicators. */
12178 pVCpu->hm.s.fUsingDebugLoop = false;
12179 pVCpu->hm.s.fDebugWantRdTscExit = false;
12180 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
12181
12182 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
12183 return rcStrict;
12184}
12185
12186
12187/** @} */
12188
12189
12190/**
12191 * Checks if any expensive dtrace probes are enabled and we should go to the
12192 * debug loop.
12193 *
12194 * @returns true if we should use debug loop, false if not.
12195 */
12196static bool hmR0VmxAnyExpensiveProbesEnabled(void)
12197{
12198 /* It's probably faster to OR the raw 32-bit counter variables together.
12199 Since the variables are in an array and the probes are next to one
12200 another (more or less), we have good locality. So, better read
12201 eight-nine cache lines ever time and only have one conditional, than
12202 128+ conditionals, right? */
12203 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
12204 | VBOXVMM_XCPT_DE_ENABLED_RAW()
12205 | VBOXVMM_XCPT_DB_ENABLED_RAW()
12206 | VBOXVMM_XCPT_BP_ENABLED_RAW()
12207 | VBOXVMM_XCPT_OF_ENABLED_RAW()
12208 | VBOXVMM_XCPT_BR_ENABLED_RAW()
12209 | VBOXVMM_XCPT_UD_ENABLED_RAW()
12210 | VBOXVMM_XCPT_NM_ENABLED_RAW()
12211 | VBOXVMM_XCPT_DF_ENABLED_RAW()
12212 | VBOXVMM_XCPT_TS_ENABLED_RAW()
12213 | VBOXVMM_XCPT_NP_ENABLED_RAW()
12214 | VBOXVMM_XCPT_SS_ENABLED_RAW()
12215 | VBOXVMM_XCPT_GP_ENABLED_RAW()
12216 | VBOXVMM_XCPT_PF_ENABLED_RAW()
12217 | VBOXVMM_XCPT_MF_ENABLED_RAW()
12218 | VBOXVMM_XCPT_AC_ENABLED_RAW()
12219 | VBOXVMM_XCPT_XF_ENABLED_RAW()
12220 | VBOXVMM_XCPT_VE_ENABLED_RAW()
12221 | VBOXVMM_XCPT_SX_ENABLED_RAW()
12222 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
12223 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
12224 ) != 0
12225 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
12226 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
12227 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
12228 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
12229 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
12230 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
12231 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
12232 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
12233 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
12234 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
12235 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
12236 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
12237 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
12238 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
12239 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
12240 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
12241 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
12242 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
12243 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
12244 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
12245 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
12246 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
12247 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
12248 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
12249 | VBOXVMM_INSTR_STR_ENABLED_RAW()
12250 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
12251 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
12252 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
12253 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
12254 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
12255 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
12256 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
12257 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
12258 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
12259 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
12260 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
12261 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
12262 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
12263 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
12264 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
12265 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
12266 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
12267 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
12268 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
12269 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
12270 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
12271 ) != 0
12272 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
12273 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
12274 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
12275 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
12276 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
12277 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
12278 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
12279 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
12280 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
12281 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
12282 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
12283 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
12284 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
12285 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
12286 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
12287 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
12288 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
12289 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
12290 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
12291 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
12292 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
12293 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
12294 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
12295 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
12296 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
12297 | VBOXVMM_EXIT_STR_ENABLED_RAW()
12298 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
12299 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
12300 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
12301 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
12302 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
12303 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
12304 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
12305 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
12306 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
12307 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
12308 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
12309 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
12310 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
12311 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
12312 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
12313 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
12314 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
12315 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
12316 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
12317 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
12318 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
12319 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
12320 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
12321 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
12322 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
12323 ) != 0;
12324}
12325
12326
12327/**
12328 * Runs the guest using hardware-assisted VMX.
12329 *
12330 * @returns Strict VBox status code (i.e. informational status codes too).
12331 * @param pVCpu The cross context virtual CPU structure.
12332 */
12333VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPUCC pVCpu)
12334{
12335 AssertPtr(pVCpu);
12336 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12337 Assert(VMMRZCallRing3IsEnabled(pVCpu));
12338 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12339 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
12340
12341 VMMRZCallRing3SetNotification(pVCpu, hmR0VmxCallRing3Callback, pCtx);
12342
12343 VBOXSTRICTRC rcStrict;
12344 uint32_t cLoops = 0;
12345 for (;;)
12346 {
12347#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12348 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
12349#else
12350 bool const fInNestedGuestMode = false;
12351#endif
12352 if (!fInNestedGuestMode)
12353 {
12354 if ( !pVCpu->hm.s.fUseDebugLoop
12355 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
12356 && !DBGFIsStepping(pVCpu)
12357 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
12358 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
12359 else
12360 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
12361 }
12362#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12363 else
12364 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
12365
12366 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
12367 {
12368 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
12369 continue;
12370 }
12371 if (rcStrict == VINF_VMX_VMEXIT)
12372 {
12373 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
12374 continue;
12375 }
12376#endif
12377 break;
12378 }
12379
12380 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
12381 switch (rcLoop)
12382 {
12383 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
12384 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
12385 }
12386
12387 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
12388 if (RT_FAILURE(rc2))
12389 {
12390 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
12391 rcStrict = rc2;
12392 }
12393 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12394 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
12395 return rcStrict;
12396}
12397
12398
12399#ifndef HMVMX_USE_FUNCTION_TABLE
12400/**
12401 * Handles a guest VM-exit from hardware-assisted VMX execution.
12402 *
12403 * @returns Strict VBox status code (i.e. informational status codes too).
12404 * @param pVCpu The cross context virtual CPU structure.
12405 * @param pVmxTransient The VMX-transient structure.
12406 */
12407DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12408{
12409#ifdef DEBUG_ramshankar
12410#define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
12411 do { \
12412 if (a_fSave != 0) \
12413 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
12414 VBOXSTRICTRC rcStrict = a_CallExpr; \
12415 if (a_fSave != 0) \
12416 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
12417 return rcStrict; \
12418 } while (0)
12419#else
12420# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
12421#endif
12422 uint32_t const uExitReason = pVmxTransient->uExitReason;
12423 switch (uExitReason)
12424 {
12425 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
12426 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
12427 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
12428 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
12429 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
12430 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
12431 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
12432 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
12433 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
12434 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
12435 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
12436 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
12437 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
12438 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
12439 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
12440 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
12441 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
12442 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
12443 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
12444 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
12445 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
12446 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
12447 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
12448 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
12449 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
12450 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
12451 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
12452 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
12453 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
12454 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
12455#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12456 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
12457 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
12458 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
12459 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
12460 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
12461 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
12462 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
12463 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
12464 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
12465 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
12466 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
12467#else
12468 case VMX_EXIT_VMCLEAR:
12469 case VMX_EXIT_VMLAUNCH:
12470 case VMX_EXIT_VMPTRLD:
12471 case VMX_EXIT_VMPTRST:
12472 case VMX_EXIT_VMREAD:
12473 case VMX_EXIT_VMRESUME:
12474 case VMX_EXIT_VMWRITE:
12475 case VMX_EXIT_VMXOFF:
12476 case VMX_EXIT_VMXON:
12477 case VMX_EXIT_INVVPID:
12478 case VMX_EXIT_INVEPT:
12479 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
12480#endif
12481
12482 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
12483 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
12484 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
12485
12486 case VMX_EXIT_INIT_SIGNAL:
12487 case VMX_EXIT_SIPI:
12488 case VMX_EXIT_IO_SMI:
12489 case VMX_EXIT_SMI:
12490 case VMX_EXIT_ERR_MSR_LOAD:
12491 case VMX_EXIT_ERR_MACHINE_CHECK:
12492 case VMX_EXIT_PML_FULL:
12493 case VMX_EXIT_VIRTUALIZED_EOI:
12494 case VMX_EXIT_GDTR_IDTR_ACCESS:
12495 case VMX_EXIT_LDTR_TR_ACCESS:
12496 case VMX_EXIT_APIC_WRITE:
12497 case VMX_EXIT_RDRAND:
12498 case VMX_EXIT_RSM:
12499 case VMX_EXIT_VMFUNC:
12500 case VMX_EXIT_ENCLS:
12501 case VMX_EXIT_RDSEED:
12502 case VMX_EXIT_XSAVES:
12503 case VMX_EXIT_XRSTORS:
12504 case VMX_EXIT_UMWAIT:
12505 case VMX_EXIT_TPAUSE:
12506 default:
12507 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
12508 }
12509#undef VMEXIT_CALL_RET
12510}
12511#endif /* !HMVMX_USE_FUNCTION_TABLE */
12512
12513
12514#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12515/**
12516 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
12517 *
12518 * @returns Strict VBox status code (i.e. informational status codes too).
12519 * @param pVCpu The cross context virtual CPU structure.
12520 * @param pVmxTransient The VMX-transient structure.
12521 */
12522DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12523{
12524 /** @todo NSTVMX: Remove after debugging regression. */
12525#if 1 //def DEBUG_ramshankar Remove later
12526 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP);
12527 Log4Func(("cs:rip=%#04x:%#RX64 rsp=%#RX64\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.rsp));
12528#endif
12529
12530 uint32_t const uExitReason = pVmxTransient->uExitReason;
12531 switch (uExitReason)
12532 {
12533 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
12534 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
12535 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
12536 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
12537 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
12538
12539 /*
12540 * We shouldn't direct host physical interrupts to the nested-guest.
12541 */
12542 case VMX_EXIT_EXT_INT:
12543 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
12544
12545 /*
12546 * Instructions that cause VM-exits unconditionally or the condition is
12547 * always is taken solely from the guest hypervisor (meaning if the VM-exit
12548 * happens, it's guaranteed to be a nested-guest VM-exit).
12549 *
12550 * - Provides VM-exit instruction length ONLY.
12551 */
12552 case VMX_EXIT_CPUID: /* Unconditional. */
12553 case VMX_EXIT_VMCALL:
12554 case VMX_EXIT_GETSEC:
12555 case VMX_EXIT_INVD:
12556 case VMX_EXIT_XSETBV:
12557 case VMX_EXIT_VMLAUNCH:
12558 case VMX_EXIT_VMRESUME:
12559 case VMX_EXIT_VMXOFF:
12560 case VMX_EXIT_ENCLS: /* Condition specified solely by guest hypervisor. */
12561 case VMX_EXIT_VMFUNC:
12562 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
12563
12564 /*
12565 * Instructions that cause VM-exits unconditionally or the condition is
12566 * always is taken solely from the guest hypervisor (meaning if the VM-exit
12567 * happens, it's guaranteed to be a nested-guest VM-exit).
12568 *
12569 * - Provides VM-exit instruction length.
12570 * - Provides VM-exit information.
12571 * - Optionally provides Exit qualification.
12572 *
12573 * Since Exit qualification is 0 for all VM-exits where it is not
12574 * applicable, reading and passing it to the guest should produce
12575 * defined behavior.
12576 *
12577 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
12578 */
12579 case VMX_EXIT_INVEPT: /* Unconditional. */
12580 case VMX_EXIT_INVVPID:
12581 case VMX_EXIT_VMCLEAR:
12582 case VMX_EXIT_VMPTRLD:
12583 case VMX_EXIT_VMPTRST:
12584 case VMX_EXIT_VMXON:
12585 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by guest hypervisor. */
12586 case VMX_EXIT_LDTR_TR_ACCESS:
12587 case VMX_EXIT_RDRAND:
12588 case VMX_EXIT_RDSEED:
12589 case VMX_EXIT_XSAVES:
12590 case VMX_EXIT_XRSTORS:
12591 case VMX_EXIT_UMWAIT:
12592 case VMX_EXIT_TPAUSE:
12593 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
12594
12595 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
12596 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
12597 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
12598 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
12599 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
12600 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
12601 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
12602 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
12603 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
12604 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
12605 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
12606 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
12607 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
12608 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
12609 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
12610 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
12611 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
12612 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
12613 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
12614
12615 case VMX_EXIT_PREEMPT_TIMER:
12616 {
12617 /** @todo NSTVMX: Preempt timer. */
12618 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
12619 }
12620
12621 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
12622 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
12623
12624 case VMX_EXIT_VMREAD:
12625 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
12626
12627 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
12628 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
12629
12630 case VMX_EXIT_INIT_SIGNAL:
12631 case VMX_EXIT_SIPI:
12632 case VMX_EXIT_IO_SMI:
12633 case VMX_EXIT_SMI:
12634 case VMX_EXIT_ERR_MSR_LOAD:
12635 case VMX_EXIT_ERR_MACHINE_CHECK:
12636 case VMX_EXIT_PML_FULL:
12637 case VMX_EXIT_RSM:
12638 default:
12639 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
12640 }
12641}
12642#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
12643
12644
12645/** @name VM-exit helpers.
12646 * @{
12647 */
12648/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
12649/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
12650/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
12651
12652/** Macro for VM-exits called unexpectedly. */
12653#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
12654 do { \
12655 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
12656 return VERR_VMX_UNEXPECTED_EXIT; \
12657 } while (0)
12658
12659#ifdef VBOX_STRICT
12660/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
12661# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
12662 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
12663
12664# define HMVMX_ASSERT_PREEMPT_CPUID() \
12665 do { \
12666 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
12667 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
12668 } while (0)
12669
12670# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12671 do { \
12672 AssertPtr((a_pVCpu)); \
12673 AssertPtr((a_pVmxTransient)); \
12674 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
12675 Assert((a_pVmxTransient)->pVmcsInfo); \
12676 Assert(ASMIntAreEnabled()); \
12677 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
12678 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
12679 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
12680 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
12681 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
12682 HMVMX_ASSERT_PREEMPT_CPUID(); \
12683 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
12684 } while (0)
12685
12686# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12687 do { \
12688 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
12689 Assert((a_pVmxTransient)->fIsNestedGuest); \
12690 } while (0)
12691
12692# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12693 do { \
12694 Log4Func(("\n")); \
12695 } while (0)
12696#else
12697# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12698 do { \
12699 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
12700 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
12701 } while (0)
12702
12703# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12704 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
12705
12706# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
12707#endif
12708
12709#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12710/** Macro that does the necessary privilege checks and intercepted VM-exits for
12711 * guests that attempted to execute a VMX instruction. */
12712# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
12713 do \
12714 { \
12715 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
12716 if (rcStrictTmp == VINF_SUCCESS) \
12717 { /* likely */ } \
12718 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
12719 { \
12720 Assert((a_pVCpu)->hm.s.Event.fPending); \
12721 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
12722 return VINF_SUCCESS; \
12723 } \
12724 else \
12725 { \
12726 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
12727 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
12728 } \
12729 } while (0)
12730
12731/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
12732# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
12733 do \
12734 { \
12735 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
12736 (a_pGCPtrEffAddr)); \
12737 if (rcStrictTmp == VINF_SUCCESS) \
12738 { /* likely */ } \
12739 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
12740 { \
12741 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
12742 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
12743 NOREF(uXcptTmp); \
12744 return VINF_SUCCESS; \
12745 } \
12746 else \
12747 { \
12748 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
12749 return rcStrictTmp; \
12750 } \
12751 } while (0)
12752#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
12753
12754
12755/**
12756 * Advances the guest RIP by the specified number of bytes.
12757 *
12758 * @param pVCpu The cross context virtual CPU structure.
12759 * @param cbInstr Number of bytes to advance the RIP by.
12760 *
12761 * @remarks No-long-jump zone!!!
12762 */
12763DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPUCC pVCpu, uint32_t cbInstr)
12764{
12765 /* Advance the RIP. */
12766 pVCpu->cpum.GstCtx.rip += cbInstr;
12767 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
12768
12769 /* Update interrupt inhibition. */
12770 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
12771 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
12772 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
12773}
12774
12775
12776/**
12777 * Advances the guest RIP after reading it from the VMCS.
12778 *
12779 * @returns VBox status code, no informational status codes.
12780 * @param pVCpu The cross context virtual CPU structure.
12781 * @param pVmxTransient The VMX-transient structure.
12782 *
12783 * @remarks No-long-jump zone!!!
12784 */
12785static int hmR0VmxAdvanceGuestRip(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12786{
12787 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
12788 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
12789 AssertRCReturn(rc, rc);
12790
12791 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbInstr);
12792 return VINF_SUCCESS;
12793}
12794
12795
12796/**
12797 * Handle a condition that occurred while delivering an event through the guest or
12798 * nested-guest IDT.
12799 *
12800 * @returns Strict VBox status code (i.e. informational status codes too).
12801 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
12802 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
12803 * to continue execution of the guest which will delivery the \#DF.
12804 * @retval VINF_EM_RESET if we detected a triple-fault condition.
12805 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
12806 *
12807 * @param pVCpu The cross context virtual CPU structure.
12808 * @param pVmxTransient The VMX-transient structure.
12809 *
12810 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
12811 * Additionally, HMVMX_READ_EXIT_QUALIFICATION is required if the VM-exit
12812 * is due to an EPT violation, PML full or SPP-related event.
12813 *
12814 * @remarks No-long-jump zone!!!
12815 */
12816static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12817{
12818 Assert(!pVCpu->hm.s.Event.fPending);
12819 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
12820 if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
12821 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
12822 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
12823 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_EXIT_QUALIFICATION);
12824
12825 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
12826 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
12827 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
12828 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
12829 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
12830 {
12831 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
12832 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
12833
12834 /*
12835 * If the event was a software interrupt (generated with INT n) or a software exception
12836 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
12837 * can handle the VM-exit and continue guest execution which will re-execute the
12838 * instruction rather than re-injecting the exception, as that can cause premature
12839 * trips to ring-3 before injection and involve TRPM which currently has no way of
12840 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
12841 * the problem).
12842 */
12843 IEMXCPTRAISE enmRaise;
12844 IEMXCPTRAISEINFO fRaiseInfo;
12845 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
12846 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
12847 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
12848 {
12849 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
12850 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
12851 }
12852 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
12853 {
12854 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
12855 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
12856 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
12857
12858 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
12859 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
12860
12861 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
12862
12863 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
12864 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
12865 {
12866 pVmxTransient->fVectoringPF = true;
12867 enmRaise = IEMXCPTRAISE_PREV_EVENT;
12868 }
12869 }
12870 else
12871 {
12872 /*
12873 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
12874 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
12875 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
12876 */
12877 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
12878 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
12879 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
12880 enmRaise = IEMXCPTRAISE_PREV_EVENT;
12881 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
12882 }
12883
12884 /*
12885 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
12886 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
12887 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
12888 * subsequent VM-entry would fail, see @bugref{7445}.
12889 *
12890 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
12891 */
12892 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
12893 && enmRaise == IEMXCPTRAISE_PREV_EVENT
12894 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
12895 && CPUMIsGuestNmiBlocking(pVCpu))
12896 {
12897 CPUMSetGuestNmiBlocking(pVCpu, false);
12898 }
12899
12900 switch (enmRaise)
12901 {
12902 case IEMXCPTRAISE_CURRENT_XCPT:
12903 {
12904 Log4Func(("IDT: Pending secondary Xcpt: idtinfo=%#RX64 exitinfo=%#RX64\n", uIdtVectorInfo, uExitIntInfo));
12905 Assert(rcStrict == VINF_SUCCESS);
12906 break;
12907 }
12908
12909 case IEMXCPTRAISE_PREV_EVENT:
12910 {
12911 uint32_t u32ErrCode;
12912 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
12913 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
12914 else
12915 u32ErrCode = 0;
12916
12917 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
12918 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
12919 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
12920 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
12921
12922 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
12923 pVCpu->hm.s.Event.u32ErrCode));
12924 Assert(rcStrict == VINF_SUCCESS);
12925 break;
12926 }
12927
12928 case IEMXCPTRAISE_REEXEC_INSTR:
12929 Assert(rcStrict == VINF_SUCCESS);
12930 break;
12931
12932 case IEMXCPTRAISE_DOUBLE_FAULT:
12933 {
12934 /*
12935 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
12936 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
12937 */
12938 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
12939 {
12940 pVmxTransient->fVectoringDoublePF = true;
12941 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
12942 pVCpu->cpum.GstCtx.cr2));
12943 rcStrict = VINF_SUCCESS;
12944 }
12945 else
12946 {
12947 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
12948 hmR0VmxSetPendingXcptDF(pVCpu);
12949 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
12950 uIdtVector, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
12951 rcStrict = VINF_HM_DOUBLE_FAULT;
12952 }
12953 break;
12954 }
12955
12956 case IEMXCPTRAISE_TRIPLE_FAULT:
12957 {
12958 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector,
12959 VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
12960 rcStrict = VINF_EM_RESET;
12961 break;
12962 }
12963
12964 case IEMXCPTRAISE_CPU_HANG:
12965 {
12966 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
12967 rcStrict = VERR_EM_GUEST_CPU_HANG;
12968 break;
12969 }
12970
12971 default:
12972 {
12973 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
12974 rcStrict = VERR_VMX_IPE_2;
12975 break;
12976 }
12977 }
12978 }
12979 else if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
12980 && !CPUMIsGuestNmiBlocking(pVCpu))
12981 {
12982 if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
12983 && VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo) != X86_XCPT_DF
12984 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo))
12985 {
12986 /*
12987 * Execution of IRET caused a fault when NMI blocking was in effect (i.e we're in
12988 * the guest or nested-guest NMI handler). We need to set the block-by-NMI field so
12989 * that NMIs remain blocked until the IRET execution is completed.
12990 *
12991 * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
12992 */
12993 CPUMSetGuestNmiBlocking(pVCpu, true);
12994 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
12995 }
12996 else if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
12997 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
12998 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
12999 {
13000 /*
13001 * Execution of IRET caused an EPT violation, page-modification log-full event or
13002 * SPP-related event VM-exit when NMI blocking was in effect (i.e. we're in the
13003 * guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13004 * that NMIs remain blocked until the IRET execution is completed.
13005 *
13006 * See Intel spec. 27.2.3 "Information about NMI unblocking due to IRET"
13007 */
13008 if (VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitQual))
13009 {
13010 CPUMSetGuestNmiBlocking(pVCpu, true);
13011 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13012 }
13013 }
13014 }
13015
13016 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13017 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13018 return rcStrict;
13019}
13020
13021
13022#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13023/**
13024 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13025 * guest attempting to execute a VMX instruction.
13026 *
13027 * @returns Strict VBox status code (i.e. informational status codes too).
13028 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13029 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13030 *
13031 * @param pVCpu The cross context virtual CPU structure.
13032 * @param uExitReason The VM-exit reason.
13033 *
13034 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13035 * @remarks No-long-jump zone!!!
13036 */
13037static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPUCC pVCpu, uint32_t uExitReason)
13038{
13039 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13040 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13041
13042 /*
13043 * The physical CPU would have already checked the CPU mode/code segment.
13044 * We shall just assert here for paranoia.
13045 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13046 */
13047 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13048 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13049 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13050
13051 if (uExitReason == VMX_EXIT_VMXON)
13052 {
13053 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13054
13055 /*
13056 * We check CR4.VMXE because it is required to be always set while in VMX operation
13057 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13058 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13059 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13060 */
13061 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13062 {
13063 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13064 hmR0VmxSetPendingXcptUD(pVCpu);
13065 return VINF_HM_PENDING_XCPT;
13066 }
13067 }
13068 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13069 {
13070 /*
13071 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13072 * (other than VMXON), we need to raise a #UD.
13073 */
13074 Log4Func(("Not in VMX root mode -> #UD\n"));
13075 hmR0VmxSetPendingXcptUD(pVCpu);
13076 return VINF_HM_PENDING_XCPT;
13077 }
13078
13079 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13080 return VINF_SUCCESS;
13081}
13082
13083
13084/**
13085 * Decodes the memory operand of an instruction that caused a VM-exit.
13086 *
13087 * The Exit qualification field provides the displacement field for memory
13088 * operand instructions, if any.
13089 *
13090 * @returns Strict VBox status code (i.e. informational status codes too).
13091 * @retval VINF_SUCCESS if the operand was successfully decoded.
13092 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
13093 * operand.
13094 * @param pVCpu The cross context virtual CPU structure.
13095 * @param uExitInstrInfo The VM-exit instruction information field.
13096 * @param enmMemAccess The memory operand's access type (read or write).
13097 * @param GCPtrDisp The instruction displacement field, if any. For
13098 * RIP-relative addressing pass RIP + displacement here.
13099 * @param pGCPtrMem Where to store the effective destination memory address.
13100 *
13101 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
13102 * virtual-8086 mode hence skips those checks while verifying if the
13103 * segment is valid.
13104 */
13105static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPUCC pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
13106 PRTGCPTR pGCPtrMem)
13107{
13108 Assert(pGCPtrMem);
13109 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
13110 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
13111 | CPUMCTX_EXTRN_CR0);
13112
13113 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
13114 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
13115 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
13116
13117 VMXEXITINSTRINFO ExitInstrInfo;
13118 ExitInstrInfo.u = uExitInstrInfo;
13119 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
13120 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
13121 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
13122 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
13123 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
13124 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
13125 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
13126 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
13127 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
13128
13129 /*
13130 * Validate instruction information.
13131 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
13132 */
13133 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
13134 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
13135 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
13136 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
13137 AssertLogRelMsgReturn(fIsMemOperand,
13138 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
13139
13140 /*
13141 * Compute the complete effective address.
13142 *
13143 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
13144 * See AMD spec. 4.5.2 "Segment Registers".
13145 */
13146 RTGCPTR GCPtrMem = GCPtrDisp;
13147 if (fBaseRegValid)
13148 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
13149 if (fIdxRegValid)
13150 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
13151
13152 RTGCPTR const GCPtrOff = GCPtrMem;
13153 if ( !fIsLongMode
13154 || iSegReg >= X86_SREG_FS)
13155 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
13156 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
13157
13158 /*
13159 * Validate effective address.
13160 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
13161 */
13162 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
13163 Assert(cbAccess > 0);
13164 if (fIsLongMode)
13165 {
13166 if (X86_IS_CANONICAL(GCPtrMem))
13167 {
13168 *pGCPtrMem = GCPtrMem;
13169 return VINF_SUCCESS;
13170 }
13171
13172 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
13173 * "Data Limit Checks in 64-bit Mode". */
13174 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
13175 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13176 return VINF_HM_PENDING_XCPT;
13177 }
13178
13179 /*
13180 * This is a watered down version of iemMemApplySegment().
13181 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
13182 * and segment CPL/DPL checks are skipped.
13183 */
13184 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
13185 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
13186 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
13187
13188 /* Check if the segment is present and usable. */
13189 if ( pSel->Attr.n.u1Present
13190 && !pSel->Attr.n.u1Unusable)
13191 {
13192 Assert(pSel->Attr.n.u1DescType);
13193 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
13194 {
13195 /* Check permissions for the data segment. */
13196 if ( enmMemAccess == VMXMEMACCESS_WRITE
13197 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
13198 {
13199 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13200 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
13201 return VINF_HM_PENDING_XCPT;
13202 }
13203
13204 /* Check limits if it's a normal data segment. */
13205 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
13206 {
13207 if ( GCPtrFirst32 > pSel->u32Limit
13208 || GCPtrLast32 > pSel->u32Limit)
13209 {
13210 Log4Func(("Data segment limit exceeded. "
13211 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13212 GCPtrLast32, pSel->u32Limit));
13213 if (iSegReg == X86_SREG_SS)
13214 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13215 else
13216 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13217 return VINF_HM_PENDING_XCPT;
13218 }
13219 }
13220 else
13221 {
13222 /* Check limits if it's an expand-down data segment.
13223 Note! The upper boundary is defined by the B bit, not the G bit! */
13224 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
13225 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
13226 {
13227 Log4Func(("Expand-down data segment limit exceeded. "
13228 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13229 GCPtrLast32, pSel->u32Limit));
13230 if (iSegReg == X86_SREG_SS)
13231 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13232 else
13233 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13234 return VINF_HM_PENDING_XCPT;
13235 }
13236 }
13237 }
13238 else
13239 {
13240 /* Check permissions for the code segment. */
13241 if ( enmMemAccess == VMXMEMACCESS_WRITE
13242 || ( enmMemAccess == VMXMEMACCESS_READ
13243 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
13244 {
13245 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
13246 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13247 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13248 return VINF_HM_PENDING_XCPT;
13249 }
13250
13251 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
13252 if ( GCPtrFirst32 > pSel->u32Limit
13253 || GCPtrLast32 > pSel->u32Limit)
13254 {
13255 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
13256 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
13257 if (iSegReg == X86_SREG_SS)
13258 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13259 else
13260 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13261 return VINF_HM_PENDING_XCPT;
13262 }
13263 }
13264 }
13265 else
13266 {
13267 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13268 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13269 return VINF_HM_PENDING_XCPT;
13270 }
13271
13272 *pGCPtrMem = GCPtrMem;
13273 return VINF_SUCCESS;
13274}
13275#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13276
13277
13278/**
13279 * VM-exit helper for LMSW.
13280 */
13281static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
13282{
13283 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13284 AssertRCReturn(rc, rc);
13285
13286 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
13287 AssertMsg( rcStrict == VINF_SUCCESS
13288 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13289
13290 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13291 if (rcStrict == VINF_IEM_RAISED_XCPT)
13292 {
13293 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13294 rcStrict = VINF_SUCCESS;
13295 }
13296
13297 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
13298 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13299 return rcStrict;
13300}
13301
13302
13303/**
13304 * VM-exit helper for CLTS.
13305 */
13306static VBOXSTRICTRC hmR0VmxExitClts(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
13307{
13308 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13309 AssertRCReturn(rc, rc);
13310
13311 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
13312 AssertMsg( rcStrict == VINF_SUCCESS
13313 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13314
13315 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13316 if (rcStrict == VINF_IEM_RAISED_XCPT)
13317 {
13318 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13319 rcStrict = VINF_SUCCESS;
13320 }
13321
13322 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
13323 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13324 return rcStrict;
13325}
13326
13327
13328/**
13329 * VM-exit helper for MOV from CRx (CRx read).
13330 */
13331static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13332{
13333 Assert(iCrReg < 16);
13334 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
13335
13336 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13337 AssertRCReturn(rc, rc);
13338
13339 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
13340 AssertMsg( rcStrict == VINF_SUCCESS
13341 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13342
13343 if (iGReg == X86_GREG_xSP)
13344 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
13345 else
13346 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13347#ifdef VBOX_WITH_STATISTICS
13348 switch (iCrReg)
13349 {
13350 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
13351 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
13352 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
13353 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
13354 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
13355 }
13356#endif
13357 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
13358 return rcStrict;
13359}
13360
13361
13362/**
13363 * VM-exit helper for MOV to CRx (CRx write).
13364 */
13365static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13366{
13367 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13368 AssertRCReturn(rc, rc);
13369
13370 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
13371 AssertMsg( rcStrict == VINF_SUCCESS
13372 || rcStrict == VINF_IEM_RAISED_XCPT
13373 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13374
13375 switch (iCrReg)
13376 {
13377 case 0:
13378 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13379 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
13380 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
13381 break;
13382
13383 case 2:
13384 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
13385 /* Nothing to do here, CR2 it's not part of the VMCS. */
13386 break;
13387
13388 case 3:
13389 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
13390 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
13391 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
13392 break;
13393
13394 case 4:
13395 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
13396 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
13397 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
13398 pVCpu->cpum.GstCtx.cr4, pVCpu->hm.s.fLoadSaveGuestXcr0));
13399 break;
13400
13401 case 8:
13402 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
13403 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
13404 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
13405 break;
13406
13407 default:
13408 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
13409 break;
13410 }
13411
13412 if (rcStrict == VINF_IEM_RAISED_XCPT)
13413 {
13414 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13415 rcStrict = VINF_SUCCESS;
13416 }
13417 return rcStrict;
13418}
13419
13420
13421/**
13422 * VM-exit exception handler for \#PF (Page-fault exception).
13423 *
13424 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13425 */
13426static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13427{
13428 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13429 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
13430 hmR0VmxReadExitQualVmcs(pVmxTransient);
13431
13432 if (!pVM->hm.s.fNestedPaging)
13433 { /* likely */ }
13434 else
13435 {
13436#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
13437 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hm.s.fUsingDebugLoop);
13438#endif
13439 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
13440 if (!pVmxTransient->fVectoringDoublePF)
13441 {
13442 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13443 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
13444 }
13445 else
13446 {
13447 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13448 Assert(!pVmxTransient->fIsNestedGuest);
13449 hmR0VmxSetPendingXcptDF(pVCpu);
13450 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
13451 }
13452 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13453 return VINF_SUCCESS;
13454 }
13455
13456 Assert(!pVmxTransient->fIsNestedGuest);
13457
13458 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
13459 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
13460 if (pVmxTransient->fVectoringPF)
13461 {
13462 Assert(pVCpu->hm.s.Event.fPending);
13463 return VINF_EM_RAW_INJECT_TRPM_EVENT;
13464 }
13465
13466 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13467 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13468 AssertRCReturn(rc, rc);
13469
13470 Log4Func(("#PF: cr2=%#RX64 cs:rip=%#04x:%#RX64 uErrCode %#RX32 cr3=%#RX64\n", pVmxTransient->uExitQual, pCtx->cs.Sel,
13471 pCtx->rip, pVmxTransient->uExitIntErrorCode, pCtx->cr3));
13472
13473 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
13474 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
13475
13476 Log4Func(("#PF: rc=%Rrc\n", rc));
13477 if (rc == VINF_SUCCESS)
13478 {
13479 /*
13480 * This is typically a shadow page table sync or a MMIO instruction. But we may have
13481 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
13482 */
13483 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13484 TRPMResetTrap(pVCpu);
13485 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
13486 return rc;
13487 }
13488
13489 if (rc == VINF_EM_RAW_GUEST_TRAP)
13490 {
13491 if (!pVmxTransient->fVectoringDoublePF)
13492 {
13493 /* It's a guest page fault and needs to be reflected to the guest. */
13494 uint32_t uGstErrorCode = TRPMGetErrorCode(pVCpu);
13495 TRPMResetTrap(pVCpu);
13496 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
13497 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13498 uGstErrorCode, pVmxTransient->uExitQual);
13499 }
13500 else
13501 {
13502 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13503 TRPMResetTrap(pVCpu);
13504 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
13505 hmR0VmxSetPendingXcptDF(pVCpu);
13506 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
13507 }
13508
13509 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13510 return VINF_SUCCESS;
13511 }
13512
13513 TRPMResetTrap(pVCpu);
13514 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
13515 return rc;
13516}
13517
13518
13519/**
13520 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
13521 *
13522 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13523 */
13524static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13525{
13526 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13527 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
13528
13529 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
13530 AssertRCReturn(rc, rc);
13531
13532 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
13533 {
13534 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
13535 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
13536
13537 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
13538 * provides VM-exit instruction length. If this causes problem later,
13539 * disassemble the instruction like it's done on AMD-V. */
13540 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13541 AssertRCReturn(rc2, rc2);
13542 return rc;
13543 }
13544
13545 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
13546 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13547 return VINF_SUCCESS;
13548}
13549
13550
13551/**
13552 * VM-exit exception handler for \#BP (Breakpoint exception).
13553 *
13554 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13555 */
13556static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13557{
13558 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13559 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
13560
13561 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13562 AssertRCReturn(rc, rc);
13563
13564 if (!pVmxTransient->fIsNestedGuest)
13565 rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
13566 else
13567 rc = VINF_EM_RAW_GUEST_TRAP;
13568 if (rc == VINF_EM_RAW_GUEST_TRAP)
13569 {
13570 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
13571 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13572 rc = VINF_SUCCESS;
13573 }
13574
13575 Assert(rc == VINF_SUCCESS || rc == VINF_EM_RAW_GUEST_TRAP || rc == VINF_EM_DBG_BREAKPOINT);
13576 return rc;
13577}
13578
13579
13580/**
13581 * VM-exit exception handler for \#AC (Alignment-check exception).
13582 *
13583 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13584 */
13585static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13586{
13587 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13588 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
13589
13590 /* Re-inject it. We'll detect any nesting before getting here. */
13591 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
13592 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13593 return VINF_SUCCESS;
13594}
13595
13596
13597/**
13598 * VM-exit exception handler for \#DB (Debug exception).
13599 *
13600 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13601 */
13602static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13603{
13604 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13605 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
13606
13607 /*
13608 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
13609 */
13610 hmR0VmxReadExitQualVmcs(pVmxTransient);
13611
13612 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
13613 uint64_t const uDR6 = X86_DR6_INIT_VAL
13614 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
13615 | X86_DR6_BD | X86_DR6_BS));
13616
13617 int rc;
13618 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13619 if (!pVmxTransient->fIsNestedGuest)
13620 rc = DBGFRZTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
13621 else
13622 rc = VINF_EM_RAW_GUEST_TRAP;
13623 Log6Func(("rc=%Rrc\n", rc));
13624 if (rc == VINF_EM_RAW_GUEST_TRAP)
13625 {
13626 /*
13627 * The exception was for the guest. Update DR6, DR7.GD and
13628 * IA32_DEBUGCTL.LBR before forwarding it.
13629 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
13630 */
13631 VMMRZCallRing3Disable(pVCpu);
13632 HM_DISABLE_PREEMPT(pVCpu);
13633
13634 pCtx->dr[6] &= ~X86_DR6_B_MASK;
13635 pCtx->dr[6] |= uDR6;
13636 if (CPUMIsGuestDebugStateActive(pVCpu))
13637 ASMSetDR6(pCtx->dr[6]);
13638
13639 HM_RESTORE_PREEMPT();
13640 VMMRZCallRing3Enable(pVCpu);
13641
13642 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
13643 AssertRCReturn(rc, rc);
13644
13645 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
13646 pCtx->dr[7] &= ~(uint64_t)X86_DR7_GD;
13647
13648 /* Paranoia. */
13649 pCtx->dr[7] &= ~(uint64_t)X86_DR7_RAZ_MASK;
13650 pCtx->dr[7] |= X86_DR7_RA1_MASK;
13651
13652 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, pCtx->dr[7]);
13653 AssertRC(rc);
13654
13655 /*
13656 * Raise #DB in the guest.
13657 *
13658 * It is important to reflect exactly what the VM-exit gave us (preserving the
13659 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
13660 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
13661 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
13662 *
13663 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
13664 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
13665 */
13666 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
13667 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13668 return VINF_SUCCESS;
13669 }
13670
13671 /*
13672 * Not a guest trap, must be a hypervisor related debug event then.
13673 * Update DR6 in case someone is interested in it.
13674 */
13675 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
13676 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
13677 CPUMSetHyperDR6(pVCpu, uDR6);
13678
13679 return rc;
13680}
13681
13682
13683/**
13684 * Hacks its way around the lovely mesa driver's backdoor accesses.
13685 *
13686 * @sa hmR0SvmHandleMesaDrvGp.
13687 */
13688static int hmR0VmxHandleMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
13689{
13690 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
13691 RT_NOREF(pCtx);
13692
13693 /* For now we'll just skip the instruction. */
13694 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13695}
13696
13697
13698/**
13699 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
13700 * backdoor logging w/o checking what it is running inside.
13701 *
13702 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
13703 * backdoor port and magic numbers loaded in registers.
13704 *
13705 * @returns true if it is, false if it isn't.
13706 * @sa hmR0SvmIsMesaDrvGp.
13707 */
13708DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
13709{
13710 /* 0xed: IN eAX,dx */
13711 uint8_t abInstr[1];
13712 if (pVmxTransient->cbInstr != sizeof(abInstr))
13713 return false;
13714
13715 /* Check that it is #GP(0). */
13716 if (pVmxTransient->uExitIntErrorCode != 0)
13717 return false;
13718
13719 /* Check magic and port. */
13720 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
13721 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
13722 if (pCtx->rax != UINT32_C(0x564d5868))
13723 return false;
13724 if (pCtx->dx != UINT32_C(0x5658))
13725 return false;
13726
13727 /* Flat ring-3 CS. */
13728 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
13729 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
13730 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
13731 if (pCtx->cs.Attr.n.u2Dpl != 3)
13732 return false;
13733 if (pCtx->cs.u64Base != 0)
13734 return false;
13735
13736 /* Check opcode. */
13737 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
13738 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
13739 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
13740 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
13741 if (RT_FAILURE(rc))
13742 return false;
13743 if (abInstr[0] != 0xed)
13744 return false;
13745
13746 return true;
13747}
13748
13749
13750/**
13751 * VM-exit exception handler for \#GP (General-protection exception).
13752 *
13753 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13754 */
13755static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13756{
13757 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13758 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
13759
13760 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13761 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13762 if (pVmcsInfo->RealMode.fRealOnV86Active)
13763 { /* likely */ }
13764 else
13765 {
13766#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13767 Assert(pVCpu->hm.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
13768#endif
13769 /*
13770 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
13771 * executing a nested-guest, reflect #GP to the guest or nested-guest.
13772 */
13773 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13774 AssertRCReturn(rc, rc);
13775 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
13776 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
13777
13778 if ( pVmxTransient->fIsNestedGuest
13779 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
13780 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
13781 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13782 pVmxTransient->cbInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13783 else
13784 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
13785 return rc;
13786 }
13787
13788 Assert(CPUMIsGuestInRealModeEx(pCtx));
13789 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest);
13790 Assert(!pVmxTransient->fIsNestedGuest);
13791
13792 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13793 AssertRCReturn(rc, rc);
13794
13795 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
13796 if (rcStrict == VINF_SUCCESS)
13797 {
13798 if (!CPUMIsGuestInRealModeEx(pCtx))
13799 {
13800 /*
13801 * The guest is no longer in real-mode, check if we can continue executing the
13802 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
13803 */
13804 pVmcsInfo->RealMode.fRealOnV86Active = false;
13805 if (HMCanExecuteVmxGuest(pVCpu->pVMR0, pVCpu, pCtx))
13806 {
13807 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
13808 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13809 }
13810 else
13811 {
13812 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
13813 rcStrict = VINF_EM_RESCHEDULE;
13814 }
13815 }
13816 else
13817 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13818 }
13819 else if (rcStrict == VINF_IEM_RAISED_XCPT)
13820 {
13821 rcStrict = VINF_SUCCESS;
13822 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13823 }
13824 return VBOXSTRICTRC_VAL(rcStrict);
13825}
13826
13827
13828/**
13829 * VM-exit exception handler wrapper for all other exceptions that are not handled
13830 * by a specific handler.
13831 *
13832 * This simply re-injects the exception back into the VM without any special
13833 * processing.
13834 *
13835 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13836 */
13837static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13838{
13839 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13840
13841#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13842 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13843 AssertMsg(pVCpu->hm.s.fUsingDebugLoop || pVmcsInfo->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
13844 ("uVector=%#x u32XcptBitmap=%#X32\n",
13845 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
13846 NOREF(pVmcsInfo);
13847#endif
13848
13849 /*
13850 * Re-inject the exception into the guest. This cannot be a double-fault condition which
13851 * would have been handled while checking exits due to event delivery.
13852 */
13853 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
13854
13855#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13856 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
13857 AssertRCReturn(rc, rc);
13858 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
13859#endif
13860
13861#ifdef VBOX_WITH_STATISTICS
13862 switch (uVector)
13863 {
13864 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
13865 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
13866 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
13867 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
13868 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
13869 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
13870 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
13871 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
13872 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
13873 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
13874 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
13875 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
13876 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
13877 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
13878 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
13879 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
13880 default:
13881 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
13882 break;
13883 }
13884#endif
13885
13886 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
13887 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
13888 NOREF(uVector);
13889
13890 /* Re-inject the original exception into the guest. */
13891 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
13892 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13893 return VINF_SUCCESS;
13894}
13895
13896
13897/**
13898 * VM-exit exception handler for all exceptions (except NMIs!).
13899 *
13900 * @remarks This may be called for both guests and nested-guests. Take care to not
13901 * make assumptions and avoid doing anything that is not relevant when
13902 * executing a nested-guest (e.g., Mesa driver hacks).
13903 */
13904static VBOXSTRICTRC hmR0VmxExitXcpt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13905{
13906 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
13907
13908 /*
13909 * If this VM-exit occurred while delivering an event through the guest IDT, take
13910 * action based on the return code and additional hints (e.g. for page-faults)
13911 * that will be updated in the VMX transient structure.
13912 */
13913 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
13914 if (rcStrict == VINF_SUCCESS)
13915 {
13916 /*
13917 * If an exception caused a VM-exit due to delivery of an event, the original
13918 * event may have to be re-injected into the guest. We shall reinject it and
13919 * continue guest execution. However, page-fault is a complicated case and
13920 * needs additional processing done in hmR0VmxExitXcptPF().
13921 */
13922 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
13923 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
13924 if ( !pVCpu->hm.s.Event.fPending
13925 || uVector == X86_XCPT_PF)
13926 {
13927 switch (uVector)
13928 {
13929 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
13930 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
13931 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
13932 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
13933 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
13934 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
13935 default:
13936 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
13937 }
13938 }
13939 /* else: inject pending event before resuming guest execution. */
13940 }
13941 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
13942 {
13943 Assert(pVCpu->hm.s.Event.fPending);
13944 rcStrict = VINF_SUCCESS;
13945 }
13946
13947 return rcStrict;
13948}
13949/** @} */
13950
13951
13952/** @name VM-exit handlers.
13953 * @{
13954 */
13955/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13956/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
13957/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13958
13959/**
13960 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
13961 */
13962HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13963{
13964 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13965 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
13966 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
13967 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
13968 return VINF_SUCCESS;
13969 return VINF_EM_RAW_INTERRUPT;
13970}
13971
13972
13973/**
13974 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
13975 * VM-exit.
13976 */
13977HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13978{
13979 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13980 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
13981
13982 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
13983
13984 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
13985 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
13986 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
13987
13988 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13989 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
13990 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
13991 NOREF(pVmcsInfo);
13992
13993 VBOXSTRICTRC rcStrict;
13994 switch (uExitIntType)
13995 {
13996 /*
13997 * Host physical NMIs:
13998 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
13999 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14000 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14001 *
14002 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14003 * See Intel spec. 27.5.5 "Updating Non-Register State".
14004 */
14005 case VMX_EXIT_INT_INFO_TYPE_NMI:
14006 {
14007 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14008 break;
14009 }
14010
14011 /*
14012 * Privileged software exceptions (#DB from ICEBP),
14013 * Software exceptions (#BP and #OF),
14014 * Hardware exceptions:
14015 * Process the required exceptions and resume guest execution if possible.
14016 */
14017 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14018 Assert(uVector == X86_XCPT_DB);
14019 RT_FALL_THRU();
14020 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14021 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14022 RT_FALL_THRU();
14023 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14024 {
14025 NOREF(uVector);
14026 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14027 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14028 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14029 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14030
14031 rcStrict = hmR0VmxExitXcpt(pVCpu, pVmxTransient);
14032 break;
14033 }
14034
14035 default:
14036 {
14037 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14038 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14039 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14040 break;
14041 }
14042 }
14043
14044 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14045 return rcStrict;
14046}
14047
14048
14049/**
14050 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14051 */
14052HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14053{
14054 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14055
14056 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14057 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14058 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14059
14060 /* Evaluate and deliver pending events and resume guest execution. */
14061 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14062 return VINF_SUCCESS;
14063}
14064
14065
14066/**
14067 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14068 */
14069HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14070{
14071 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14072
14073 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14074 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14075 {
14076 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14077 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14078 }
14079
14080 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14081
14082 /*
14083 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14084 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14085 */
14086 uint32_t fIntrState;
14087 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
14088 AssertRC(rc);
14089 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
14090 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
14091 {
14092 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
14093 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
14094
14095 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
14096 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
14097 AssertRC(rc);
14098 }
14099
14100 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
14101 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
14102
14103 /* Evaluate and deliver pending events and resume guest execution. */
14104 return VINF_SUCCESS;
14105}
14106
14107
14108/**
14109 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
14110 */
14111HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14112{
14113 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14114 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14115}
14116
14117
14118/**
14119 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
14120 */
14121HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14122{
14123 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14124 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14125}
14126
14127
14128/**
14129 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
14130 */
14131HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14132{
14133 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14134
14135 /*
14136 * Get the state we need and update the exit history entry.
14137 */
14138 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14139 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14140
14141 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14142 AssertRCReturn(rc, rc);
14143
14144 VBOXSTRICTRC rcStrict;
14145 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14146 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
14147 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14148 if (!pExitRec)
14149 {
14150 /*
14151 * Regular CPUID instruction execution.
14152 */
14153 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbInstr);
14154 if (rcStrict == VINF_SUCCESS)
14155 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14156 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14157 {
14158 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14159 rcStrict = VINF_SUCCESS;
14160 }
14161 }
14162 else
14163 {
14164 /*
14165 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14166 */
14167 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14168 AssertRCReturn(rc2, rc2);
14169
14170 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
14171 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
14172
14173 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14174 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14175
14176 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14177 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14178 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14179 }
14180 return rcStrict;
14181}
14182
14183
14184/**
14185 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
14186 */
14187HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14188{
14189 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14190
14191 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14192 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
14193 AssertRCReturn(rc, rc);
14194
14195 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
14196 return VINF_EM_RAW_EMULATE_INSTR;
14197
14198 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
14199 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14200}
14201
14202
14203/**
14204 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
14205 */
14206HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14207{
14208 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14209
14210 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14211 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14212 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14213 AssertRCReturn(rc, rc);
14214
14215 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbInstr);
14216 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14217 {
14218 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14219 we must reset offsetting on VM-entry. See @bugref{6634}. */
14220 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14221 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14222 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14223 }
14224 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14225 {
14226 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14227 rcStrict = VINF_SUCCESS;
14228 }
14229 return rcStrict;
14230}
14231
14232
14233/**
14234 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
14235 */
14236HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14237{
14238 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14239
14240 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14241 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14242 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
14243 AssertRCReturn(rc, rc);
14244
14245 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbInstr);
14246 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14247 {
14248 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14249 we must reset offsetting on VM-reentry. See @bugref{6634}. */
14250 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14251 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14252 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14253 }
14254 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14255 {
14256 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14257 rcStrict = VINF_SUCCESS;
14258 }
14259 return rcStrict;
14260}
14261
14262
14263/**
14264 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
14265 */
14266HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14267{
14268 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14269
14270 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14271 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
14272 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
14273 AssertRCReturn(rc, rc);
14274
14275 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14276 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
14277 if (RT_LIKELY(rc == VINF_SUCCESS))
14278 {
14279 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14280 Assert(pVmxTransient->cbInstr == 2);
14281 }
14282 else
14283 {
14284 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
14285 rc = VERR_EM_INTERPRETER;
14286 }
14287 return rc;
14288}
14289
14290
14291/**
14292 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
14293 */
14294HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14295{
14296 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14297
14298 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
14299 if (EMAreHypercallInstructionsEnabled(pVCpu))
14300 {
14301 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14302 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
14303 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
14304 AssertRCReturn(rc, rc);
14305
14306 /* Perform the hypercall. */
14307 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
14308 if (rcStrict == VINF_SUCCESS)
14309 {
14310 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14311 AssertRCReturn(rc, rc);
14312 }
14313 else
14314 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
14315 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
14316 || RT_FAILURE(rcStrict));
14317
14318 /* If the hypercall changes anything other than guest's general-purpose registers,
14319 we would need to reload the guest changed bits here before VM-entry. */
14320 }
14321 else
14322 Log4Func(("Hypercalls not enabled\n"));
14323
14324 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
14325 if (RT_FAILURE(rcStrict))
14326 {
14327 hmR0VmxSetPendingXcptUD(pVCpu);
14328 rcStrict = VINF_SUCCESS;
14329 }
14330
14331 return rcStrict;
14332}
14333
14334
14335/**
14336 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
14337 */
14338HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14339{
14340 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14341 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || pVCpu->hm.s.fUsingDebugLoop);
14342
14343 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14344 hmR0VmxReadExitQualVmcs(pVmxTransient);
14345 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14346 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14347 AssertRCReturn(rc, rc);
14348
14349 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbInstr, pVmxTransient->uExitQual);
14350
14351 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
14352 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14353 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14354 {
14355 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14356 rcStrict = VINF_SUCCESS;
14357 }
14358 else
14359 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
14360 VBOXSTRICTRC_VAL(rcStrict)));
14361 return rcStrict;
14362}
14363
14364
14365/**
14366 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
14367 */
14368HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14369{
14370 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14371
14372 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14373 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14374 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
14375 AssertRCReturn(rc, rc);
14376
14377 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbInstr);
14378 if (rcStrict == VINF_SUCCESS)
14379 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14380 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14381 {
14382 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14383 rcStrict = VINF_SUCCESS;
14384 }
14385
14386 return rcStrict;
14387}
14388
14389
14390/**
14391 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
14392 */
14393HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14394{
14395 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14396
14397 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14398 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14399 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14400 AssertRCReturn(rc, rc);
14401
14402 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbInstr);
14403 if (RT_SUCCESS(rcStrict))
14404 {
14405 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14406 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
14407 rcStrict = VINF_SUCCESS;
14408 }
14409
14410 return rcStrict;
14411}
14412
14413
14414/**
14415 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
14416 * VM-exit.
14417 */
14418HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14419{
14420 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14421 return VINF_EM_RESET;
14422}
14423
14424
14425/**
14426 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
14427 */
14428HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14429{
14430 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14431
14432 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14433 AssertRCReturn(rc, rc);
14434
14435 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
14436 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
14437 rc = VINF_SUCCESS;
14438 else
14439 rc = VINF_EM_HALT;
14440
14441 if (rc != VINF_SUCCESS)
14442 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
14443 return rc;
14444}
14445
14446
14447/**
14448 * VM-exit handler for instructions that result in a \#UD exception delivered to
14449 * the guest.
14450 */
14451HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14452{
14453 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14454 hmR0VmxSetPendingXcptUD(pVCpu);
14455 return VINF_SUCCESS;
14456}
14457
14458
14459/**
14460 * VM-exit handler for expiry of the VMX-preemption timer.
14461 */
14462HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14463{
14464 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14465
14466 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
14467 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14468
14469 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
14470 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
14471 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
14472 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
14473 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
14474}
14475
14476
14477/**
14478 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
14479 */
14480HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14481{
14482 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14483
14484 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14485 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14486 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
14487 AssertRCReturn(rc, rc);
14488
14489 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbInstr);
14490 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
14491 : HM_CHANGED_RAISED_XCPT_MASK);
14492
14493 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14494 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
14495
14496 return rcStrict;
14497}
14498
14499
14500/**
14501 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
14502 */
14503HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14504{
14505 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14506 /** @todo Use VM-exit instruction information. */
14507 return VERR_EM_INTERPRETER;
14508}
14509
14510
14511/**
14512 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
14513 * VM-exit.
14514 */
14515HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14516{
14517 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14518 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14519 AssertRCReturn(rc, rc);
14520
14521 rc = hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
14522 if (RT_FAILURE(rc))
14523 return rc;
14524
14525 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
14526 NOREF(uInvalidReason);
14527
14528#ifdef VBOX_STRICT
14529 uint32_t fIntrState;
14530 uint64_t u64Val;
14531 hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
14532 hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
14533 hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
14534
14535 Log4(("uInvalidReason %u\n", uInvalidReason));
14536 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
14537 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
14538 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
14539
14540 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState); AssertRC(rc);
14541 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
14542 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Val); AssertRC(rc);
14543 Log4(("VMX_VMCS_GUEST_CR0 %#RX64\n", u64Val));
14544 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_MASK, &u64Val); AssertRC(rc);
14545 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RX64\n", u64Val));
14546 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Val); AssertRC(rc);
14547 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14548 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_MASK, &u64Val); AssertRC(rc);
14549 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RX64\n", u64Val));
14550 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Val); AssertRC(rc);
14551 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14552 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
14553 {
14554 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
14555 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
14556 }
14557 hmR0DumpRegs(pVCpu, HM_DUMP_REG_FLAGS_ALL);
14558#endif
14559
14560 return VERR_VMX_INVALID_GUEST_STATE;
14561}
14562
14563/**
14564 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
14565 */
14566HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14567{
14568 /*
14569 * Cummulative notes of all recognized but unexpected VM-exits.
14570 *
14571 * 1. This does -not- cover scenarios like like a page-fault VM-exit occurring when
14572 * nested-paging is used.
14573 *
14574 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
14575 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
14576 * this function (and thereby stop VM execution) for handling such instructions.
14577 *
14578 *
14579 * VMX_EXIT_INIT_SIGNAL:
14580 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
14581 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
14582 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
14583 *
14584 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
14585 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
14586 * See Intel spec. "23.8 Restrictions on VMX operation".
14587 *
14588 * VMX_EXIT_SIPI:
14589 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
14590 * activity state is used. We don't make use of it as our guests don't have direct
14591 * access to the host local APIC.
14592 *
14593 * See Intel spec. 25.3 "Other Causes of VM-exits".
14594 *
14595 * VMX_EXIT_IO_SMI:
14596 * VMX_EXIT_SMI:
14597 * This can only happen if we support dual-monitor treatment of SMI, which can be
14598 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
14599 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
14600 * VMX root mode or receive an SMI. If we get here, something funny is going on.
14601 *
14602 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
14603 * See Intel spec. 25.3 "Other Causes of VM-Exits"
14604 *
14605 * VMX_EXIT_ERR_MSR_LOAD:
14606 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
14607 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
14608 * execution.
14609 *
14610 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
14611 *
14612 * VMX_EXIT_ERR_MACHINE_CHECK:
14613 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
14614 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
14615 * #MC exception abort class exception is raised. We thus cannot assume a
14616 * reasonable chance of continuing any sort of execution and we bail.
14617 *
14618 * See Intel spec. 15.1 "Machine-check Architecture".
14619 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
14620 *
14621 * VMX_EXIT_PML_FULL:
14622 * VMX_EXIT_VIRTUALIZED_EOI:
14623 * VMX_EXIT_APIC_WRITE:
14624 * We do not currently support any of these features and thus they are all unexpected
14625 * VM-exits.
14626 *
14627 * VMX_EXIT_GDTR_IDTR_ACCESS:
14628 * VMX_EXIT_LDTR_TR_ACCESS:
14629 * VMX_EXIT_RDRAND:
14630 * VMX_EXIT_RSM:
14631 * VMX_EXIT_VMFUNC:
14632 * VMX_EXIT_ENCLS:
14633 * VMX_EXIT_RDSEED:
14634 * VMX_EXIT_XSAVES:
14635 * VMX_EXIT_XRSTORS:
14636 * VMX_EXIT_UMWAIT:
14637 * VMX_EXIT_TPAUSE:
14638 * These VM-exits are -not- caused unconditionally by execution of the corresponding
14639 * instruction. Any VM-exit for these instructions indicate a hardware problem,
14640 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
14641 *
14642 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
14643 */
14644 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14645 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
14646 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14647}
14648
14649
14650/**
14651 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
14652 */
14653HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14654{
14655 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14656
14657 /** @todo Optimize this: We currently drag in in the whole MSR state
14658 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
14659 * MSRs required. That would require changes to IEM and possibly CPUM too.
14660 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
14661 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14662 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
14663 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
14664 switch (idMsr)
14665 {
14666 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
14667 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
14668 }
14669
14670 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14671 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
14672 AssertRCReturn(rc, rc);
14673
14674 Log4Func(("ecx=%#RX32\n", idMsr));
14675
14676#ifdef VBOX_STRICT
14677 Assert(!pVmxTransient->fIsNestedGuest);
14678 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
14679 {
14680 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
14681 && idMsr != MSR_K6_EFER)
14682 {
14683 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
14684 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14685 }
14686 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14687 {
14688 Assert(pVmcsInfo->pvMsrBitmap);
14689 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
14690 if (fMsrpm & VMXMSRPM_ALLOW_RD)
14691 {
14692 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
14693 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14694 }
14695 }
14696 }
14697#endif
14698
14699 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbInstr);
14700 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
14701 if (rcStrict == VINF_SUCCESS)
14702 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
14703 | HM_CHANGED_GUEST_RAX | HM_CHANGED_GUEST_RDX);
14704 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14705 {
14706 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14707 rcStrict = VINF_SUCCESS;
14708 }
14709 else
14710 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ, ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
14711
14712 return rcStrict;
14713}
14714
14715
14716/**
14717 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
14718 */
14719HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14720{
14721 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14722
14723 /** @todo Optimize this: We currently drag in in the whole MSR state
14724 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
14725 * MSRs required. That would require changes to IEM and possibly CPUM too.
14726 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
14727 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
14728 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
14729
14730 /*
14731 * The FS and GS base MSRs are not part of the above all-MSRs mask.
14732 * Although we don't need to fetch the base as it will be overwritten shortly, while
14733 * loading guest-state we would also load the entire segment register including limit
14734 * and attributes and thus we need to load them here.
14735 */
14736 switch (idMsr)
14737 {
14738 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
14739 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
14740 }
14741
14742 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14743 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14744 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
14745 AssertRCReturn(rc, rc);
14746
14747 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
14748
14749 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbInstr);
14750 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
14751
14752 if (rcStrict == VINF_SUCCESS)
14753 {
14754 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14755
14756 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
14757 if ( idMsr == MSR_IA32_APICBASE
14758 || ( idMsr >= MSR_IA32_X2APIC_START
14759 && idMsr <= MSR_IA32_X2APIC_END))
14760 {
14761 /*
14762 * We've already saved the APIC related guest-state (TPR) in post-run phase.
14763 * When full APIC register virtualization is implemented we'll have to make
14764 * sure APIC state is saved from the VMCS before IEM changes it.
14765 */
14766 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
14767 }
14768 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
14769 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14770 else if (idMsr == MSR_K6_EFER)
14771 {
14772 /*
14773 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
14774 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
14775 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
14776 */
14777 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
14778 }
14779
14780 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
14781 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
14782 {
14783 switch (idMsr)
14784 {
14785 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
14786 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
14787 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
14788 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
14789 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
14790 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
14791 default:
14792 {
14793 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14794 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
14795 else if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
14796 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
14797 break;
14798 }
14799 }
14800 }
14801#ifdef VBOX_STRICT
14802 else
14803 {
14804 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
14805 switch (idMsr)
14806 {
14807 case MSR_IA32_SYSENTER_CS:
14808 case MSR_IA32_SYSENTER_EIP:
14809 case MSR_IA32_SYSENTER_ESP:
14810 case MSR_K8_FS_BASE:
14811 case MSR_K8_GS_BASE:
14812 {
14813 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
14814 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14815 }
14816
14817 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
14818 default:
14819 {
14820 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
14821 {
14822 /* EFER MSR writes are always intercepted. */
14823 if (idMsr != MSR_K6_EFER)
14824 {
14825 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
14826 idMsr));
14827 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14828 }
14829 }
14830
14831 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14832 {
14833 Assert(pVmcsInfo->pvMsrBitmap);
14834 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
14835 if (fMsrpm & VMXMSRPM_ALLOW_WR)
14836 {
14837 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
14838 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14839 }
14840 }
14841 break;
14842 }
14843 }
14844 }
14845#endif /* VBOX_STRICT */
14846 }
14847 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14848 {
14849 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14850 rcStrict = VINF_SUCCESS;
14851 }
14852 else
14853 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE, ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
14854
14855 return rcStrict;
14856}
14857
14858
14859/**
14860 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
14861 */
14862HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14863{
14864 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14865
14866 /** @todo The guest has likely hit a contended spinlock. We might want to
14867 * poke a schedule different guest VCPU. */
14868 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14869 if (RT_SUCCESS(rc))
14870 return VINF_EM_RAW_INTERRUPT;
14871
14872 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
14873 return rc;
14874}
14875
14876
14877/**
14878 * VM-exit handler for when the TPR value is lowered below the specified
14879 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
14880 */
14881HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14882{
14883 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14884 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
14885
14886 /*
14887 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
14888 * We'll re-evaluate pending interrupts and inject them before the next VM
14889 * entry so we can just continue execution here.
14890 */
14891 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
14892 return VINF_SUCCESS;
14893}
14894
14895
14896/**
14897 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
14898 * VM-exit.
14899 *
14900 * @retval VINF_SUCCESS when guest execution can continue.
14901 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
14902 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
14903 * incompatible guest state for VMX execution (real-on-v86 case).
14904 */
14905HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14906{
14907 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14908 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
14909
14910 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14911 hmR0VmxReadExitQualVmcs(pVmxTransient);
14912 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14913
14914 VBOXSTRICTRC rcStrict;
14915 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
14916 uint64_t const uExitQual = pVmxTransient->uExitQual;
14917 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
14918 switch (uAccessType)
14919 {
14920 /*
14921 * MOV to CRx.
14922 */
14923 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
14924 {
14925 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14926 AssertRCReturn(rc, rc);
14927
14928 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
14929 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
14930 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
14931 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
14932
14933 /*
14934 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
14935 * - When nested paging isn't used.
14936 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
14937 * - We are executing in the VM debug loop.
14938 */
14939 Assert( iCrReg != 3
14940 || !pVM->hm.s.fNestedPaging
14941 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
14942 || pVCpu->hm.s.fUsingDebugLoop);
14943
14944 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
14945 Assert( iCrReg != 8
14946 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
14947
14948 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
14949 AssertMsg( rcStrict == VINF_SUCCESS
14950 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14951
14952 /*
14953 * This is a kludge for handling switches back to real mode when we try to use
14954 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
14955 * deal with special selector values, so we have to return to ring-3 and run
14956 * there till the selector values are V86 mode compatible.
14957 *
14958 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
14959 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
14960 * this function.
14961 */
14962 if ( iCrReg == 0
14963 && rcStrict == VINF_SUCCESS
14964 && !pVM->hm.s.vmx.fUnrestrictedGuest
14965 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
14966 && (uOldCr0 & X86_CR0_PE)
14967 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
14968 {
14969 /** @todo Check selectors rather than returning all the time. */
14970 Assert(!pVmxTransient->fIsNestedGuest);
14971 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
14972 rcStrict = VINF_EM_RESCHEDULE_REM;
14973 }
14974 break;
14975 }
14976
14977 /*
14978 * MOV from CRx.
14979 */
14980 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
14981 {
14982 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
14983 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
14984
14985 /*
14986 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
14987 * - When nested paging isn't used.
14988 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
14989 * - We are executing in the VM debug loop.
14990 */
14991 Assert( iCrReg != 3
14992 || !pVM->hm.s.fNestedPaging
14993 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
14994 || pVCpu->hm.s.fUsingDebugLoop);
14995
14996 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
14997 Assert( iCrReg != 8
14998 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
14999
15000 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
15001 break;
15002 }
15003
15004 /*
15005 * CLTS (Clear Task-Switch Flag in CR0).
15006 */
15007 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15008 {
15009 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbInstr);
15010 break;
15011 }
15012
15013 /*
15014 * LMSW (Load Machine-Status Word into CR0).
15015 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15016 */
15017 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15018 {
15019 RTGCPTR GCPtrEffDst;
15020 uint8_t const cbInstr = pVmxTransient->cbInstr;
15021 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15022 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15023 if (fMemOperand)
15024 {
15025 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
15026 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15027 }
15028 else
15029 GCPtrEffDst = NIL_RTGCPTR;
15030 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15031 break;
15032 }
15033
15034 default:
15035 {
15036 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15037 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15038 }
15039 }
15040
15041 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15042 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15043 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15044
15045 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15046 NOREF(pVM);
15047 return rcStrict;
15048}
15049
15050
15051/**
15052 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15053 * VM-exit.
15054 */
15055HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15056{
15057 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15058 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15059
15060 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15061 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15062 hmR0VmxReadExitQualVmcs(pVmxTransient);
15063 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15064 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15065 | CPUMCTX_EXTRN_EFER);
15066 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15067 AssertRCReturn(rc, rc);
15068
15069 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15070 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15071 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15072 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15073 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15074 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15075 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15076 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15077
15078 /*
15079 * Update exit history to see if this exit can be optimized.
15080 */
15081 VBOXSTRICTRC rcStrict;
15082 PCEMEXITREC pExitRec = NULL;
15083 if ( !fGstStepping
15084 && !fDbgStepping)
15085 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15086 !fIOString
15087 ? !fIOWrite
15088 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
15089 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
15090 : !fIOWrite
15091 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
15092 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
15093 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15094 if (!pExitRec)
15095 {
15096 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
15097 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
15098
15099 uint32_t const cbValue = s_aIOSizes[uIOSize];
15100 uint32_t const cbInstr = pVmxTransient->cbInstr;
15101 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
15102 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15103 if (fIOString)
15104 {
15105 /*
15106 * INS/OUTS - I/O String instruction.
15107 *
15108 * Use instruction-information if available, otherwise fall back on
15109 * interpreting the instruction.
15110 */
15111 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15112 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
15113 bool const fInsOutsInfo = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
15114 if (fInsOutsInfo)
15115 {
15116 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15117 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
15118 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
15119 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
15120 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
15121 if (fIOWrite)
15122 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
15123 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
15124 else
15125 {
15126 /*
15127 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
15128 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
15129 * See Intel Instruction spec. for "INS".
15130 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
15131 */
15132 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
15133 }
15134 }
15135 else
15136 rcStrict = IEMExecOne(pVCpu);
15137
15138 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15139 fUpdateRipAlready = true;
15140 }
15141 else
15142 {
15143 /*
15144 * IN/OUT - I/O instruction.
15145 */
15146 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15147 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
15148 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
15149 if (fIOWrite)
15150 {
15151 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
15152 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
15153 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15154 && !pCtx->eflags.Bits.u1TF)
15155 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
15156 }
15157 else
15158 {
15159 uint32_t u32Result = 0;
15160 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
15161 if (IOM_SUCCESS(rcStrict))
15162 {
15163 /* Save result of I/O IN instr. in AL/AX/EAX. */
15164 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
15165 }
15166 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15167 && !pCtx->eflags.Bits.u1TF)
15168 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
15169 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
15170 }
15171 }
15172
15173 if (IOM_SUCCESS(rcStrict))
15174 {
15175 if (!fUpdateRipAlready)
15176 {
15177 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
15178 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15179 }
15180
15181 /*
15182 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
15183 * while booting Fedora 17 64-bit guest.
15184 *
15185 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
15186 */
15187 if (fIOString)
15188 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
15189
15190 /*
15191 * If any I/O breakpoints are armed, we need to check if one triggered
15192 * and take appropriate action.
15193 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
15194 */
15195 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
15196 AssertRCReturn(rc, rc);
15197
15198 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
15199 * execution engines about whether hyper BPs and such are pending. */
15200 uint32_t const uDr7 = pCtx->dr[7];
15201 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
15202 && X86_DR7_ANY_RW_IO(uDr7)
15203 && (pCtx->cr4 & X86_CR4_DE))
15204 || DBGFBpIsHwIoArmed(pVM)))
15205 {
15206 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
15207
15208 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
15209 VMMRZCallRing3Disable(pVCpu);
15210 HM_DISABLE_PREEMPT(pVCpu);
15211
15212 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
15213
15214 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
15215 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
15216 {
15217 /* Raise #DB. */
15218 if (fIsGuestDbgActive)
15219 ASMSetDR6(pCtx->dr[6]);
15220 if (pCtx->dr[7] != uDr7)
15221 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
15222
15223 hmR0VmxSetPendingXcptDB(pVCpu);
15224 }
15225 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
15226 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
15227 else if ( rcStrict2 != VINF_SUCCESS
15228 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
15229 rcStrict = rcStrict2;
15230 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
15231
15232 HM_RESTORE_PREEMPT();
15233 VMMRZCallRing3Enable(pVCpu);
15234 }
15235 }
15236
15237#ifdef VBOX_STRICT
15238 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15239 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
15240 Assert(!fIOWrite);
15241 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15242 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
15243 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
15244 Assert(fIOWrite);
15245 else
15246 {
15247# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
15248 * statuses, that the VMM device and some others may return. See
15249 * IOM_SUCCESS() for guidance. */
15250 AssertMsg( RT_FAILURE(rcStrict)
15251 || rcStrict == VINF_SUCCESS
15252 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
15253 || rcStrict == VINF_EM_DBG_BREAKPOINT
15254 || rcStrict == VINF_EM_RAW_GUEST_TRAP
15255 || rcStrict == VINF_EM_RAW_TO_R3
15256 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15257# endif
15258 }
15259#endif
15260 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
15261 }
15262 else
15263 {
15264 /*
15265 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
15266 */
15267 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15268 AssertRCReturn(rc2, rc2);
15269 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
15270 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
15271 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
15272 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15273 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
15274 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
15275
15276 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15277 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15278
15279 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15280 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15281 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15282 }
15283 return rcStrict;
15284}
15285
15286
15287/**
15288 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
15289 * VM-exit.
15290 */
15291HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15292{
15293 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15294
15295 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
15296 hmR0VmxReadExitQualVmcs(pVmxTransient);
15297 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
15298 {
15299 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15300 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
15301 {
15302 uint32_t uErrCode;
15303 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
15304 {
15305 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15306 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
15307 }
15308 else
15309 uErrCode = 0;
15310
15311 RTGCUINTPTR GCPtrFaultAddress;
15312 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
15313 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
15314 else
15315 GCPtrFaultAddress = 0;
15316
15317 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15318
15319 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
15320 pVmxTransient->cbInstr, uErrCode, GCPtrFaultAddress);
15321
15322 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
15323 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
15324 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15325 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15326 }
15327 }
15328
15329 /* Fall back to the interpreter to emulate the task-switch. */
15330 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15331 return VERR_EM_INTERPRETER;
15332}
15333
15334
15335/**
15336 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
15337 */
15338HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15339{
15340 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15341
15342 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15343 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
15344 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15345 AssertRC(rc);
15346 return VINF_EM_DBG_STEPPED;
15347}
15348
15349
15350/**
15351 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
15352 */
15353HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15354{
15355 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15356 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
15357
15358 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15359 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15360 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15361 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15362 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15363
15364 /*
15365 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15366 */
15367 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15368 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15369 {
15370 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
15371 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
15372 {
15373 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15374 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15375 }
15376 }
15377 else
15378 {
15379 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15380 return rcStrict;
15381 }
15382
15383 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
15384 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15385 hmR0VmxReadExitQualVmcs(pVmxTransient);
15386 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15387 AssertRCReturn(rc, rc);
15388
15389 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
15390 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
15391 switch (uAccessType)
15392 {
15393 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
15394 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
15395 {
15396 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
15397 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
15398 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
15399
15400 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
15401 GCPhys &= PAGE_BASE_GC_MASK;
15402 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
15403 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
15404 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
15405
15406 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15407 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15408 rcStrict = IOMMMIOPhysHandler(pVM, pVCpu,
15409 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW,
15410 CPUMCTX2CORE(pCtx), GCPhys);
15411 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15412 if ( rcStrict == VINF_SUCCESS
15413 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15414 || rcStrict == VERR_PAGE_NOT_PRESENT)
15415 {
15416 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15417 | HM_CHANGED_GUEST_APIC_TPR);
15418 rcStrict = VINF_SUCCESS;
15419 }
15420 break;
15421 }
15422
15423 default:
15424 {
15425 Log4Func(("uAccessType=%#x\n", uAccessType));
15426 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
15427 break;
15428 }
15429 }
15430
15431 if (rcStrict != VINF_SUCCESS)
15432 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
15433 return rcStrict;
15434}
15435
15436
15437/**
15438 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
15439 * VM-exit.
15440 */
15441HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15442{
15443 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15444 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15445
15446 /* We might get this VM-exit if the nested-guest is not intercepting MOV DRx accesses. */
15447 if (!pVmxTransient->fIsNestedGuest)
15448 {
15449 /* We should -not- get this VM-exit if the guest's debug registers were active. */
15450 if (pVmxTransient->fWasGuestDebugStateActive)
15451 {
15452 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
15453 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15454 }
15455
15456 if ( !pVCpu->hm.s.fSingleInstruction
15457 && !pVmxTransient->fWasHyperDebugStateActive)
15458 {
15459 Assert(!DBGFIsStepping(pVCpu));
15460 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
15461
15462 /* Don't intercept MOV DRx any more. */
15463 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
15464 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15465 AssertRC(rc);
15466
15467 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
15468 VMMRZCallRing3Disable(pVCpu);
15469 HM_DISABLE_PREEMPT(pVCpu);
15470
15471 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
15472 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
15473 Assert(CPUMIsGuestDebugStateActive(pVCpu));
15474
15475 HM_RESTORE_PREEMPT();
15476 VMMRZCallRing3Enable(pVCpu);
15477
15478#ifdef VBOX_WITH_STATISTICS
15479 hmR0VmxReadExitQualVmcs(pVmxTransient);
15480 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15481 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15482 else
15483 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15484#endif
15485 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
15486 return VINF_SUCCESS;
15487 }
15488 }
15489
15490 /*
15491 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
15492 * The EFER MSR is always up-to-date.
15493 * Update the segment registers and DR7 from the CPU.
15494 */
15495 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15496 hmR0VmxReadExitQualVmcs(pVmxTransient);
15497 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
15498 AssertRCReturn(rc, rc);
15499 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
15500
15501 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15502 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15503 {
15504 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15505 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
15506 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
15507 if (RT_SUCCESS(rc))
15508 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
15509 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15510 }
15511 else
15512 {
15513 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15514 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
15515 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
15516 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15517 }
15518
15519 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
15520 if (RT_SUCCESS(rc))
15521 {
15522 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15523 AssertRCReturn(rc2, rc2);
15524 return VINF_SUCCESS;
15525 }
15526 return rc;
15527}
15528
15529
15530/**
15531 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
15532 * Conditional VM-exit.
15533 */
15534HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15535{
15536 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15537 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
15538
15539 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15540 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15541 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15542 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15543 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15544
15545 /*
15546 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15547 */
15548 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15549 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15550 {
15551 /*
15552 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
15553 * instruction emulation to inject the original event. Otherwise, injecting the original event
15554 * using hardware-assisted VMX would would trigger the same EPT misconfig VM-exit again.
15555 */
15556 if (!pVCpu->hm.s.Event.fPending)
15557 { /* likely */ }
15558 else
15559 {
15560 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15561#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
15562 /** @todo NSTVMX: Think about how this should be handled. */
15563 if (pVmxTransient->fIsNestedGuest)
15564 return VERR_VMX_IPE_3;
15565#endif
15566 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15567 }
15568 }
15569 else
15570 {
15571 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15572 return rcStrict;
15573 }
15574
15575 /*
15576 * Get sufficent state and update the exit history entry.
15577 */
15578 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15579 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
15580 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15581 AssertRCReturn(rc, rc);
15582
15583 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
15584 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15585 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
15586 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15587 if (!pExitRec)
15588 {
15589 /*
15590 * If we succeed, resume guest execution.
15591 * If we fail in interpreting the instruction because we couldn't get the guest physical address
15592 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
15593 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
15594 * weird case. See @bugref{6043}.
15595 */
15596 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15597 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15598 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
15599 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
15600 if ( rcStrict == VINF_SUCCESS
15601 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15602 || rcStrict == VERR_PAGE_NOT_PRESENT)
15603 {
15604 /* Successfully handled MMIO operation. */
15605 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15606 | HM_CHANGED_GUEST_APIC_TPR);
15607 rcStrict = VINF_SUCCESS;
15608 }
15609 }
15610 else
15611 {
15612 /*
15613 * Frequent exit or something needing probing. Call EMHistoryExec.
15614 */
15615 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
15616 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
15617
15618 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15619 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15620
15621 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15622 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15623 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15624 }
15625 return rcStrict;
15626}
15627
15628
15629/**
15630 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
15631 * VM-exit.
15632 */
15633HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15634{
15635 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15636 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
15637
15638 hmR0VmxReadExitQualVmcs(pVmxTransient);
15639 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15640 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15641 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15642 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15643 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15644
15645 /*
15646 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15647 */
15648 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15649 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15650 {
15651 /*
15652 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
15653 * we shall resolve the nested #PF and re-inject the original event.
15654 */
15655 if (pVCpu->hm.s.Event.fPending)
15656 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
15657 }
15658 else
15659 {
15660 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15661 return rcStrict;
15662 }
15663
15664 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15665 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
15666 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15667 AssertRCReturn(rc, rc);
15668
15669 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
15670 uint64_t const uExitQual = pVmxTransient->uExitQual;
15671 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", uExitQual));
15672
15673 RTGCUINT uErrorCode = 0;
15674 if (uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
15675 uErrorCode |= X86_TRAP_PF_ID;
15676 if (uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
15677 uErrorCode |= X86_TRAP_PF_RW;
15678 if (uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
15679 uErrorCode |= X86_TRAP_PF_P;
15680
15681 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15682 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15683 Log4Func(("at %#RX64 (%#RX64 errcode=%#x) cs:rip=%#04x:%#RX64\n", GCPhys, uExitQual, uErrorCode, pCtx->cs.Sel, pCtx->rip));
15684
15685 /*
15686 * Handle the pagefault trap for the nested shadow table.
15687 */
15688 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
15689 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
15690 TRPMResetTrap(pVCpu);
15691
15692 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
15693 if ( rcStrict == VINF_SUCCESS
15694 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15695 || rcStrict == VERR_PAGE_NOT_PRESENT)
15696 {
15697 /* Successfully synced our nested page tables. */
15698 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
15699 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
15700 return VINF_SUCCESS;
15701 }
15702
15703 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15704 return rcStrict;
15705}
15706
15707
15708#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
15709/**
15710 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
15711 */
15712HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15713{
15714 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15715
15716 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15717 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15718 hmR0VmxReadExitQualVmcs(pVmxTransient);
15719 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15720 | CPUMCTX_EXTRN_HWVIRT
15721 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15722 AssertRCReturn(rc, rc);
15723
15724 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15725
15726 VMXVEXITINFO ExitInfo;
15727 RT_ZERO(ExitInfo);
15728 ExitInfo.uReason = pVmxTransient->uExitReason;
15729 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15730 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15731 ExitInfo.cbInstr = pVmxTransient->cbInstr;
15732 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15733
15734 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
15735 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15736 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15737 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15738 {
15739 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15740 rcStrict = VINF_SUCCESS;
15741 }
15742 return rcStrict;
15743}
15744
15745
15746/**
15747 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
15748 */
15749HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15750{
15751 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15752
15753 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
15754 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
15755 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15756 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15757 AssertRCReturn(rc, rc);
15758
15759 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15760
15761 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
15762 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbInstr, VMXINSTRID_VMLAUNCH);
15763 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
15764 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15765 {
15766 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15767 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
15768 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
15769 }
15770 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15771 return rcStrict;
15772}
15773
15774
15775/**
15776 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
15777 */
15778HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15779{
15780 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15781
15782 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15783 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15784 hmR0VmxReadExitQualVmcs(pVmxTransient);
15785 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15786 | CPUMCTX_EXTRN_HWVIRT
15787 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15788 AssertRCReturn(rc, rc);
15789
15790 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15791
15792 VMXVEXITINFO ExitInfo;
15793 RT_ZERO(ExitInfo);
15794 ExitInfo.uReason = pVmxTransient->uExitReason;
15795 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15796 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15797 ExitInfo.cbInstr = pVmxTransient->cbInstr;
15798 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15799
15800 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
15801 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15802 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15803 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15804 {
15805 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15806 rcStrict = VINF_SUCCESS;
15807 }
15808 return rcStrict;
15809}
15810
15811
15812/**
15813 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
15814 */
15815HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15816{
15817 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15818
15819 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15820 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15821 hmR0VmxReadExitQualVmcs(pVmxTransient);
15822 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15823 | CPUMCTX_EXTRN_HWVIRT
15824 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15825 AssertRCReturn(rc, rc);
15826
15827 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15828
15829 VMXVEXITINFO ExitInfo;
15830 RT_ZERO(ExitInfo);
15831 ExitInfo.uReason = pVmxTransient->uExitReason;
15832 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15833 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15834 ExitInfo.cbInstr = pVmxTransient->cbInstr;
15835 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
15836
15837 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
15838 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15839 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15840 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15841 {
15842 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15843 rcStrict = VINF_SUCCESS;
15844 }
15845 return rcStrict;
15846}
15847
15848
15849/**
15850 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
15851 */
15852HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15853{
15854 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15855
15856 /*
15857 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
15858 * thus might not need to import the shadow VMCS state, it's safer just in case
15859 * code elsewhere dares look at unsynced VMCS fields.
15860 */
15861 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15862 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15863 hmR0VmxReadExitQualVmcs(pVmxTransient);
15864 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15865 | CPUMCTX_EXTRN_HWVIRT
15866 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15867 AssertRCReturn(rc, rc);
15868
15869 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15870
15871 VMXVEXITINFO ExitInfo;
15872 RT_ZERO(ExitInfo);
15873 ExitInfo.uReason = pVmxTransient->uExitReason;
15874 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15875 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15876 ExitInfo.cbInstr = pVmxTransient->cbInstr;
15877 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
15878 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
15879
15880 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
15881 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15882 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15883 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15884 {
15885 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15886 rcStrict = VINF_SUCCESS;
15887 }
15888 return rcStrict;
15889}
15890
15891
15892/**
15893 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
15894 */
15895HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15896{
15897 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15898
15899 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
15900 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
15901 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15902 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15903 AssertRCReturn(rc, rc);
15904
15905 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15906
15907 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
15908 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbInstr, VMXINSTRID_VMRESUME);
15909 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
15910 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15911 {
15912 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15913 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
15914 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
15915 }
15916 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15917 return rcStrict;
15918}
15919
15920
15921/**
15922 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
15923 */
15924HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15925{
15926 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15927
15928 /*
15929 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
15930 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
15931 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
15932 */
15933 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15934 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15935 hmR0VmxReadExitQualVmcs(pVmxTransient);
15936 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15937 | CPUMCTX_EXTRN_HWVIRT
15938 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15939 AssertRCReturn(rc, rc);
15940
15941 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15942
15943 VMXVEXITINFO ExitInfo;
15944 RT_ZERO(ExitInfo);
15945 ExitInfo.uReason = pVmxTransient->uExitReason;
15946 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15947 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15948 ExitInfo.cbInstr = pVmxTransient->cbInstr;
15949 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
15950 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15951
15952 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
15953 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15954 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15955 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15956 {
15957 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15958 rcStrict = VINF_SUCCESS;
15959 }
15960 return rcStrict;
15961}
15962
15963
15964/**
15965 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
15966 */
15967HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15968{
15969 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15970
15971 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15972 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
15973 | CPUMCTX_EXTRN_HWVIRT
15974 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
15975 AssertRCReturn(rc, rc);
15976
15977 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15978
15979 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbInstr);
15980 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15981 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
15982 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15983 {
15984 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15985 rcStrict = VINF_SUCCESS;
15986 }
15987 return rcStrict;
15988}
15989
15990
15991/**
15992 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
15993 */
15994HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15995{
15996 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15997
15998 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15999 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16000 hmR0VmxReadExitQualVmcs(pVmxTransient);
16001 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16002 | CPUMCTX_EXTRN_HWVIRT
16003 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16004 AssertRCReturn(rc, rc);
16005
16006 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16007
16008 VMXVEXITINFO ExitInfo;
16009 RT_ZERO(ExitInfo);
16010 ExitInfo.uReason = pVmxTransient->uExitReason;
16011 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16012 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16013 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16014 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16015
16016 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16017 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16018 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16019 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16020 {
16021 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16022 rcStrict = VINF_SUCCESS;
16023 }
16024 return rcStrict;
16025}
16026
16027
16028/**
16029 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16030 */
16031HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16032{
16033 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16034
16035 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16036 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16037 hmR0VmxReadExitQualVmcs(pVmxTransient);
16038 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16039 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16040 AssertRCReturn(rc, rc);
16041
16042 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16043
16044 VMXVEXITINFO ExitInfo;
16045 RT_ZERO(ExitInfo);
16046 ExitInfo.uReason = pVmxTransient->uExitReason;
16047 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16048 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16049 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16050 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16051
16052 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16053 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16054 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16055 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16056 {
16057 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16058 rcStrict = VINF_SUCCESS;
16059 }
16060 return rcStrict;
16061}
16062#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16063/** @} */
16064
16065
16066#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16067/** @name Nested-guest VM-exit handlers.
16068 * @{
16069 */
16070/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16071/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16072/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16073
16074/**
16075 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
16076 * Conditional VM-exit.
16077 */
16078HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16079{
16080 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16081
16082 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16083
16084 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
16085 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
16086 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
16087
16088 switch (uExitIntType)
16089 {
16090 /*
16091 * Physical NMIs:
16092 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
16093 */
16094 case VMX_EXIT_INT_INFO_TYPE_NMI:
16095 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
16096
16097 /*
16098 * Hardware exceptions,
16099 * Software exceptions,
16100 * Privileged software exceptions:
16101 * Figure out if the exception must be delivered to the guest or the nested-guest.
16102 */
16103 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
16104 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
16105 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
16106 {
16107 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16108 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16109 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16110 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16111
16112 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16113 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pVCpu, pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
16114 pVmxTransient->uExitIntErrorCode);
16115 if (fIntercept)
16116 {
16117 /* Exit qualification is required for debug and page-fault exceptions. */
16118 hmR0VmxReadExitQualVmcs(pVmxTransient);
16119
16120 /*
16121 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
16122 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
16123 * length. However, if delivery of a software interrupt, software exception or privileged
16124 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
16125 */
16126 VMXVEXITINFO ExitInfo;
16127 RT_ZERO(ExitInfo);
16128 ExitInfo.uReason = pVmxTransient->uExitReason;
16129 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16130 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16131
16132 VMXVEXITEVENTINFO ExitEventInfo;
16133 RT_ZERO(ExitEventInfo);
16134 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
16135 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
16136 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16137 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16138
16139#ifdef DEBUG_ramshankar
16140 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16141 Log4Func(("exit_int_info=%#x err_code=%#x exit_qual=%#RX64\n", pVmxTransient->uExitIntInfo,
16142 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual));
16143 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16144 {
16145 Log4Func(("idt_info=%#RX32 idt_errcode=%#RX32 cr2=%#RX64\n", pVmxTransient->uIdtVectoringInfo,
16146 pVmxTransient->uIdtVectoringErrorCode, pCtx->cr2));
16147 }
16148
16149 /* DOS VM debugging (IRET). */
16150 hmR0DumpRegs(pVCpu, HM_DUMP_REG_FLAGS_GPRS);
16151 uint8_t abStack[64];
16152 int rc = PGMPhysSimpleReadGCPtr(pVCpu, &abStack[0], pCtx->esp, sizeof(abStack));
16153 if (RT_SUCCESS(rc))
16154 Log(("StackMem: %.*Rhxs\n", sizeof(abStack), abStack));
16155#endif
16156 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
16157 }
16158
16159 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs in hmR0VmxExitXcptPF. */
16160 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16161 return hmR0VmxExitXcpt(pVCpu, pVmxTransient);
16162 }
16163
16164 /*
16165 * Software interrupts:
16166 * VM-exits cannot be caused by software interrupts.
16167 *
16168 * External interrupts:
16169 * This should only happen when "acknowledge external interrupts on VM-exit"
16170 * control is set. However, we never set this when executing a guest or
16171 * nested-guest. For nested-guests it is emulated while injecting interrupts into
16172 * the guest.
16173 */
16174 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
16175 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
16176 default:
16177 {
16178 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
16179 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
16180 }
16181 }
16182}
16183
16184
16185/**
16186 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
16187 * Unconditional VM-exit.
16188 */
16189HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16190{
16191 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16192 return IEMExecVmxVmexitTripleFault(pVCpu);
16193}
16194
16195
16196/**
16197 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
16198 */
16199HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16200{
16201 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16202
16203 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
16204 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16205 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16206}
16207
16208
16209/**
16210 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
16211 */
16212HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16213{
16214 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16215
16216 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
16217 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16218 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16219}
16220
16221
16222/**
16223 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
16224 * Unconditional VM-exit.
16225 */
16226HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16227{
16228 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16229
16230 hmR0VmxReadExitQualVmcs(pVmxTransient);
16231 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16232 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16233 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16234
16235 VMXVEXITINFO ExitInfo;
16236 RT_ZERO(ExitInfo);
16237 ExitInfo.uReason = pVmxTransient->uExitReason;
16238 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16239 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16240
16241 VMXVEXITEVENTINFO ExitEventInfo;
16242 RT_ZERO(ExitEventInfo);
16243 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16244 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16245 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
16246}
16247
16248
16249/**
16250 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
16251 */
16252HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16253{
16254 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16255
16256 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
16257 {
16258 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16259 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16260 }
16261 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
16262}
16263
16264
16265/**
16266 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
16267 */
16268HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16269{
16270 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16271
16272 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16273 {
16274 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16275 hmR0VmxReadExitQualVmcs(pVmxTransient);
16276
16277 VMXVEXITINFO ExitInfo;
16278 RT_ZERO(ExitInfo);
16279 ExitInfo.uReason = pVmxTransient->uExitReason;
16280 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16281 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16282 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16283 }
16284 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
16285}
16286
16287
16288/**
16289 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
16290 */
16291HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16292{
16293 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16294
16295 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
16296 {
16297 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16298 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16299 }
16300 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
16301}
16302
16303
16304/**
16305 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
16306 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
16307 */
16308HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16309{
16310 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16311
16312 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
16313 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
16314
16315 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16316
16317 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
16318 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16319 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16320
16321 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
16322 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
16323 u64VmcsField &= UINT64_C(0xffffffff);
16324
16325 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
16326 {
16327 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16328 hmR0VmxReadExitQualVmcs(pVmxTransient);
16329
16330 VMXVEXITINFO ExitInfo;
16331 RT_ZERO(ExitInfo);
16332 ExitInfo.uReason = pVmxTransient->uExitReason;
16333 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16334 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16335 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16336 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16337 }
16338
16339 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
16340 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
16341 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
16342}
16343
16344
16345/**
16346 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
16347 */
16348HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16349{
16350 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16351
16352 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16353 {
16354 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16355 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16356 }
16357
16358 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
16359}
16360
16361
16362/**
16363 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
16364 * Conditional VM-exit.
16365 */
16366HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16367{
16368 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16369
16370 hmR0VmxReadExitQualVmcs(pVmxTransient);
16371 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16372
16373 VBOXSTRICTRC rcStrict;
16374 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
16375 switch (uAccessType)
16376 {
16377 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
16378 {
16379 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16380 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16381 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16382 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16383
16384 bool fIntercept;
16385 switch (iCrReg)
16386 {
16387 case 0:
16388 case 4:
16389 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(pVCpu, &pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
16390 break;
16391
16392 case 3:
16393 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
16394 break;
16395
16396 case 8:
16397 fIntercept = CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
16398 break;
16399
16400 default:
16401 fIntercept = false;
16402 break;
16403 }
16404 if (fIntercept)
16405 {
16406 VMXVEXITINFO ExitInfo;
16407 RT_ZERO(ExitInfo);
16408 ExitInfo.uReason = pVmxTransient->uExitReason;
16409 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16410 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16411 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16412 }
16413 else
16414 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
16415 break;
16416 }
16417
16418 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
16419 {
16420 /*
16421 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
16422 * CR2 reads do not cause a VM-exit.
16423 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
16424 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
16425 */
16426 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16427 if ( iCrReg == 3
16428 || iCrReg == 8)
16429 {
16430 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
16431 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
16432 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
16433 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uIntercept))
16434 {
16435 VMXVEXITINFO ExitInfo;
16436 RT_ZERO(ExitInfo);
16437 ExitInfo.uReason = pVmxTransient->uExitReason;
16438 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16439 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16440 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16441 }
16442 else
16443 {
16444 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16445 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
16446 }
16447 }
16448 else
16449 {
16450 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
16451 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
16452 }
16453 break;
16454 }
16455
16456 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
16457 {
16458 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
16459 Assert(pVmcsNstGst);
16460 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
16461 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
16462 if ( (uGstHostMask & X86_CR0_TS)
16463 && (uReadShadow & X86_CR0_TS))
16464 {
16465 VMXVEXITINFO ExitInfo;
16466 RT_ZERO(ExitInfo);
16467 ExitInfo.uReason = pVmxTransient->uExitReason;
16468 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16469 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16470 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16471 }
16472 else
16473 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr);
16474 break;
16475 }
16476
16477 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
16478 {
16479 RTGCPTR GCPtrEffDst;
16480 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
16481 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
16482 if (fMemOperand)
16483 {
16484 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
16485 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
16486 }
16487 else
16488 GCPtrEffDst = NIL_RTGCPTR;
16489
16490 if (CPUMIsGuestVmxLmswInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, uNewMsw))
16491 {
16492 VMXVEXITINFO ExitInfo;
16493 RT_ZERO(ExitInfo);
16494 ExitInfo.uReason = pVmxTransient->uExitReason;
16495 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16496 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
16497 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16498 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16499 }
16500 else
16501 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, uNewMsw, GCPtrEffDst);
16502 break;
16503 }
16504
16505 default:
16506 {
16507 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
16508 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
16509 }
16510 }
16511
16512 if (rcStrict == VINF_IEM_RAISED_XCPT)
16513 {
16514 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16515 rcStrict = VINF_SUCCESS;
16516 }
16517 return rcStrict;
16518}
16519
16520
16521/**
16522 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
16523 * Conditional VM-exit.
16524 */
16525HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16526{
16527 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16528
16529 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
16530 {
16531 hmR0VmxReadExitQualVmcs(pVmxTransient);
16532 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16533
16534 VMXVEXITINFO ExitInfo;
16535 RT_ZERO(ExitInfo);
16536 ExitInfo.uReason = pVmxTransient->uExitReason;
16537 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16538 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16539 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16540 }
16541 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
16542}
16543
16544
16545/**
16546 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
16547 * Conditional VM-exit.
16548 */
16549HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16550{
16551 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16552
16553 hmR0VmxReadExitQualVmcs(pVmxTransient);
16554
16555 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
16556 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
16557 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
16558
16559 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
16560 uint8_t const cbAccess = s_aIOSizes[uIOSize];
16561 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
16562 {
16563 /*
16564 * IN/OUT instruction:
16565 * - Provides VM-exit instruction length.
16566 *
16567 * INS/OUTS instruction:
16568 * - Provides VM-exit instruction length.
16569 * - Provides Guest-linear address.
16570 * - Optionally provides VM-exit instruction info (depends on CPU feature).
16571 */
16572 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16573 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16574
16575 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
16576 pVmxTransient->ExitInstrInfo.u = 0;
16577 pVmxTransient->uGuestLinearAddr = 0;
16578
16579 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
16580 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
16581 if (fIOString)
16582 {
16583 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
16584 if (fVmxInsOutsInfo)
16585 {
16586 Assert(RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
16587 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16588 }
16589 }
16590
16591 VMXVEXITINFO ExitInfo;
16592 RT_ZERO(ExitInfo);
16593 ExitInfo.uReason = pVmxTransient->uExitReason;
16594 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16595 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16596 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16597 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
16598 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16599 }
16600 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
16601}
16602
16603
16604/**
16605 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
16606 */
16607HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16608{
16609 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16610
16611 uint32_t fMsrpm;
16612 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
16613 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
16614 else
16615 fMsrpm = VMXMSRPM_EXIT_RD;
16616
16617 if (fMsrpm & VMXMSRPM_EXIT_RD)
16618 {
16619 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16620 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16621 }
16622 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
16623}
16624
16625
16626/**
16627 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
16628 */
16629HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16630{
16631 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16632
16633 uint32_t fMsrpm;
16634 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
16635 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
16636 else
16637 fMsrpm = VMXMSRPM_EXIT_WR;
16638
16639 if (fMsrpm & VMXMSRPM_EXIT_WR)
16640 {
16641 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16642 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16643 }
16644 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
16645}
16646
16647
16648/**
16649 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
16650 */
16651HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16652{
16653 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16654
16655 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
16656 {
16657 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16658 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16659 }
16660 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
16661}
16662
16663
16664/**
16665 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
16666 * VM-exit.
16667 */
16668HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16669{
16670 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16671
16672 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
16673 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16674}
16675
16676
16677/**
16678 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
16679 */
16680HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16681{
16682 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16683
16684 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
16685 {
16686 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16687 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16688 }
16689 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
16690}
16691
16692
16693/**
16694 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
16695 */
16696HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16697{
16698 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16699
16700 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
16701 * PAUSE when executing a nested-guest? If it does not, we would not need
16702 * to check for the intercepts here. Just call VM-exit... */
16703
16704 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
16705 if ( CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
16706 || CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
16707 {
16708 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16709 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16710 }
16711 return hmR0VmxExitPause(pVCpu, pVmxTransient);
16712}
16713
16714
16715/**
16716 * Nested-guest VM-exit handler for when the TPR value is lowered below the
16717 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
16718 */
16719HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16720{
16721 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16722
16723 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
16724 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16725 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
16726}
16727
16728
16729/**
16730 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
16731 * VM-exit.
16732 */
16733HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16734{
16735 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16736
16737 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16738 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16739 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16740 hmR0VmxReadExitQualVmcs(pVmxTransient);
16741
16742 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
16743
16744 Log4Func(("at offset %#x type=%u\n", VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual),
16745 VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual)));
16746
16747 VMXVEXITINFO ExitInfo;
16748 RT_ZERO(ExitInfo);
16749 ExitInfo.uReason = pVmxTransient->uExitReason;
16750 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16751 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16752
16753 VMXVEXITEVENTINFO ExitEventInfo;
16754 RT_ZERO(ExitEventInfo);
16755 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16756 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16757 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
16758}
16759
16760
16761/**
16762 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
16763 * Conditional VM-exit.
16764 */
16765HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16766{
16767 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16768
16769 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
16770 hmR0VmxReadExitQualVmcs(pVmxTransient);
16771 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
16772}
16773
16774
16775/**
16776 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
16777 * Conditional VM-exit.
16778 */
16779HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16780{
16781 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16782
16783 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
16784 hmR0VmxReadExitQualVmcs(pVmxTransient);
16785 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
16786}
16787
16788
16789/**
16790 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
16791 */
16792HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16793{
16794 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16795
16796 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16797 {
16798 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
16799 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16800 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16801 }
16802 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
16803}
16804
16805
16806/**
16807 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
16808 */
16809HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16810{
16811 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16812
16813 if (CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
16814 {
16815 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16816 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16817 }
16818 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
16819}
16820
16821
16822/**
16823 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
16824 */
16825HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16826{
16827 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16828
16829 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16830 {
16831 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
16832 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16833 hmR0VmxReadExitQualVmcs(pVmxTransient);
16834 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16835
16836 VMXVEXITINFO ExitInfo;
16837 RT_ZERO(ExitInfo);
16838 ExitInfo.uReason = pVmxTransient->uExitReason;
16839 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16840 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16841 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16842 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16843 }
16844 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
16845}
16846
16847
16848/**
16849 * Nested-guest VM-exit handler for invalid-guest state
16850 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
16851 */
16852HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16853{
16854 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16855
16856 /*
16857 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
16858 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
16859 * Handle it like it's in an invalid guest state of the outer guest.
16860 *
16861 * When the fast path is implemented, this should be changed to cause the corresponding
16862 * nested-guest VM-exit.
16863 */
16864 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
16865}
16866
16867
16868/**
16869 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
16870 * and only provide the instruction length.
16871 *
16872 * Unconditional VM-exit.
16873 */
16874HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16875{
16876 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16877
16878#ifdef VBOX_STRICT
16879 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16880 switch (pVmxTransient->uExitReason)
16881 {
16882 case VMX_EXIT_ENCLS:
16883 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
16884 break;
16885
16886 case VMX_EXIT_VMFUNC:
16887 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_VMFUNC));
16888 break;
16889 }
16890#endif
16891
16892 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16893 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16894}
16895
16896
16897/**
16898 * Nested-guest VM-exit handler for instructions that provide instruction length as
16899 * well as more information.
16900 *
16901 * Unconditional VM-exit.
16902 */
16903HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16904{
16905 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16906
16907#ifdef VBOX_STRICT
16908 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16909 switch (pVmxTransient->uExitReason)
16910 {
16911 case VMX_EXIT_GDTR_IDTR_ACCESS:
16912 case VMX_EXIT_LDTR_TR_ACCESS:
16913 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
16914 break;
16915
16916 case VMX_EXIT_RDRAND:
16917 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
16918 break;
16919
16920 case VMX_EXIT_RDSEED:
16921 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
16922 break;
16923
16924 case VMX_EXIT_XSAVES:
16925 case VMX_EXIT_XRSTORS:
16926 /** @todo NSTVMX: Verify XSS-bitmap. */
16927 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
16928 break;
16929
16930 case VMX_EXIT_UMWAIT:
16931 case VMX_EXIT_TPAUSE:
16932 Assert(CPUMIsGuestVmxProcCtlsSet(pVCpu, pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
16933 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
16934 break;
16935 }
16936#endif
16937
16938 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16939 hmR0VmxReadExitQualVmcs(pVmxTransient);
16940 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16941
16942 VMXVEXITINFO ExitInfo;
16943 RT_ZERO(ExitInfo);
16944 ExitInfo.uReason = pVmxTransient->uExitReason;
16945 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16946 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16947 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16948 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16949}
16950
16951/** @} */
16952#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16953
Note: See TracBrowser for help on using the repository browser.

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