VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/HM.cpp@ 73269

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

PGM,HM: Made PGMR3ChangeMode work in ring-0 too. This required a kludge for the VT-x real-in-V86-mode stuff, as there are certain limitations on that mode which weren't checked as CR0.PE was cleared. The kludge isn't very smart, but it seems to do the job. Similar kludge for getting out of the mode. bugref:9044

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 169.3 KB
Line 
1/* $Id: HM.cpp 73266 2018-07-20 14:27:20Z vboxsync $ */
2/** @file
3 * HM - Intel/AMD VM Hardware Support Manager.
4 */
5
6/*
7 * Copyright (C) 2006-2017 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/** @page pg_hm HM - Hardware Assisted Virtualization Manager
19 *
20 * The HM manages guest execution using the VT-x and AMD-V CPU hardware
21 * extensions.
22 *
23 * {summary of what HM does}
24 *
25 * Hardware assisted virtualization manager was originally abbreviated HWACCM,
26 * however that was cumbersome to write and parse for such a central component,
27 * so it was shortened to HM when refactoring the code in the 4.3 development
28 * cycle.
29 *
30 * {add sections with more details}
31 *
32 * @sa @ref grp_hm
33 */
34
35
36/*********************************************************************************************************************************
37* Header Files *
38*********************************************************************************************************************************/
39#define LOG_GROUP LOG_GROUP_HM
40#define VMCPU_INCL_CPUM_GST_CTX
41#include <VBox/vmm/cpum.h>
42#include <VBox/vmm/stam.h>
43#include <VBox/vmm/mm.h>
44#include <VBox/vmm/pdmapi.h>
45#include <VBox/vmm/pgm.h>
46#include <VBox/vmm/ssm.h>
47#include <VBox/vmm/trpm.h>
48#include <VBox/vmm/dbgf.h>
49#include <VBox/vmm/iom.h>
50#include <VBox/vmm/iem.h>
51#include <VBox/vmm/patm.h>
52#include <VBox/vmm/csam.h>
53#include <VBox/vmm/selm.h>
54#include <VBox/vmm/nem.h>
55#ifdef VBOX_WITH_REM
56# include <VBox/vmm/rem.h>
57#endif
58#include <VBox/vmm/hm_vmx.h>
59#include <VBox/vmm/hm_svm.h>
60#include "HMInternal.h"
61#include <VBox/vmm/vm.h>
62#include <VBox/vmm/uvm.h>
63#include <VBox/err.h>
64#include <VBox/param.h>
65
66#include <iprt/assert.h>
67#include <VBox/log.h>
68#include <iprt/asm.h>
69#include <iprt/asm-amd64-x86.h>
70#include <iprt/env.h>
71#include <iprt/thread.h>
72
73
74/*********************************************************************************************************************************
75* Global Variables *
76*********************************************************************************************************************************/
77#define EXIT_REASON(def, val, str) #def " - " #val " - " str
78#define EXIT_REASON_NIL() NULL
79/** Exit reason descriptions for VT-x, used to describe statistics. */
80static const char * const g_apszVTxExitReasons[MAX_EXITREASON_STAT] =
81{
82 EXIT_REASON(VMX_EXIT_XCPT_OR_NMI , 0, "Exception or non-maskable interrupt (NMI)."),
83 EXIT_REASON(VMX_EXIT_EXT_INT , 1, "External interrupt."),
84 EXIT_REASON(VMX_EXIT_TRIPLE_FAULT , 2, "Triple fault."),
85 EXIT_REASON(VMX_EXIT_INIT_SIGNAL , 3, "INIT signal."),
86 EXIT_REASON(VMX_EXIT_SIPI , 4, "Start-up IPI (SIPI)."),
87 EXIT_REASON(VMX_EXIT_IO_SMI_IRQ , 5, "I/O system-management interrupt (SMI)."),
88 EXIT_REASON(VMX_EXIT_SMI_IRQ , 6, "Other SMI."),
89 EXIT_REASON(VMX_EXIT_INT_WINDOW , 7, "Interrupt window."),
90 EXIT_REASON(VMX_EXIT_NMI_WINDOW , 8, "NMI window."),
91 EXIT_REASON(VMX_EXIT_TASK_SWITCH , 9, "Task switch."),
92 EXIT_REASON(VMX_EXIT_CPUID , 10, "CPUID instruction."),
93 EXIT_REASON(VMX_EXIT_GETSEC , 11, "GETSEC instrunction."),
94 EXIT_REASON(VMX_EXIT_HLT , 12, "HLT instruction."),
95 EXIT_REASON(VMX_EXIT_INVD , 13, "INVD instruction."),
96 EXIT_REASON(VMX_EXIT_INVLPG , 14, "INVLPG instruction."),
97 EXIT_REASON(VMX_EXIT_RDPMC , 15, "RDPMCinstruction."),
98 EXIT_REASON(VMX_EXIT_RDTSC , 16, "RDTSC instruction."),
99 EXIT_REASON(VMX_EXIT_RSM , 17, "RSM instruction in SMM."),
100 EXIT_REASON(VMX_EXIT_VMCALL , 18, "VMCALL instruction."),
101 EXIT_REASON(VMX_EXIT_VMCLEAR , 19, "VMCLEAR instruction."),
102 EXIT_REASON(VMX_EXIT_VMLAUNCH , 20, "VMLAUNCH instruction."),
103 EXIT_REASON(VMX_EXIT_VMPTRLD , 21, "VMPTRLD instruction."),
104 EXIT_REASON(VMX_EXIT_VMPTRST , 22, "VMPTRST instruction."),
105 EXIT_REASON(VMX_EXIT_VMREAD , 23, "VMREAD instruction."),
106 EXIT_REASON(VMX_EXIT_VMRESUME , 24, "VMRESUME instruction."),
107 EXIT_REASON(VMX_EXIT_VMWRITE , 25, "VMWRITE instruction."),
108 EXIT_REASON(VMX_EXIT_VMXOFF , 26, "VMXOFF instruction."),
109 EXIT_REASON(VMX_EXIT_VMXON , 27, "VMXON instruction."),
110 EXIT_REASON(VMX_EXIT_MOV_CRX , 28, "Control-register accesses."),
111 EXIT_REASON(VMX_EXIT_MOV_DRX , 29, "Debug-register accesses."),
112 EXIT_REASON(VMX_EXIT_PORT_IO , 30, "I/O instruction."),
113 EXIT_REASON(VMX_EXIT_RDMSR , 31, "RDMSR instruction."),
114 EXIT_REASON(VMX_EXIT_WRMSR , 32, "WRMSR instruction."),
115 EXIT_REASON(VMX_EXIT_ERR_INVALID_GUEST_STATE, 33, "VM-entry failure due to invalid guest state."),
116 EXIT_REASON(VMX_EXIT_ERR_MSR_LOAD , 34, "VM-entry failure due to MSR loading."),
117 EXIT_REASON_NIL(),
118 EXIT_REASON(VMX_EXIT_MWAIT , 36, "MWAIT instruction."),
119 EXIT_REASON(VMX_EXIT_MTF , 37, "Monitor Trap Flag."),
120 EXIT_REASON_NIL(),
121 EXIT_REASON(VMX_EXIT_MONITOR , 39, "MONITOR instruction."),
122 EXIT_REASON(VMX_EXIT_PAUSE , 40, "PAUSE instruction."),
123 EXIT_REASON(VMX_EXIT_ERR_MACHINE_CHECK , 41, "VM-entry failure due to machine-check."),
124 EXIT_REASON_NIL(),
125 EXIT_REASON(VMX_EXIT_TPR_BELOW_THRESHOLD , 43, "TPR below threshold (MOV to CR8)."),
126 EXIT_REASON(VMX_EXIT_APIC_ACCESS , 44, "APIC access."),
127 EXIT_REASON(VMX_EXIT_VIRTUALIZED_EOI , 45, "Virtualized EOI."),
128 EXIT_REASON(VMX_EXIT_XDTR_ACCESS , 46, "GDTR/IDTR access using LGDT/SGDT/LIDT/SIDT."),
129 EXIT_REASON(VMX_EXIT_TR_ACCESS , 47, "LDTR/TR access using LLDT/SLDT/LTR/STR."),
130 EXIT_REASON(VMX_EXIT_EPT_VIOLATION , 48, "EPT violation."),
131 EXIT_REASON(VMX_EXIT_EPT_MISCONFIG , 49, "EPT misconfiguration."),
132 EXIT_REASON(VMX_EXIT_INVEPT , 50, "INVEPT instruction."),
133 EXIT_REASON(VMX_EXIT_RDTSCP , 51, "RDTSCP instruction."),
134 EXIT_REASON(VMX_EXIT_PREEMPT_TIMER , 52, "VMX-preemption timer expired."),
135 EXIT_REASON(VMX_EXIT_INVVPID , 53, "INVVPID instruction."),
136 EXIT_REASON(VMX_EXIT_WBINVD , 54, "WBINVD instruction."),
137 EXIT_REASON(VMX_EXIT_XSETBV , 55, "XSETBV instruction."),
138 EXIT_REASON(VMX_EXIT_APIC_WRITE , 56, "APIC write completed to virtual-APIC page."),
139 EXIT_REASON(VMX_EXIT_RDRAND , 57, "RDRAND instruction."),
140 EXIT_REASON(VMX_EXIT_INVPCID , 58, "INVPCID instruction."),
141 EXIT_REASON(VMX_EXIT_VMFUNC , 59, "VMFUNC instruction."),
142 EXIT_REASON(VMX_EXIT_ENCLS , 60, "ENCLS instruction."),
143 EXIT_REASON(VMX_EXIT_RDSEED , 61, "RDSEED instruction."),
144 EXIT_REASON(VMX_EXIT_PML_FULL , 62, "Page-modification log full."),
145 EXIT_REASON(VMX_EXIT_XSAVES , 63, "XSAVES instruction."),
146 EXIT_REASON(VMX_EXIT_XRSTORS , 64, "XRSTORS instruction.")
147};
148/** Array index of the last valid VT-x exit reason. */
149#define MAX_EXITREASON_VTX 64
150
151/** A partial list of Exit reason descriptions for AMD-V, used to describe
152 * statistics.
153 *
154 * @note AMD-V have annoyingly large gaps (e.g. \#NPF VMEXIT comes at 1024),
155 * this array doesn't contain the entire set of exit reasons, we
156 * handle them via hmSvmGetSpecialExitReasonDesc(). */
157static const char * const g_apszAmdVExitReasons[MAX_EXITREASON_STAT] =
158{
159 EXIT_REASON(SVM_EXIT_READ_CR0 , 0, "Read CR0."),
160 EXIT_REASON(SVM_EXIT_READ_CR1 , 1, "Read CR1."),
161 EXIT_REASON(SVM_EXIT_READ_CR2 , 2, "Read CR2."),
162 EXIT_REASON(SVM_EXIT_READ_CR3 , 3, "Read CR3."),
163 EXIT_REASON(SVM_EXIT_READ_CR4 , 4, "Read CR4."),
164 EXIT_REASON(SVM_EXIT_READ_CR5 , 5, "Read CR5."),
165 EXIT_REASON(SVM_EXIT_READ_CR6 , 6, "Read CR6."),
166 EXIT_REASON(SVM_EXIT_READ_CR7 , 7, "Read CR7."),
167 EXIT_REASON(SVM_EXIT_READ_CR8 , 8, "Read CR8."),
168 EXIT_REASON(SVM_EXIT_READ_CR9 , 9, "Read CR9."),
169 EXIT_REASON(SVM_EXIT_READ_CR10 , 10, "Read CR10."),
170 EXIT_REASON(SVM_EXIT_READ_CR11 , 11, "Read CR11."),
171 EXIT_REASON(SVM_EXIT_READ_CR12 , 12, "Read CR12."),
172 EXIT_REASON(SVM_EXIT_READ_CR13 , 13, "Read CR13."),
173 EXIT_REASON(SVM_EXIT_READ_CR14 , 14, "Read CR14."),
174 EXIT_REASON(SVM_EXIT_READ_CR15 , 15, "Read CR15."),
175 EXIT_REASON(SVM_EXIT_WRITE_CR0 , 16, "Write CR0."),
176 EXIT_REASON(SVM_EXIT_WRITE_CR1 , 17, "Write CR1."),
177 EXIT_REASON(SVM_EXIT_WRITE_CR2 , 18, "Write CR2."),
178 EXIT_REASON(SVM_EXIT_WRITE_CR3 , 19, "Write CR3."),
179 EXIT_REASON(SVM_EXIT_WRITE_CR4 , 20, "Write CR4."),
180 EXIT_REASON(SVM_EXIT_WRITE_CR5 , 21, "Write CR5."),
181 EXIT_REASON(SVM_EXIT_WRITE_CR6 , 22, "Write CR6."),
182 EXIT_REASON(SVM_EXIT_WRITE_CR7 , 23, "Write CR7."),
183 EXIT_REASON(SVM_EXIT_WRITE_CR8 , 24, "Write CR8."),
184 EXIT_REASON(SVM_EXIT_WRITE_CR9 , 25, "Write CR9."),
185 EXIT_REASON(SVM_EXIT_WRITE_CR10 , 26, "Write CR10."),
186 EXIT_REASON(SVM_EXIT_WRITE_CR11 , 27, "Write CR11."),
187 EXIT_REASON(SVM_EXIT_WRITE_CR12 , 28, "Write CR12."),
188 EXIT_REASON(SVM_EXIT_WRITE_CR13 , 29, "Write CR13."),
189 EXIT_REASON(SVM_EXIT_WRITE_CR14 , 30, "Write CR14."),
190 EXIT_REASON(SVM_EXIT_WRITE_CR15 , 31, "Write CR15."),
191 EXIT_REASON(SVM_EXIT_READ_DR0 , 32, "Read DR0."),
192 EXIT_REASON(SVM_EXIT_READ_DR1 , 33, "Read DR1."),
193 EXIT_REASON(SVM_EXIT_READ_DR2 , 34, "Read DR2."),
194 EXIT_REASON(SVM_EXIT_READ_DR3 , 35, "Read DR3."),
195 EXIT_REASON(SVM_EXIT_READ_DR4 , 36, "Read DR4."),
196 EXIT_REASON(SVM_EXIT_READ_DR5 , 37, "Read DR5."),
197 EXIT_REASON(SVM_EXIT_READ_DR6 , 38, "Read DR6."),
198 EXIT_REASON(SVM_EXIT_READ_DR7 , 39, "Read DR7."),
199 EXIT_REASON(SVM_EXIT_READ_DR8 , 40, "Read DR8."),
200 EXIT_REASON(SVM_EXIT_READ_DR9 , 41, "Read DR9."),
201 EXIT_REASON(SVM_EXIT_READ_DR10 , 42, "Read DR10."),
202 EXIT_REASON(SVM_EXIT_READ_DR11 , 43, "Read DR11"),
203 EXIT_REASON(SVM_EXIT_READ_DR12 , 44, "Read DR12."),
204 EXIT_REASON(SVM_EXIT_READ_DR13 , 45, "Read DR13."),
205 EXIT_REASON(SVM_EXIT_READ_DR14 , 46, "Read DR14."),
206 EXIT_REASON(SVM_EXIT_READ_DR15 , 47, "Read DR15."),
207 EXIT_REASON(SVM_EXIT_WRITE_DR0 , 48, "Write DR0."),
208 EXIT_REASON(SVM_EXIT_WRITE_DR1 , 49, "Write DR1."),
209 EXIT_REASON(SVM_EXIT_WRITE_DR2 , 50, "Write DR2."),
210 EXIT_REASON(SVM_EXIT_WRITE_DR3 , 51, "Write DR3."),
211 EXIT_REASON(SVM_EXIT_WRITE_DR4 , 52, "Write DR4."),
212 EXIT_REASON(SVM_EXIT_WRITE_DR5 , 53, "Write DR5."),
213 EXIT_REASON(SVM_EXIT_WRITE_DR6 , 54, "Write DR6."),
214 EXIT_REASON(SVM_EXIT_WRITE_DR7 , 55, "Write DR7."),
215 EXIT_REASON(SVM_EXIT_WRITE_DR8 , 56, "Write DR8."),
216 EXIT_REASON(SVM_EXIT_WRITE_DR9 , 57, "Write DR9."),
217 EXIT_REASON(SVM_EXIT_WRITE_DR10 , 58, "Write DR10."),
218 EXIT_REASON(SVM_EXIT_WRITE_DR11 , 59, "Write DR11."),
219 EXIT_REASON(SVM_EXIT_WRITE_DR12 , 60, "Write DR12."),
220 EXIT_REASON(SVM_EXIT_WRITE_DR13 , 61, "Write DR13."),
221 EXIT_REASON(SVM_EXIT_WRITE_DR14 , 62, "Write DR14."),
222 EXIT_REASON(SVM_EXIT_WRITE_DR15 , 63, "Write DR15."),
223 EXIT_REASON(SVM_EXIT_XCPT_0 , 64, "Exception 0 (#DE)."),
224 EXIT_REASON(SVM_EXIT_XCPT_1 , 65, "Exception 1 (#DB)."),
225 EXIT_REASON(SVM_EXIT_XCPT_2 , 66, "Exception 2 (#NMI)."),
226 EXIT_REASON(SVM_EXIT_XCPT_3 , 67, "Exception 3 (#BP)."),
227 EXIT_REASON(SVM_EXIT_XCPT_4 , 68, "Exception 4 (#OF)."),
228 EXIT_REASON(SVM_EXIT_XCPT_5 , 69, "Exception 5 (#BR)."),
229 EXIT_REASON(SVM_EXIT_XCPT_6 , 70, "Exception 6 (#UD)."),
230 EXIT_REASON(SVM_EXIT_XCPT_7 , 71, "Exception 7 (#NM)."),
231 EXIT_REASON(SVM_EXIT_XCPT_8 , 72, "Exception 8 (#DF)."),
232 EXIT_REASON(SVM_EXIT_XCPT_9 , 73, "Exception 9 (#CO_SEG_OVERRUN)."),
233 EXIT_REASON(SVM_EXIT_XCPT_10 , 74, "Exception 10 (#TS)."),
234 EXIT_REASON(SVM_EXIT_XCPT_11 , 75, "Exception 11 (#NP)."),
235 EXIT_REASON(SVM_EXIT_XCPT_12 , 76, "Exception 12 (#SS)."),
236 EXIT_REASON(SVM_EXIT_XCPT_13 , 77, "Exception 13 (#GP)."),
237 EXIT_REASON(SVM_EXIT_XCPT_14 , 78, "Exception 14 (#PF)."),
238 EXIT_REASON(SVM_EXIT_XCPT_15 , 79, "Exception 15 (0x0f)."),
239 EXIT_REASON(SVM_EXIT_XCPT_16 , 80, "Exception 16 (#MF)."),
240 EXIT_REASON(SVM_EXIT_XCPT_17 , 81, "Exception 17 (#AC)."),
241 EXIT_REASON(SVM_EXIT_XCPT_18 , 82, "Exception 18 (#MC)."),
242 EXIT_REASON(SVM_EXIT_XCPT_19 , 83, "Exception 19 (#XF)."),
243 EXIT_REASON(SVM_EXIT_XCPT_20 , 84, "Exception 20 (#VE)."),
244 EXIT_REASON(SVM_EXIT_XCPT_21 , 85, "Exception 22 (0x15)."),
245 EXIT_REASON(SVM_EXIT_XCPT_22 , 86, "Exception 22 (0x16)."),
246 EXIT_REASON(SVM_EXIT_XCPT_23 , 87, "Exception 23 (0x17)."),
247 EXIT_REASON(SVM_EXIT_XCPT_24 , 88, "Exception 24 (0x18)."),
248 EXIT_REASON(SVM_EXIT_XCPT_25 , 89, "Exception 25 (0x19)."),
249 EXIT_REASON(SVM_EXIT_XCPT_26 , 90, "Exception 26 (0x1A)."),
250 EXIT_REASON(SVM_EXIT_XCPT_27 , 91, "Exception 27 (0x1B)."),
251 EXIT_REASON(SVM_EXIT_XCPT_28 , 92, "Exception 28 (0x1C)."),
252 EXIT_REASON(SVM_EXIT_XCPT_29 , 93, "Exception 29 (0x1D)."),
253 EXIT_REASON(SVM_EXIT_XCPT_30 , 94, "Exception 30 (#SX)."),
254 EXIT_REASON(SVM_EXIT_XCPT_31 , 95, "Exception 31 (0x1F)."),
255 EXIT_REASON(SVM_EXIT_INTR , 96, "Physical maskable interrupt (host)."),
256 EXIT_REASON(SVM_EXIT_NMI , 97, "Physical non-maskable interrupt (host)."),
257 EXIT_REASON(SVM_EXIT_SMI , 98, "System management interrupt (host)."),
258 EXIT_REASON(SVM_EXIT_INIT , 99, "Physical INIT signal (host)."),
259 EXIT_REASON(SVM_EXIT_VINTR , 100, "Virtual interrupt-window exit."),
260 EXIT_REASON(SVM_EXIT_CR0_SEL_WRITE, 101, "Selective CR0 Write (to bits other than CR0.TS and CR0.MP)."),
261 EXIT_REASON(SVM_EXIT_IDTR_READ , 102, "Read IDTR."),
262 EXIT_REASON(SVM_EXIT_GDTR_READ , 103, "Read GDTR."),
263 EXIT_REASON(SVM_EXIT_LDTR_READ , 104, "Read LDTR."),
264 EXIT_REASON(SVM_EXIT_TR_READ , 105, "Read TR."),
265 EXIT_REASON(SVM_EXIT_IDTR_WRITE , 106, "Write IDTR."),
266 EXIT_REASON(SVM_EXIT_GDTR_WRITE , 107, "Write GDTR."),
267 EXIT_REASON(SVM_EXIT_LDTR_WRITE , 108, "Write LDTR."),
268 EXIT_REASON(SVM_EXIT_TR_WRITE , 109, "Write TR."),
269 EXIT_REASON(SVM_EXIT_RDTSC , 110, "RDTSC instruction."),
270 EXIT_REASON(SVM_EXIT_RDPMC , 111, "RDPMC instruction."),
271 EXIT_REASON(SVM_EXIT_PUSHF , 112, "PUSHF instruction."),
272 EXIT_REASON(SVM_EXIT_POPF , 113, "POPF instruction."),
273 EXIT_REASON(SVM_EXIT_CPUID , 114, "CPUID instruction."),
274 EXIT_REASON(SVM_EXIT_RSM , 115, "RSM instruction."),
275 EXIT_REASON(SVM_EXIT_IRET , 116, "IRET instruction."),
276 EXIT_REASON(SVM_EXIT_SWINT , 117, "Software interrupt (INTn instructions)."),
277 EXIT_REASON(SVM_EXIT_INVD , 118, "INVD instruction."),
278 EXIT_REASON(SVM_EXIT_PAUSE , 119, "PAUSE instruction."),
279 EXIT_REASON(SVM_EXIT_HLT , 120, "HLT instruction."),
280 EXIT_REASON(SVM_EXIT_INVLPG , 121, "INVLPG instruction."),
281 EXIT_REASON(SVM_EXIT_INVLPGA , 122, "INVLPGA instruction."),
282 EXIT_REASON(SVM_EXIT_IOIO , 123, "IN/OUT/INS/OUTS instruction."),
283 EXIT_REASON(SVM_EXIT_MSR , 124, "RDMSR or WRMSR access to protected MSR."),
284 EXIT_REASON(SVM_EXIT_TASK_SWITCH , 125, "Task switch."),
285 EXIT_REASON(SVM_EXIT_FERR_FREEZE , 126, "FERR Freeze; CPU frozen in an x87/mmx instruction waiting for interrupt."),
286 EXIT_REASON(SVM_EXIT_SHUTDOWN , 127, "Shutdown."),
287 EXIT_REASON(SVM_EXIT_VMRUN , 128, "VMRUN instruction."),
288 EXIT_REASON(SVM_EXIT_VMMCALL , 129, "VMCALL instruction."),
289 EXIT_REASON(SVM_EXIT_VMLOAD , 130, "VMLOAD instruction."),
290 EXIT_REASON(SVM_EXIT_VMSAVE , 131, "VMSAVE instruction."),
291 EXIT_REASON(SVM_EXIT_STGI , 132, "STGI instruction."),
292 EXIT_REASON(SVM_EXIT_CLGI , 133, "CLGI instruction."),
293 EXIT_REASON(SVM_EXIT_SKINIT , 134, "SKINIT instruction."),
294 EXIT_REASON(SVM_EXIT_RDTSCP , 135, "RDTSCP instruction."),
295 EXIT_REASON(SVM_EXIT_ICEBP , 136, "ICEBP instruction."),
296 EXIT_REASON(SVM_EXIT_WBINVD , 137, "WBINVD instruction."),
297 EXIT_REASON(SVM_EXIT_MONITOR , 138, "MONITOR instruction."),
298 EXIT_REASON(SVM_EXIT_MWAIT , 139, "MWAIT instruction."),
299 EXIT_REASON(SVM_EXIT_MWAIT_ARMED , 140, "MWAIT instruction when armed."),
300 EXIT_REASON(SVM_EXIT_XSETBV , 141, "XSETBV instruction."),
301};
302/** Array index of the last valid AMD-V exit reason. */
303#define MAX_EXITREASON_AMDV 141
304
305/** Special exit reasons not covered in the array above. */
306#define SVM_EXIT_REASON_NPF EXIT_REASON(SVM_EXIT_NPF , 1024, "Nested Page Fault.")
307#define SVM_EXIT_REASON_AVIC_INCOMPLETE_IPI EXIT_REASON(SVM_EXIT_AVIC_INCOMPLETE_IPI, 1025, "AVIC - Incomplete IPI delivery.")
308#define SVM_EXIT_REASON_AVIC_NOACCEL EXIT_REASON(SVM_EXIT_AVIC_NOACCEL , 1026, "AVIC - Unhandled register.")
309
310/**
311 * Gets the SVM exit reason if it's one of the reasons not present in the @c
312 * g_apszAmdVExitReasons array.
313 *
314 * @returns The exit reason or NULL if unknown.
315 * @param uExit The exit.
316 */
317DECLINLINE(const char *) hmSvmGetSpecialExitReasonDesc(uint16_t uExit)
318{
319 switch (uExit)
320 {
321 case SVM_EXIT_NPF: return SVM_EXIT_REASON_NPF;
322 case SVM_EXIT_AVIC_INCOMPLETE_IPI: return SVM_EXIT_REASON_AVIC_INCOMPLETE_IPI;
323 case SVM_EXIT_AVIC_NOACCEL: return SVM_EXIT_REASON_AVIC_NOACCEL;
324 }
325 return EXIT_REASON_NIL();
326}
327#undef EXIT_REASON_NIL
328#undef EXIT_REASON
329
330/** @def HMVMX_REPORT_FEATURE
331 * Reports VT-x feature to the release log.
332 *
333 * @param allowed1 Mask of allowed feature bits.
334 * @param disallowed0 Mask of disallowed feature bits.
335 * @param strdesc The description string to report.
336 * @param featflag Mask of the feature to report.
337 */
338#define HMVMX_REPORT_FEATURE(allowed1, disallowed0, strdesc, featflag) \
339 do { \
340 if ((allowed1) & (featflag)) \
341 { \
342 if ((disallowed0) & (featflag)) \
343 LogRel(("HM: " strdesc " (must be set)\n")); \
344 else \
345 LogRel(("HM: " strdesc "\n")); \
346 } \
347 else \
348 LogRel(("HM: " strdesc " (must be cleared)\n")); \
349 } while (0)
350
351/** @def HMVMX_REPORT_ALLOWED_FEATURE
352 * Reports an allowed VT-x feature to the release log.
353 *
354 * @param allowed1 Mask of allowed feature bits.
355 * @param strdesc The description string to report.
356 * @param featflag Mask of the feature to report.
357 */
358#define HMVMX_REPORT_ALLOWED_FEATURE(allowed1, strdesc, featflag) \
359 do { \
360 if ((allowed1) & (featflag)) \
361 LogRel(("HM: " strdesc "\n")); \
362 else \
363 LogRel(("HM: " strdesc " not supported\n")); \
364 } while (0)
365
366/** @def HMVMX_REPORT_MSR_CAPABILITY
367 * Reports MSR feature capability.
368 *
369 * @param msrcaps Mask of MSR feature bits.
370 * @param strdesc The description string to report.
371 * @param cap Mask of the feature to report.
372 */
373#define HMVMX_REPORT_MSR_CAPABILITY(msrcaps, strdesc, cap) \
374 do { \
375 if ((msrcaps) & (cap)) \
376 LogRel(("HM: " strdesc "\n")); \
377 } while (0)
378
379/** @def HMVMX_LOGREL_FEAT
380 * Dumps a feature flag from a bitmap of features to the release log.
381 *
382 * @param a_fVal The value of all the features.
383 * @param a_fMask The specific bitmask of the feature.
384 */
385#define HMVMX_LOGREL_FEAT(a_fVal, a_fMask) \
386 do { \
387 if ((a_fVal) & (a_fMask)) \
388 LogRel(("HM: %s\n", #a_fMask)); \
389 } while (0)
390
391
392/*********************************************************************************************************************************
393* Internal Functions *
394*********************************************************************************************************************************/
395static DECLCALLBACK(int) hmR3Save(PVM pVM, PSSMHANDLE pSSM);
396static DECLCALLBACK(int) hmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
397static DECLCALLBACK(void) hmR3InfoSvmNstGstVmcbCache(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
398static DECLCALLBACK(void) hmR3Info(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
399static DECLCALLBACK(void) hmR3InfoEventPending(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
400static int hmR3InitCPU(PVM pVM);
401static int hmR3InitFinalizeR0(PVM pVM);
402static int hmR3InitFinalizeR0Intel(PVM pVM);
403static int hmR3InitFinalizeR0Amd(PVM pVM);
404static int hmR3TermCPU(PVM pVM);
405
406
407
408/**
409 * Initializes the HM.
410 *
411 * This is the very first component to really do init after CFGM so that we can
412 * establish the predominat execution engine for the VM prior to initializing
413 * other modules. It takes care of NEM initialization if needed (HM disabled or
414 * not available in HW).
415 *
416 * If VT-x or AMD-V hardware isn't available, HM will try fall back on a native
417 * hypervisor API via NEM, and then back on raw-mode if that isn't available
418 * either. The fallback to raw-mode will not happen if /HM/HMForced is set
419 * (like for guest using SMP or 64-bit as well as for complicated guest like OS
420 * X, OS/2 and others).
421 *
422 * Note that a lot of the set up work is done in ring-0 and thus postponed till
423 * the ring-3 and ring-0 callback to HMR3InitCompleted.
424 *
425 * @returns VBox status code.
426 * @param pVM The cross context VM structure.
427 *
428 * @remarks Be careful with what we call here, since most of the VMM components
429 * are uninitialized.
430 */
431VMMR3_INT_DECL(int) HMR3Init(PVM pVM)
432{
433 LogFlow(("HMR3Init\n"));
434
435 /*
436 * Assert alignment and sizes.
437 */
438 AssertCompileMemberAlignment(VM, hm.s, 32);
439 AssertCompile(sizeof(pVM->hm.s) <= sizeof(pVM->hm.padding));
440
441 /*
442 * Register the saved state data unit.
443 */
444 int rc = SSMR3RegisterInternal(pVM, "HWACCM", 0, HM_SAVED_STATE_VERSION, sizeof(HM),
445 NULL, NULL, NULL,
446 NULL, hmR3Save, NULL,
447 NULL, hmR3Load, NULL);
448 if (RT_FAILURE(rc))
449 return rc;
450
451 /*
452 * Register info handlers.
453 */
454 rc = DBGFR3InfoRegisterInternalEx(pVM, "hm", "Dumps HM info.", hmR3Info, DBGFINFO_FLAGS_ALL_EMTS);
455 AssertRCReturn(rc, rc);
456
457 rc = DBGFR3InfoRegisterInternalEx(pVM, "hmeventpending", "Dumps the pending HM event.", hmR3InfoEventPending,
458 DBGFINFO_FLAGS_ALL_EMTS);
459 AssertRCReturn(rc, rc);
460
461 rc = DBGFR3InfoRegisterInternalEx(pVM, "svmvmcbcache", "Dumps the HM SVM nested-guest VMCB cache.",
462 hmR3InfoSvmNstGstVmcbCache, DBGFINFO_FLAGS_ALL_EMTS);
463 AssertRCReturn(rc, rc);
464
465 /*
466 * Read configuration.
467 */
468 PCFGMNODE pCfgHm = CFGMR3GetChild(CFGMR3GetRoot(pVM), "HM/");
469
470 /*
471 * Validate the HM settings.
472 */
473 rc = CFGMR3ValidateConfig(pCfgHm, "/HM/",
474 "HMForced"
475 "|UseNEMInstead"
476 "|FallbackToNEM"
477 "|EnableNestedPaging"
478 "|EnableUX"
479 "|EnableLargePages"
480 "|EnableVPID"
481 "|IBPBOnVMExit"
482 "|IBPBOnVMEntry"
483 "|SpecCtrlByHost"
484 "|TPRPatchingEnabled"
485 "|64bitEnabled"
486 "|Exclusive"
487 "|MaxResumeLoops"
488 "|VmxPleGap"
489 "|VmxPleWindow"
490 "|UseVmxPreemptTimer"
491 "|SvmPauseFilter"
492 "|SvmPauseFilterThreshold"
493 "|SvmVirtVmsaveVmload"
494 "|SvmVGif",
495 "" /* pszValidNodes */, "HM" /* pszWho */, 0 /* uInstance */);
496 if (RT_FAILURE(rc))
497 return rc;
498
499 /** @cfgm{/HM/HMForced, bool, false}
500 * Forces hardware virtualization, no falling back on raw-mode. HM must be
501 * enabled, i.e. /HMEnabled must be true. */
502 bool fHMForced;
503#ifdef VBOX_WITH_RAW_MODE
504 rc = CFGMR3QueryBoolDef(pCfgHm, "HMForced", &fHMForced, false);
505 AssertRCReturn(rc, rc);
506 AssertLogRelMsgReturn(!fHMForced || pVM->fHMEnabled, ("Configuration error: HM forced but not enabled!\n"),
507 VERR_INVALID_PARAMETER);
508# if defined(RT_OS_DARWIN)
509 if (pVM->fHMEnabled)
510 fHMForced = true;
511# endif
512 AssertLogRelMsgReturn(pVM->cCpus == 1 || pVM->fHMEnabled, ("Configuration error: SMP requires HM to be enabled!\n"),
513 VERR_INVALID_PARAMETER);
514 if (pVM->cCpus > 1)
515 fHMForced = true;
516#else /* !VBOX_WITH_RAW_MODE */
517 AssertRelease(pVM->fHMEnabled);
518 fHMForced = true;
519#endif /* !VBOX_WITH_RAW_MODE */
520
521 /** @cfgm{/HM/UseNEMInstead, bool, true}
522 * Don't use HM, use NEM instead. */
523 bool fUseNEMInstead = false;
524 rc = CFGMR3QueryBoolDef(pCfgHm, "UseNEMInstead", &fUseNEMInstead, false);
525 AssertRCReturn(rc, rc);
526 if (fUseNEMInstead && pVM->fHMEnabled)
527 {
528 LogRel(("HM: Setting fHMEnabled to false because fUseNEMInstead is set.\n"));
529 pVM->fHMEnabled = false;
530 }
531
532 /** @cfgm{/HM/FallbackToNEM, bool, true}
533 * Enables fallback on NEM. */
534 bool fFallbackToNEM = true;
535 rc = CFGMR3QueryBoolDef(pCfgHm, "FallbackToNEM", &fFallbackToNEM, true);
536 AssertRCReturn(rc, rc);
537
538 /** @cfgm{/HM/EnableNestedPaging, bool, false}
539 * Enables nested paging (aka extended page tables). */
540 rc = CFGMR3QueryBoolDef(pCfgHm, "EnableNestedPaging", &pVM->hm.s.fAllowNestedPaging, false);
541 AssertRCReturn(rc, rc);
542
543 /** @cfgm{/HM/EnableUX, bool, true}
544 * Enables the VT-x unrestricted execution feature. */
545 rc = CFGMR3QueryBoolDef(pCfgHm, "EnableUX", &pVM->hm.s.vmx.fAllowUnrestricted, true);
546 AssertRCReturn(rc, rc);
547
548 /** @cfgm{/HM/EnableLargePages, bool, false}
549 * Enables using large pages (2 MB) for guest memory, thus saving on (nested)
550 * page table walking and maybe better TLB hit rate in some cases. */
551 rc = CFGMR3QueryBoolDef(pCfgHm, "EnableLargePages", &pVM->hm.s.fLargePages, false);
552 AssertRCReturn(rc, rc);
553
554 /** @cfgm{/HM/EnableVPID, bool, false}
555 * Enables the VT-x VPID feature. */
556 rc = CFGMR3QueryBoolDef(pCfgHm, "EnableVPID", &pVM->hm.s.vmx.fAllowVpid, false);
557 AssertRCReturn(rc, rc);
558
559 /** @cfgm{/HM/TPRPatchingEnabled, bool, false}
560 * Enables TPR patching for 32-bit windows guests with IO-APIC. */
561 rc = CFGMR3QueryBoolDef(pCfgHm, "TPRPatchingEnabled", &pVM->hm.s.fTprPatchingAllowed, false);
562 AssertRCReturn(rc, rc);
563
564 /** @cfgm{/HM/64bitEnabled, bool, 32-bit:false, 64-bit:true}
565 * Enables AMD64 cpu features.
566 * On 32-bit hosts this isn't default and require host CPU support. 64-bit hosts
567 * already have the support. */
568#ifdef VBOX_ENABLE_64_BITS_GUESTS
569 rc = CFGMR3QueryBoolDef(pCfgHm, "64bitEnabled", &pVM->hm.s.fAllow64BitGuests, HC_ARCH_BITS == 64);
570 AssertLogRelRCReturn(rc, rc);
571#else
572 pVM->hm.s.fAllow64BitGuests = false;
573#endif
574
575 /** @cfgm{/HM/VmxPleGap, uint32_t, 0}
576 * The pause-filter exiting gap in TSC ticks. When the number of ticks between
577 * two successive PAUSE instructions exceeds VmxPleGap, the CPU considers the
578 * latest PAUSE instruction to be start of a new PAUSE loop.
579 */
580 rc = CFGMR3QueryU32Def(pCfgHm, "VmxPleGap", &pVM->hm.s.vmx.cPleGapTicks, 0);
581 AssertRCReturn(rc, rc);
582
583 /** @cfgm{/HM/VmxPleWindow, uint32_t, 0}
584 * The pause-filter exiting window in TSC ticks. When the number of ticks
585 * between the current PAUSE instruction and first PAUSE of a loop exceeds
586 * VmxPleWindow, a VM-exit is triggered.
587 *
588 * Setting VmxPleGap and VmxPleGap to 0 disables pause-filter exiting.
589 */
590 rc = CFGMR3QueryU32Def(pCfgHm, "VmxPleWindow", &pVM->hm.s.vmx.cPleWindowTicks, 0);
591 AssertRCReturn(rc, rc);
592
593 /** @cfgm{/HM/SvmPauseFilterCount, uint16_t, 0}
594 * A counter that is decrement each time a PAUSE instruction is executed by the
595 * guest. When the counter is 0, a \#VMEXIT is triggered.
596 *
597 * Setting SvmPauseFilterCount to 0 disables pause-filter exiting.
598 */
599 rc = CFGMR3QueryU16Def(pCfgHm, "SvmPauseFilter", &pVM->hm.s.svm.cPauseFilter, 0);
600 AssertRCReturn(rc, rc);
601
602 /** @cfgm{/HM/SvmPauseFilterThreshold, uint16_t, 0}
603 * The pause filter threshold in ticks. When the elapsed time (in ticks) between
604 * two successive PAUSE instructions exceeds SvmPauseFilterThreshold, the
605 * PauseFilter count is reset to its initial value. However, if PAUSE is
606 * executed PauseFilter times within PauseFilterThreshold ticks, a VM-exit will
607 * be triggered.
608 *
609 * Requires SvmPauseFilterCount to be non-zero for pause-filter threshold to be
610 * activated.
611 */
612 rc = CFGMR3QueryU16Def(pCfgHm, "SvmPauseFilterThreshold", &pVM->hm.s.svm.cPauseFilterThresholdTicks, 0);
613 AssertRCReturn(rc, rc);
614
615 /** @cfgm{/HM/SvmVirtVmsaveVmload, bool, true}
616 * Whether to make use of virtualized VMSAVE/VMLOAD feature of the CPU if it's
617 * available. */
618 rc = CFGMR3QueryBoolDef(pCfgHm, "SvmVirtVmsaveVmload", &pVM->hm.s.svm.fVirtVmsaveVmload, true);
619 AssertRCReturn(rc, rc);
620
621 /** @cfgm{/HM/SvmVGif, bool, true}
622 * Whether to make use of Virtual GIF (Global Interrupt Flag) feature of the CPU
623 * if it's available. */
624 rc = CFGMR3QueryBoolDef(pCfgHm, "SvmVGif", &pVM->hm.s.svm.fVGif, true);
625 AssertRCReturn(rc, rc);
626
627 /** @cfgm{/HM/Exclusive, bool}
628 * Determines the init method for AMD-V and VT-x. If set to true, HM will do a
629 * global init for each host CPU. If false, we do local init each time we wish
630 * to execute guest code.
631 *
632 * On Windows, default is false due to the higher risk of conflicts with other
633 * hypervisors.
634 *
635 * On Mac OS X, this setting is ignored since the code does not handle local
636 * init when it utilizes the OS provided VT-x function, SUPR0EnableVTx().
637 */
638#if defined(RT_OS_DARWIN)
639 pVM->hm.s.fGlobalInit = true;
640#else
641 rc = CFGMR3QueryBoolDef(pCfgHm, "Exclusive", &pVM->hm.s.fGlobalInit,
642# if defined(RT_OS_WINDOWS)
643 false
644# else
645 true
646# endif
647 );
648 AssertLogRelRCReturn(rc, rc);
649#endif
650
651 /** @cfgm{/HM/MaxResumeLoops, uint32_t}
652 * The number of times to resume guest execution before we forcibly return to
653 * ring-3. The return value of RTThreadPreemptIsPendingTrusty in ring-0
654 * determines the default value. */
655 rc = CFGMR3QueryU32Def(pCfgHm, "MaxResumeLoops", &pVM->hm.s.cMaxResumeLoops, 0 /* set by R0 later */);
656 AssertLogRelRCReturn(rc, rc);
657
658 /** @cfgm{/HM/UseVmxPreemptTimer, bool}
659 * Whether to make use of the VMX-preemption timer feature of the CPU if it's
660 * available. */
661 rc = CFGMR3QueryBoolDef(pCfgHm, "UseVmxPreemptTimer", &pVM->hm.s.vmx.fUsePreemptTimer, true);
662 AssertLogRelRCReturn(rc, rc);
663
664 /** @cfgm{/HM/IBPBOnVMExit, bool}
665 * Costly paranoia setting. */
666 rc = CFGMR3QueryBoolDef(pCfgHm, "IBPBOnVMExit", &pVM->hm.s.fIbpbOnVmExit, false);
667 AssertLogRelRCReturn(rc, rc);
668
669 /** @cfgm{/HM/IBPBOnVMEntry, bool}
670 * Costly paranoia setting. */
671 rc = CFGMR3QueryBoolDef(pCfgHm, "IBPBOnVMEntry", &pVM->hm.s.fIbpbOnVmEntry, false);
672 AssertLogRelRCReturn(rc, rc);
673
674 /** @cfgm{/HM/SpecCtrlByHost, bool}
675 * Another expensive paranoia setting. */
676 rc = CFGMR3QueryBoolDef(pCfgHm, "SpecCtrlByHost", &pVM->hm.s.fSpecCtrlByHost, false);
677 AssertLogRelRCReturn(rc, rc);
678
679 /*
680 * Check if VT-x or AMD-v support according to the users wishes.
681 */
682 /** @todo SUPR3QueryVTCaps won't catch VERR_VMX_IN_VMX_ROOT_MODE or
683 * VERR_SVM_IN_USE. */
684 if (pVM->fHMEnabled)
685 {
686 uint32_t fCaps;
687 rc = SUPR3QueryVTCaps(&fCaps);
688 if (RT_SUCCESS(rc))
689 {
690 if (fCaps & SUPVTCAPS_AMD_V)
691 {
692 LogRel(("HM: HMR3Init: AMD-V%s\n", fCaps & SUPVTCAPS_NESTED_PAGING ? " w/ nested paging" : ""));
693 pVM->hm.s.svm.fSupported = true;
694 VM_SET_MAIN_EXECUTION_ENGINE(pVM, VM_EXEC_ENGINE_HW_VIRT);
695 }
696 else if (fCaps & SUPVTCAPS_VT_X)
697 {
698 const char *pszWhy;
699 rc = SUPR3QueryVTxSupported(&pszWhy);
700 if (RT_SUCCESS(rc))
701 {
702 LogRel(("HM: HMR3Init: VT-x%s%s%s\n",
703 fCaps & SUPVTCAPS_NESTED_PAGING ? " w/ nested paging" : "",
704 fCaps & SUPVTCAPS_VTX_UNRESTRICTED_GUEST ? " and unrestricted guest execution" : "",
705 (fCaps & (SUPVTCAPS_NESTED_PAGING | SUPVTCAPS_VTX_UNRESTRICTED_GUEST)) ? " hw support" : ""));
706 pVM->hm.s.vmx.fSupported = true;
707 VM_SET_MAIN_EXECUTION_ENGINE(pVM, VM_EXEC_ENGINE_HW_VIRT);
708 }
709 else
710 {
711 /*
712 * Before failing, try fallback to NEM if we're allowed to do that.
713 */
714 pVM->fHMEnabled = false;
715 Assert(pVM->bMainExecutionEngine == VM_EXEC_ENGINE_NOT_SET);
716 if (fFallbackToNEM)
717 {
718 LogRel(("HM: HMR3Init: Attempting fall back to NEM: The host kernel does not support VT-x - %s\n", pszWhy));
719 int rc2 = NEMR3Init(pVM, true /*fFallback*/, fHMForced);
720
721 ASMCompilerBarrier(); /* NEMR3Init may have changed bMainExecutionEngine. */
722 if ( RT_SUCCESS(rc2)
723 && pVM->bMainExecutionEngine != VM_EXEC_ENGINE_NOT_SET)
724 rc = VINF_SUCCESS;
725 }
726 if (RT_FAILURE(rc))
727 {
728 if (fHMForced)
729 return VMSetError(pVM, rc, RT_SRC_POS, "The host kernel does not support VT-x: %s\n", pszWhy);
730
731 /* Fall back to raw-mode. */
732 LogRel(("HM: HMR3Init: Falling back to raw-mode: The host kernel does not support VT-x - %s\n", pszWhy));
733 VM_SET_MAIN_EXECUTION_ENGINE(pVM, VM_EXEC_ENGINE_RAW_MODE);
734 }
735 }
736 }
737 else
738 AssertLogRelMsgFailedReturn(("SUPR3QueryVTCaps didn't return either AMD-V or VT-x flag set (%#x)!\n", fCaps),
739 VERR_INTERNAL_ERROR_5);
740
741 /*
742 * Do we require a little bit or raw-mode for 64-bit guest execution?
743 */
744 pVM->fHMNeedRawModeCtx = HC_ARCH_BITS == 32
745 && pVM->fHMEnabled
746 && pVM->hm.s.fAllow64BitGuests;
747
748 /*
749 * Disable nested paging and unrestricted guest execution now if they're
750 * configured so that CPUM can make decisions based on our configuration.
751 */
752 Assert(!pVM->hm.s.fNestedPaging);
753 if (pVM->hm.s.fAllowNestedPaging)
754 {
755 if (fCaps & SUPVTCAPS_NESTED_PAGING)
756 pVM->hm.s.fNestedPaging = true;
757 else
758 pVM->hm.s.fAllowNestedPaging = false;
759 }
760
761 if (fCaps & SUPVTCAPS_VT_X)
762 {
763 Assert(!pVM->hm.s.vmx.fUnrestrictedGuest);
764 if (pVM->hm.s.vmx.fAllowUnrestricted)
765 {
766 if ( (fCaps & SUPVTCAPS_VTX_UNRESTRICTED_GUEST)
767 && pVM->hm.s.fNestedPaging)
768 pVM->hm.s.vmx.fUnrestrictedGuest = true;
769 else
770 pVM->hm.s.vmx.fAllowUnrestricted = false;
771 }
772 }
773 }
774 else
775 {
776 const char *pszMsg;
777 switch (rc)
778 {
779 case VERR_UNSUPPORTED_CPU: pszMsg = "Unknown CPU, VT-x or AMD-v features cannot be ascertained"; break;
780 case VERR_VMX_NO_VMX: pszMsg = "VT-x is not available"; break;
781 case VERR_VMX_MSR_VMX_DISABLED: pszMsg = "VT-x is disabled in the BIOS"; break;
782 case VERR_VMX_MSR_ALL_VMX_DISABLED: pszMsg = "VT-x is disabled in the BIOS for all CPU modes"; break;
783 case VERR_VMX_MSR_LOCKING_FAILED: pszMsg = "Failed to enable and lock VT-x features"; break;
784 case VERR_SVM_NO_SVM: pszMsg = "AMD-V is not available"; break;
785 case VERR_SVM_DISABLED: pszMsg = "AMD-V is disabled in the BIOS (or by the host OS)"; break;
786 default:
787 return VMSetError(pVM, rc, RT_SRC_POS, "SUPR3QueryVTCaps failed with %Rrc", rc);
788 }
789
790 /*
791 * Before failing, try fallback to NEM if we're allowed to do that.
792 */
793 pVM->fHMEnabled = false;
794 if (fFallbackToNEM)
795 {
796 LogRel(("HM: HMR3Init: Attempting fall back to NEM: %s\n", pszMsg));
797 int rc2 = NEMR3Init(pVM, true /*fFallback*/, fHMForced);
798 ASMCompilerBarrier(); /* NEMR3Init may have changed bMainExecutionEngine. */
799 if ( RT_SUCCESS(rc2)
800 && pVM->bMainExecutionEngine != VM_EXEC_ENGINE_NOT_SET)
801 rc = VINF_SUCCESS;
802 }
803 if (RT_FAILURE(rc))
804 {
805 if (fHMForced)
806 return VM_SET_ERROR(pVM, rc, pszMsg);
807
808 LogRel(("HM: HMR3Init: Falling back to raw-mode: %s\n", pszMsg));
809 VM_SET_MAIN_EXECUTION_ENGINE(pVM, VM_EXEC_ENGINE_RAW_MODE);
810 }
811 }
812 }
813 else
814 {
815 /*
816 * Disabled HM mean raw-mode, unless NEM is supposed to be used.
817 */
818 if (!fUseNEMInstead)
819 VM_SET_MAIN_EXECUTION_ENGINE(pVM, VM_EXEC_ENGINE_RAW_MODE);
820 else
821 {
822 rc = NEMR3Init(pVM, false /*fFallback*/, true);
823 ASMCompilerBarrier(); /* NEMR3Init may have changed bMainExecutionEngine. */
824 if (RT_FAILURE(rc))
825 return rc;
826 }
827 }
828
829 return VINF_SUCCESS;
830}
831
832
833/**
834 * Initializes the per-VCPU HM.
835 *
836 * @returns VBox status code.
837 * @param pVM The cross context VM structure.
838 */
839static int hmR3InitCPU(PVM pVM)
840{
841 LogFlow(("HMR3InitCPU\n"));
842
843 if (!HMIsEnabled(pVM))
844 return VINF_SUCCESS;
845
846 for (VMCPUID i = 0; i < pVM->cCpus; i++)
847 {
848 PVMCPU pVCpu = &pVM->aCpus[i];
849 pVCpu->hm.s.fActive = false;
850 }
851
852#ifdef VBOX_WITH_STATISTICS
853 STAM_REG(pVM, &pVM->hm.s.StatTprPatchSuccess, STAMTYPE_COUNTER, "/HM/TPR/Patch/Success", STAMUNIT_OCCURENCES, "Number of times an instruction was successfully patched.");
854 STAM_REG(pVM, &pVM->hm.s.StatTprPatchFailure, STAMTYPE_COUNTER, "/HM/TPR/Patch/Failed", STAMUNIT_OCCURENCES, "Number of unsuccessful patch attempts.");
855 STAM_REG(pVM, &pVM->hm.s.StatTprReplaceSuccessCr8, STAMTYPE_COUNTER, "/HM/TPR/Replace/SuccessCR8",STAMUNIT_OCCURENCES, "Number of instruction replacements by MOV CR8.");
856 STAM_REG(pVM, &pVM->hm.s.StatTprReplaceSuccessVmc, STAMTYPE_COUNTER, "/HM/TPR/Replace/SuccessVMC",STAMUNIT_OCCURENCES, "Number of instruction replacements by VMMCALL.");
857 STAM_REG(pVM, &pVM->hm.s.StatTprReplaceFailure, STAMTYPE_COUNTER, "/HM/TPR/Replace/Failed", STAMUNIT_OCCURENCES, "Number of unsuccessful replace attempts.");
858#endif
859
860 /*
861 * Statistics.
862 */
863 for (VMCPUID i = 0; i < pVM->cCpus; i++)
864 {
865 PVMCPU pVCpu = &pVM->aCpus[i];
866 int rc;
867
868#ifdef VBOX_WITH_STATISTICS
869 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatPoke, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
870 "Profiling of RTMpPokeCpu.",
871 "/PROF/CPU%d/HM/Poke", i);
872 AssertRC(rc);
873 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatSpinPoke, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
874 "Profiling of poke wait.",
875 "/PROF/CPU%d/HM/PokeWait", i);
876 AssertRC(rc);
877 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatSpinPokeFailed, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
878 "Profiling of poke wait when RTMpPokeCpu fails.",
879 "/PROF/CPU%d/HM/PokeWaitFailed", i);
880 AssertRC(rc);
881 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatEntry, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
882 "Profiling of entry until entering GC.",
883 "/PROF/CPU%d/HM/Entry", i);
884 AssertRC(rc);
885 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatPreExit, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
886 "Profiling of pre-exit processing after returning from GC.",
887 "/PROF/CPU%d/HM/SwitchFromGC_1", i);
888 AssertRC(rc);
889 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatExitHandling, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
890 "Profiling of exit handling (longjmps not included!)",
891 "/PROF/CPU%d/HM/SwitchFromGC_2", i);
892 AssertRC(rc);
893
894 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatExitIO, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
895 "I/O.",
896 "/PROF/CPU%d/HM/SwitchFromGC_2/IO", i);
897 AssertRC(rc);
898 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatExitMovCRx, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
899 "MOV CRx.",
900 "/PROF/CPU%d/HM/SwitchFromGC_2/MovCRx", i);
901 AssertRC(rc);
902 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatExitXcptNmi, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
903 "Exceptions, NMIs.",
904 "/PROF/CPU%d/HM/SwitchFromGC_2/XcptNmi", i);
905 AssertRC(rc);
906
907 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatImportGuestState, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
908 "Profiling of importing guest state from hardware after VM-exit.",
909 "/PROF/CPU%d/HM/ImportGuestState", i);
910 AssertRC(rc);
911 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatExportGuestState, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
912 "Profiling of exporting guest state to hardware before VM-entry.",
913 "/PROF/CPU%d/HM/ExportGuestState", i);
914 AssertRC(rc);
915 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatLoadGuestFpuState, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
916 "Profiling of CPUMR0LoadGuestFPU.",
917 "/PROF/CPU%d/HM/LoadGuestFpuState", i);
918 AssertRC(rc);
919 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatInGC, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
920 "Profiling of execution of guest-code in hardware.",
921 "/PROF/CPU%d/HM/InGC", i);
922 AssertRC(rc);
923
924# if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
925 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatWorldSwitch3264, STAMTYPE_PROFILE, STAMVISIBILITY_USED,
926 STAMUNIT_TICKS_PER_CALL, "Profiling of the 32/64 switcher.",
927 "/PROF/CPU%d/HM/Switcher3264", i);
928 AssertRC(rc);
929# endif
930
931# ifdef HM_PROFILE_EXIT_DISPATCH
932 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatExitDispatch, STAMTYPE_PROFILE_ADV, STAMVISIBILITY_USED,
933 STAMUNIT_TICKS_PER_CALL, "Profiling the dispatching of exit handlers.",
934 "/PROF/CPU%d/HM/ExitDispatch", i);
935 AssertRC(rc);
936# endif
937
938#endif
939# define HM_REG_COUNTER(a, b, desc) \
940 rc = STAMR3RegisterF(pVM, a, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, desc, b, i); \
941 AssertRC(rc);
942
943#ifdef VBOX_WITH_STATISTICS
944 HM_REG_COUNTER(&pVCpu->hm.s.StatExitAll, "/HM/CPU%d/Exit/All", "Exits (total).");
945 HM_REG_COUNTER(&pVCpu->hm.s.StatExitShadowNM, "/HM/CPU%d/Exit/Trap/Shw/#NM", "Shadow #NM (device not available, no math co-processor) exception.");
946 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestNM, "/HM/CPU%d/Exit/Trap/Gst/#NM", "Guest #NM (device not available, no math co-processor) exception.");
947 HM_REG_COUNTER(&pVCpu->hm.s.StatExitShadowPF, "/HM/CPU%d/Exit/Trap/Shw/#PF", "Shadow #PF (page fault) exception.");
948 HM_REG_COUNTER(&pVCpu->hm.s.StatExitShadowPFEM, "/HM/CPU%d/Exit/Trap/Shw/#PF-EM", "#PF (page fault) exception going back to ring-3 for emulating the instruction.");
949 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestPF, "/HM/CPU%d/Exit/Trap/Gst/#PF", "Guest #PF (page fault) exception.");
950 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestUD, "/HM/CPU%d/Exit/Trap/Gst/#UD", "Guest #UD (undefined opcode) exception.");
951 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestSS, "/HM/CPU%d/Exit/Trap/Gst/#SS", "Guest #SS (stack-segment fault) exception.");
952 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestNP, "/HM/CPU%d/Exit/Trap/Gst/#NP", "Guest #NP (segment not present) exception.");
953 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestGP, "/HM/CPU%d/Exit/Trap/Gst/#GP", "Guest #GP (general protection) exception.");
954 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestMF, "/HM/CPU%d/Exit/Trap/Gst/#MF", "Guest #MF (x87 FPU error, math fault) exception.");
955 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestDE, "/HM/CPU%d/Exit/Trap/Gst/#DE", "Guest #DE (divide error) exception.");
956 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestDB, "/HM/CPU%d/Exit/Trap/Gst/#DB", "Guest #DB (debug) exception.");
957 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestBP, "/HM/CPU%d/Exit/Trap/Gst/#BP", "Guest #BP (breakpoint) exception.");
958 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestXF, "/HM/CPU%d/Exit/Trap/Gst/#XF", "Guest #XF (extended math fault, SIMD FPU) exception.");
959 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestXcpUnk, "/HM/CPU%d/Exit/Trap/Gst/Other", "Other guest exceptions.");
960 HM_REG_COUNTER(&pVCpu->hm.s.StatExitHlt, "/HM/CPU%d/Exit/Instr/Hlt", "HLT instruction.");
961 HM_REG_COUNTER(&pVCpu->hm.s.StatExitRdmsr, "/HM/CPU%d/Exit/Instr/Rdmsr", "RDMSR instruction.");
962 HM_REG_COUNTER(&pVCpu->hm.s.StatExitWrmsr, "/HM/CPU%d/Exit/Instr/Wrmsr", "WRMSR instruction.");
963 HM_REG_COUNTER(&pVCpu->hm.s.StatExitMwait, "/HM/CPU%d/Exit/Instr/Mwait", "MWAIT instruction.");
964 HM_REG_COUNTER(&pVCpu->hm.s.StatExitMonitor, "/HM/CPU%d/Exit/Instr/Monitor", "MONITOR instruction.");
965 HM_REG_COUNTER(&pVCpu->hm.s.StatExitDRxWrite, "/HM/CPU%d/Exit/Instr/DR-Write", "Debug register write.");
966 HM_REG_COUNTER(&pVCpu->hm.s.StatExitDRxRead, "/HM/CPU%d/Exit/Instr/DR-Read", "Debug register read.");
967 HM_REG_COUNTER(&pVCpu->hm.s.StatExitCR0Read, "/HM/CPU%d/Exit/Instr/CR-Read/CR0", "CR0 read.");
968 HM_REG_COUNTER(&pVCpu->hm.s.StatExitCR2Read, "/HM/CPU%d/Exit/Instr/CR-Read/CR2", "CR2 read.");
969 HM_REG_COUNTER(&pVCpu->hm.s.StatExitCR3Read, "/HM/CPU%d/Exit/Instr/CR-Read/CR3", "CR3 read.");
970 HM_REG_COUNTER(&pVCpu->hm.s.StatExitCR4Read, "/HM/CPU%d/Exit/Instr/CR-Read/CR4", "CR4 read.");
971 HM_REG_COUNTER(&pVCpu->hm.s.StatExitCR8Read, "/HM/CPU%d/Exit/Instr/CR-Read/CR8", "CR8 read.");
972 HM_REG_COUNTER(&pVCpu->hm.s.StatExitCR0Write, "/HM/CPU%d/Exit/Instr/CR-Write/CR0", "CR0 write.");
973 HM_REG_COUNTER(&pVCpu->hm.s.StatExitCR2Write, "/HM/CPU%d/Exit/Instr/CR-Write/CR2", "CR2 write.");
974 HM_REG_COUNTER(&pVCpu->hm.s.StatExitCR3Write, "/HM/CPU%d/Exit/Instr/CR-Write/CR3", "CR3 write.");
975 HM_REG_COUNTER(&pVCpu->hm.s.StatExitCR4Write, "/HM/CPU%d/Exit/Instr/CR-Write/CR4", "CR4 write.");
976 HM_REG_COUNTER(&pVCpu->hm.s.StatExitCR8Write, "/HM/CPU%d/Exit/Instr/CR-Write/CR8", "CR8 write.");
977 HM_REG_COUNTER(&pVCpu->hm.s.StatExitClts, "/HM/CPU%d/Exit/Instr/CLTS", "CLTS instruction.");
978 HM_REG_COUNTER(&pVCpu->hm.s.StatExitLmsw, "/HM/CPU%d/Exit/Instr/LMSW", "LMSW instruction.");
979 HM_REG_COUNTER(&pVCpu->hm.s.StatExitCli, "/HM/CPU%d/Exit/Instr/Cli", "CLI instruction.");
980 HM_REG_COUNTER(&pVCpu->hm.s.StatExitSti, "/HM/CPU%d/Exit/Instr/Sti", "STI instruction.");
981 HM_REG_COUNTER(&pVCpu->hm.s.StatExitPushf, "/HM/CPU%d/Exit/Instr/Pushf", "PUSHF instruction.");
982 HM_REG_COUNTER(&pVCpu->hm.s.StatExitPopf, "/HM/CPU%d/Exit/Instr/Popf", "POPF instruction.");
983 HM_REG_COUNTER(&pVCpu->hm.s.StatExitIret, "/HM/CPU%d/Exit/Instr/Iret", "IRET instruction.");
984 HM_REG_COUNTER(&pVCpu->hm.s.StatExitInt, "/HM/CPU%d/Exit/Instr/Int", "INT instruction.");
985 HM_REG_COUNTER(&pVCpu->hm.s.StatExitXdtrAccess, "/HM/CPU%d/Exit/Instr/XdtrAccess", "GDTR, IDTR, LDTR access.");
986 HM_REG_COUNTER(&pVCpu->hm.s.StatExitIOWrite, "/HM/CPU%d/Exit/IO/Write", "I/O write.");
987 HM_REG_COUNTER(&pVCpu->hm.s.StatExitIORead, "/HM/CPU%d/Exit/IO/Read", "I/O read.");
988 HM_REG_COUNTER(&pVCpu->hm.s.StatExitIOStringWrite, "/HM/CPU%d/Exit/IO/WriteString", "String I/O write.");
989 HM_REG_COUNTER(&pVCpu->hm.s.StatExitIOStringRead, "/HM/CPU%d/Exit/IO/ReadString", "String I/O read.");
990 HM_REG_COUNTER(&pVCpu->hm.s.StatExitIntWindow, "/HM/CPU%d/Exit/IntWindow", "Interrupt-window exit. Guest is ready to receive interrupts again.");
991 HM_REG_COUNTER(&pVCpu->hm.s.StatExitExtInt, "/HM/CPU%d/Exit/ExtInt", "Physical maskable interrupt (host).");
992#endif
993 HM_REG_COUNTER(&pVCpu->hm.s.StatExitHostNmiInGC, "/HM/CPU%d/Exit/HostNmiInGC", "Host NMI received while in guest context.");
994#ifdef VBOX_WITH_STATISTICS
995 HM_REG_COUNTER(&pVCpu->hm.s.StatExitPreemptTimer, "/HM/CPU%d/Exit/PreemptTimer", "VMX-preemption timer expired.");
996 HM_REG_COUNTER(&pVCpu->hm.s.StatExitTprBelowThreshold, "/HM/CPU%d/Exit/TprBelowThreshold", "TPR lowered below threshold by the guest.");
997 HM_REG_COUNTER(&pVCpu->hm.s.StatExitTaskSwitch, "/HM/CPU%d/Exit/TaskSwitch", "Task switch.");
998 HM_REG_COUNTER(&pVCpu->hm.s.StatExitMtf, "/HM/CPU%d/Exit/MonitorTrapFlag", "Monitor Trap Flag.");
999 HM_REG_COUNTER(&pVCpu->hm.s.StatExitApicAccess, "/HM/CPU%d/Exit/ApicAccess", "APIC access. Guest attempted to access memory at a physical address on the APIC-access page.");
1000
1001 HM_REG_COUNTER(&pVCpu->hm.s.StatSwitchTprMaskedIrq, "/HM/CPU%d/Switch/TprMaskedIrq", "PDMGetInterrupt() signals TPR masks pending Irq.");
1002 HM_REG_COUNTER(&pVCpu->hm.s.StatSwitchGuestIrq, "/HM/CPU%d/Switch/IrqPending", "PDMGetInterrupt() cleared behind our back!?!.");
1003 HM_REG_COUNTER(&pVCpu->hm.s.StatPendingHostIrq, "/HM/CPU%d/Switch/PendingHostIrq", "Exit to ring-3 due to pending host interrupt before executing guest code.");
1004 HM_REG_COUNTER(&pVCpu->hm.s.StatSwitchHmToR3FF, "/HM/CPU%d/Switch/HmToR3FF", "Exit to ring-3 due to pending timers, EMT rendezvous, critical section etc.");
1005 HM_REG_COUNTER(&pVCpu->hm.s.StatSwitchExitToR3, "/HM/CPU%d/Switch/ExitToR3", "Exit to ring-3 (total).");
1006 HM_REG_COUNTER(&pVCpu->hm.s.StatSwitchLongJmpToR3, "/HM/CPU%d/Switch/LongJmpToR3", "Longjump to ring-3.");
1007 HM_REG_COUNTER(&pVCpu->hm.s.StatSwitchMaxResumeLoops, "/HM/CPU%d/Switch/MaxResumeToR3", "Maximum VMRESUME inner-loop counter reached.");
1008 HM_REG_COUNTER(&pVCpu->hm.s.StatSwitchHltToR3, "/HM/CPU%d/Switch/HltToR3", "HLT causing us to go to ring-3.");
1009 HM_REG_COUNTER(&pVCpu->hm.s.StatSwitchApicAccessToR3, "/HM/CPU%d/Switch/ApicAccessToR3", "APIC access causing us to go to ring-3.");
1010#endif
1011 HM_REG_COUNTER(&pVCpu->hm.s.StatSwitchPreempt, "/HM/CPU%d/Switch/Preempting", "EMT has been preempted while in HM context.");
1012#ifdef VBOX_WITH_STATISTICS
1013 HM_REG_COUNTER(&pVCpu->hm.s.StatSwitchPreemptExportHostState, "/HM/CPU%d/Switch/ExportHostState", "Preemption caused us to re-export the host state.");
1014
1015 HM_REG_COUNTER(&pVCpu->hm.s.StatInjectInterrupt, "/HM/CPU%d/EventInject/Interrupt", "Injected an external interrupt into the guest.");
1016 HM_REG_COUNTER(&pVCpu->hm.s.StatInjectXcpt, "/HM/CPU%d/EventInject/Trap", "Injected an exception into the guest.");
1017 HM_REG_COUNTER(&pVCpu->hm.s.StatInjectPendingReflect, "/HM/CPU%d/EventInject/PendingReflect", "Reflecting an exception (or #DF) caused due to event injection.");
1018 HM_REG_COUNTER(&pVCpu->hm.s.StatInjectPendingInterpret, "/HM/CPU%d/EventInject/PendingInterpret", "Falling to interpreter for handling exception caused due to event injection.");
1019
1020 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushPage, "/HM/CPU%d/Flush/Page", "Invalidating a guest page on all guest CPUs.");
1021 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushPageManual, "/HM/CPU%d/Flush/Page/Virt", "Invalidating a guest page using guest-virtual address.");
1022 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushPhysPageManual, "/HM/CPU%d/Flush/Page/Phys", "Invalidating a guest page using guest-physical address.");
1023 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushTlb, "/HM/CPU%d/Flush/TLB", "Forcing a full guest-TLB flush (ring-0).");
1024 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushTlbManual, "/HM/CPU%d/Flush/TLB/Manual", "Request a full guest-TLB flush.");
1025 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushTlbWorldSwitch, "/HM/CPU%d/Flush/TLB/CpuSwitch", "Forcing a full guest-TLB flush due to host-CPU reschedule or ASID-limit hit by another guest-VCPU.");
1026 HM_REG_COUNTER(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch, "/HM/CPU%d/Flush/TLB/Skipped", "No TLB flushing required.");
1027 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushEntire, "/HM/CPU%d/Flush/TLB/Entire", "Flush the entire TLB (host + guest).");
1028 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushAsid, "/HM/CPU%d/Flush/TLB/ASID", "Flushed guest-TLB entries for the current VPID.");
1029 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushNestedPaging, "/HM/CPU%d/Flush/TLB/NestedPaging", "Flushed guest-TLB entries for the current EPT.");
1030 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushTlbInvlpgVirt, "/HM/CPU%d/Flush/TLB/InvlpgVirt", "Invalidated a guest-TLB entry for a guest-virtual address.");
1031 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushTlbInvlpgPhys, "/HM/CPU%d/Flush/TLB/InvlpgPhys", "Currently not possible, flushes entire guest-TLB.");
1032 HM_REG_COUNTER(&pVCpu->hm.s.StatTlbShootdown, "/HM/CPU%d/Flush/Shootdown/Page", "Inter-VCPU request to flush queued guest page.");
1033 HM_REG_COUNTER(&pVCpu->hm.s.StatTlbShootdownFlush, "/HM/CPU%d/Flush/Shootdown/TLB", "Inter-VCPU request to flush entire guest-TLB.");
1034
1035 HM_REG_COUNTER(&pVCpu->hm.s.StatTscParavirt, "/HM/CPU%d/TSC/Paravirt", "Paravirtualized TSC in effect.");
1036 HM_REG_COUNTER(&pVCpu->hm.s.StatTscOffset, "/HM/CPU%d/TSC/Offset", "TSC offsetting is in effect.");
1037 HM_REG_COUNTER(&pVCpu->hm.s.StatTscIntercept, "/HM/CPU%d/TSC/Intercept", "Intercept TSC accesses.");
1038
1039 HM_REG_COUNTER(&pVCpu->hm.s.StatDRxArmed, "/HM/CPU%d/Debug/Armed", "Loaded guest-debug state while loading guest-state.");
1040 HM_REG_COUNTER(&pVCpu->hm.s.StatDRxContextSwitch, "/HM/CPU%d/Debug/ContextSwitch", "Loaded guest-debug state on MOV DRx.");
1041 HM_REG_COUNTER(&pVCpu->hm.s.StatDRxIoCheck, "/HM/CPU%d/Debug/IOCheck", "Checking for I/O breakpoint.");
1042
1043 HM_REG_COUNTER(&pVCpu->hm.s.StatExportMinimal, "/HM/CPU%d/Load/Minimal", "VM-entry exporting minimal guest-state.");
1044 HM_REG_COUNTER(&pVCpu->hm.s.StatExportFull, "/HM/CPU%d/Load/Full", "VM-entry exporting the full guest-state.");
1045 HM_REG_COUNTER(&pVCpu->hm.s.StatLoadGuestFpu, "/HM/CPU%d/Load/GuestFpu", "VM-entry loading the guest-FPU state.");
1046
1047 HM_REG_COUNTER(&pVCpu->hm.s.StatVmxCheckBadRmSelBase, "/HM/CPU%d/VMXCheck/RMSelBase", "Could not use VMX due to unsuitable real-mode selector base.");
1048 HM_REG_COUNTER(&pVCpu->hm.s.StatVmxCheckBadRmSelLimit, "/HM/CPU%d/VMXCheck/RMSelLimit", "Could not use VMX due to unsuitable real-mode selector limit.");
1049 HM_REG_COUNTER(&pVCpu->hm.s.StatVmxCheckRmOk, "/HM/CPU%d/VMXCheck/VMX_RM", "VMX execution in real (V86) mode OK.");
1050 HM_REG_COUNTER(&pVCpu->hm.s.StatVmxCheckBadSel, "/HM/CPU%d/VMXCheck/Selector", "Could not use VMX due to unsuitable selector.");
1051 HM_REG_COUNTER(&pVCpu->hm.s.StatVmxCheckBadRpl, "/HM/CPU%d/VMXCheck/RPL", "Could not use VMX due to unsuitable RPL.");
1052 HM_REG_COUNTER(&pVCpu->hm.s.StatVmxCheckBadLdt, "/HM/CPU%d/VMXCheck/LDT", "Could not use VMX due to unsuitable LDT.");
1053 HM_REG_COUNTER(&pVCpu->hm.s.StatVmxCheckBadTr, "/HM/CPU%d/VMXCheck/TR", "Could not use VMX due to unsuitable TR.");
1054 HM_REG_COUNTER(&pVCpu->hm.s.StatVmxCheckPmOk, "/HM/CPU%d/VMXCheck/VMX_PM", "VMX execution in protected mode OK.");
1055
1056#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
1057 HM_REG_COUNTER(&pVCpu->hm.s.StatFpu64SwitchBack, "/HM/CPU%d/Switch64/Fpu", "Saving guest FPU/XMM state.");
1058 HM_REG_COUNTER(&pVCpu->hm.s.StatDebug64SwitchBack, "/HM/CPU%d/Switch64/Debug", "Saving guest debug state.");
1059#endif
1060
1061#undef HM_REG_COUNTER
1062
1063 const char *const *papszDesc = ASMIsIntelCpu() || ASMIsViaCentaurCpu() ? &g_apszVTxExitReasons[0]
1064 : &g_apszAmdVExitReasons[0];
1065
1066 /*
1067 * Guest Exit reason stats.
1068 */
1069 pVCpu->hm.s.paStatExitReason = NULL;
1070 rc = MMHyperAlloc(pVM, MAX_EXITREASON_STAT * sizeof(*pVCpu->hm.s.paStatExitReason), 0 /* uAlignment */, MM_TAG_HM,
1071 (void **)&pVCpu->hm.s.paStatExitReason);
1072 AssertRCReturn(rc, rc);
1073 for (int j = 0; j < MAX_EXITREASON_STAT; j++)
1074 {
1075 if (papszDesc[j])
1076 {
1077 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.paStatExitReason[j], STAMTYPE_COUNTER, STAMVISIBILITY_USED,
1078 STAMUNIT_OCCURENCES, papszDesc[j], "/HM/CPU%d/Exit/Reason/%02x", i, j);
1079 AssertRCReturn(rc, rc);
1080 }
1081 }
1082 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatExitReasonNpf, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
1083 "Nested page fault", "/HM/CPU%d/Exit/Reason/#NPF", i);
1084 AssertRCReturn(rc, rc);
1085 pVCpu->hm.s.paStatExitReasonR0 = MMHyperR3ToR0(pVM, pVCpu->hm.s.paStatExitReason);
1086# ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
1087 Assert(pVCpu->hm.s.paStatExitReasonR0 != NIL_RTR0PTR || !HMIsEnabled(pVM));
1088# else
1089 Assert(pVCpu->hm.s.paStatExitReasonR0 != NIL_RTR0PTR);
1090# endif
1091
1092#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
1093 /*
1094 * Nested-guest Exit reason stats.
1095 */
1096 pVCpu->hm.s.paStatNestedExitReason = NULL;
1097 rc = MMHyperAlloc(pVM, MAX_EXITREASON_STAT * sizeof(*pVCpu->hm.s.paStatNestedExitReason), 0 /* uAlignment */, MM_TAG_HM,
1098 (void **)&pVCpu->hm.s.paStatNestedExitReason);
1099 AssertRCReturn(rc, rc);
1100 for (int j = 0; j < MAX_EXITREASON_STAT; j++)
1101 {
1102 if (papszDesc[j])
1103 {
1104 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.paStatNestedExitReason[j], STAMTYPE_COUNTER, STAMVISIBILITY_USED,
1105 STAMUNIT_OCCURENCES, papszDesc[j], "/HM/CPU%d/NestedExit/Reason/%02x", i, j);
1106 AssertRC(rc);
1107 }
1108 }
1109 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatNestedExitReasonNpf, STAMTYPE_COUNTER, STAMVISIBILITY_USED,
1110 STAMUNIT_OCCURENCES, "Nested page fault", "/HM/CPU%d/NestedExit/Reason/#NPF", i);
1111 AssertRCReturn(rc, rc);
1112 pVCpu->hm.s.paStatNestedExitReasonR0 = MMHyperR3ToR0(pVM, pVCpu->hm.s.paStatNestedExitReason);
1113# ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
1114 Assert(pVCpu->hm.s.paStatNestedExitReasonR0 != NIL_RTR0PTR || !HMIsEnabled(pVM));
1115# else
1116 Assert(pVCpu->hm.s.paStatNestedExitReasonR0 != NIL_RTR0PTR);
1117# endif
1118#endif
1119
1120 /*
1121 * Injected events stats.
1122 */
1123 rc = MMHyperAlloc(pVM, sizeof(STAMCOUNTER) * 256, 8, MM_TAG_HM, (void **)&pVCpu->hm.s.paStatInjectedIrqs);
1124 AssertRCReturn(rc, rc);
1125 pVCpu->hm.s.paStatInjectedIrqsR0 = MMHyperR3ToR0(pVM, pVCpu->hm.s.paStatInjectedIrqs);
1126# ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
1127 Assert(pVCpu->hm.s.paStatInjectedIrqsR0 != NIL_RTR0PTR || !HMIsEnabled(pVM));
1128# else
1129 Assert(pVCpu->hm.s.paStatInjectedIrqsR0 != NIL_RTR0PTR);
1130# endif
1131 for (unsigned j = 0; j < 255; j++)
1132 {
1133 STAMR3RegisterF(pVM, &pVCpu->hm.s.paStatInjectedIrqs[j], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
1134 "Injected event.",
1135 (j < 0x20) ? "/HM/CPU%d/EventInject/InjectTrap/%02X" : "/HM/CPU%d/EventInject/InjectIRQ/%02X", i, j);
1136 }
1137
1138#endif /* VBOX_WITH_STATISTICS */
1139 }
1140
1141#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1142 /*
1143 * Magic marker for searching in crash dumps.
1144 */
1145 for (VMCPUID i = 0; i < pVM->cCpus; i++)
1146 {
1147 PVMCPU pVCpu = &pVM->aCpus[i];
1148
1149 PVMCSCACHE pCache = &pVCpu->hm.s.vmx.VMCSCache;
1150 strcpy((char *)pCache->aMagic, "VMCSCACHE Magic");
1151 pCache->uMagic = UINT64_C(0xDEADBEEFDEADBEEF);
1152 }
1153#endif
1154
1155 return VINF_SUCCESS;
1156}
1157
1158
1159/**
1160 * Called when a init phase has completed.
1161 *
1162 * @returns VBox status code.
1163 * @param pVM The cross context VM structure.
1164 * @param enmWhat The phase that completed.
1165 */
1166VMMR3_INT_DECL(int) HMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat)
1167{
1168 switch (enmWhat)
1169 {
1170 case VMINITCOMPLETED_RING3:
1171 return hmR3InitCPU(pVM);
1172 case VMINITCOMPLETED_RING0:
1173 return hmR3InitFinalizeR0(pVM);
1174 default:
1175 return VINF_SUCCESS;
1176 }
1177}
1178
1179
1180/**
1181 * Turns off normal raw mode features.
1182 *
1183 * @param pVM The cross context VM structure.
1184 */
1185static void hmR3DisableRawMode(PVM pVM)
1186{
1187/** @todo r=bird: HM shouldn't be doing this crap. */
1188 /* Reinit the paging mode to force the new shadow mode. */
1189 for (VMCPUID i = 0; i < pVM->cCpus; i++)
1190 {
1191 PVMCPU pVCpu = &pVM->aCpus[i];
1192 PGMHCChangeMode(pVM, pVCpu, PGMMODE_REAL);
1193 }
1194}
1195
1196
1197/**
1198 * Initialize VT-x or AMD-V.
1199 *
1200 * @returns VBox status code.
1201 * @param pVM The cross context VM structure.
1202 */
1203static int hmR3InitFinalizeR0(PVM pVM)
1204{
1205 int rc;
1206
1207 if (!HMIsEnabled(pVM))
1208 return VINF_SUCCESS;
1209
1210 /*
1211 * Hack to allow users to work around broken BIOSes that incorrectly set
1212 * EFER.SVME, which makes us believe somebody else is already using AMD-V.
1213 */
1214 if ( !pVM->hm.s.vmx.fSupported
1215 && !pVM->hm.s.svm.fSupported
1216 && pVM->hm.s.rcInit == VERR_SVM_IN_USE /* implies functional AMD-V */
1217 && RTEnvExist("VBOX_HWVIRTEX_IGNORE_SVM_IN_USE"))
1218 {
1219 LogRel(("HM: VBOX_HWVIRTEX_IGNORE_SVM_IN_USE active!\n"));
1220 pVM->hm.s.svm.fSupported = true;
1221 pVM->hm.s.svm.fIgnoreInUseError = true;
1222 pVM->hm.s.rcInit = VINF_SUCCESS;
1223 }
1224
1225 /*
1226 * Report ring-0 init errors.
1227 */
1228 if ( !pVM->hm.s.vmx.fSupported
1229 && !pVM->hm.s.svm.fSupported)
1230 {
1231 LogRel(("HM: Failed to initialize VT-x / AMD-V: %Rrc\n", pVM->hm.s.rcInit));
1232 LogRel(("HM: VMX MSR_IA32_FEATURE_CONTROL=%RX64\n", pVM->hm.s.vmx.Msrs.u64FeatureCtrl));
1233 switch (pVM->hm.s.rcInit)
1234 {
1235 case VERR_VMX_IN_VMX_ROOT_MODE:
1236 return VM_SET_ERROR(pVM, VERR_VMX_IN_VMX_ROOT_MODE, "VT-x is being used by another hypervisor");
1237 case VERR_VMX_NO_VMX:
1238 return VM_SET_ERROR(pVM, VERR_VMX_NO_VMX, "VT-x is not available");
1239 case VERR_VMX_MSR_VMX_DISABLED:
1240 return VM_SET_ERROR(pVM, VERR_VMX_MSR_VMX_DISABLED, "VT-x is disabled in the BIOS");
1241 case VERR_VMX_MSR_ALL_VMX_DISABLED:
1242 return VM_SET_ERROR(pVM, VERR_VMX_MSR_ALL_VMX_DISABLED, "VT-x is disabled in the BIOS for all CPU modes");
1243 case VERR_VMX_MSR_LOCKING_FAILED:
1244 return VM_SET_ERROR(pVM, VERR_VMX_MSR_LOCKING_FAILED, "Failed to lock VT-x features while trying to enable VT-x");
1245 case VERR_VMX_MSR_VMX_ENABLE_FAILED:
1246 return VM_SET_ERROR(pVM, VERR_VMX_MSR_VMX_ENABLE_FAILED, "Failed to enable VT-x features");
1247 case VERR_VMX_MSR_SMX_VMX_ENABLE_FAILED:
1248 return VM_SET_ERROR(pVM, VERR_VMX_MSR_SMX_VMX_ENABLE_FAILED, "Failed to enable VT-x features in SMX mode");
1249
1250 case VERR_SVM_IN_USE:
1251 return VM_SET_ERROR(pVM, VERR_SVM_IN_USE, "AMD-V is being used by another hypervisor");
1252 case VERR_SVM_NO_SVM:
1253 return VM_SET_ERROR(pVM, VERR_SVM_NO_SVM, "AMD-V is not available");
1254 case VERR_SVM_DISABLED:
1255 return VM_SET_ERROR(pVM, VERR_SVM_DISABLED, "AMD-V is disabled in the BIOS");
1256 }
1257 return VMSetError(pVM, pVM->hm.s.rcInit, RT_SRC_POS, "HM ring-0 init failed: %Rrc", pVM->hm.s.rcInit);
1258 }
1259
1260 /*
1261 * Enable VT-x or AMD-V on all host CPUs.
1262 */
1263 rc = SUPR3CallVMMR0Ex(pVM->pVMR0, 0 /*idCpu*/, VMMR0_DO_HM_ENABLE, 0, NULL);
1264 if (RT_FAILURE(rc))
1265 {
1266 LogRel(("HM: Failed to enable, error %Rrc\n", rc));
1267 HMR3CheckError(pVM, rc);
1268 return rc;
1269 }
1270
1271 /*
1272 * No TPR patching is required when the IO-APIC is not enabled for this VM.
1273 * (Main should have taken care of this already)
1274 */
1275 if (!PDMHasIoApic(pVM))
1276 {
1277 Assert(!pVM->hm.s.fTprPatchingAllowed); /* paranoia */
1278 pVM->hm.s.fTprPatchingAllowed = false;
1279 }
1280
1281 /*
1282 * Sync options.
1283 */
1284 /** @todo Move this out of of CPUMCTX and into some ring-0 only HM structure.
1285 * That will require a little bit of work, of course. */
1286 for (VMCPUID iCpu = 0; iCpu < pVM->cCpus; iCpu++)
1287 {
1288 PVMCPU pVCpu = &pVM->aCpus[iCpu];
1289 PCPUMCTX pCpuCtx = &pVCpu->cpum.GstCtx;
1290 pCpuCtx->fWorldSwitcher &= ~(CPUMCTX_WSF_IBPB_EXIT | CPUMCTX_WSF_IBPB_ENTRY);
1291 if (pVM->cpum.ro.HostFeatures.fIbpb)
1292 {
1293 if (pVM->hm.s.fIbpbOnVmExit)
1294 pCpuCtx->fWorldSwitcher |= CPUMCTX_WSF_IBPB_EXIT;
1295 if (pVM->hm.s.fIbpbOnVmEntry)
1296 pCpuCtx->fWorldSwitcher |= CPUMCTX_WSF_IBPB_ENTRY;
1297 }
1298 if (iCpu == 0)
1299 LogRel(("HM: fWorldSwitcher=%#x (fIbpbOnVmExit=%RTbool fIbpbOnVmEntry=%RTbool)\n",
1300 pCpuCtx->fWorldSwitcher, pVM->hm.s.fIbpbOnVmExit, pVM->hm.s.fIbpbOnVmEntry));
1301 }
1302
1303 /*
1304 * Do the vendor specific initialization
1305 *
1306 * Note! We disable release log buffering here since we're doing relatively
1307 * lot of logging and doesn't want to hit the disk with each LogRel
1308 * statement.
1309 */
1310 AssertLogRelReturn(!pVM->hm.s.fInitialized, VERR_HM_IPE_5);
1311 bool fOldBuffered = RTLogRelSetBuffering(true /*fBuffered*/);
1312 if (pVM->hm.s.vmx.fSupported)
1313 rc = hmR3InitFinalizeR0Intel(pVM);
1314 else
1315 rc = hmR3InitFinalizeR0Amd(pVM);
1316 LogRel(("HM: VT-x/AMD-V init method: %s\n", (pVM->hm.s.fGlobalInit) ? "GLOBAL" : "LOCAL"));
1317 RTLogRelSetBuffering(fOldBuffered);
1318 pVM->hm.s.fInitialized = true;
1319
1320 return rc;
1321}
1322
1323
1324/**
1325 * @callback_method_impl{FNPDMVMMDEVHEAPNOTIFY}
1326 */
1327static DECLCALLBACK(void) hmR3VmmDevHeapNotify(PVM pVM, void *pvAllocation, RTGCPHYS GCPhysAllocation)
1328{
1329 NOREF(pVM);
1330 NOREF(pvAllocation);
1331 NOREF(GCPhysAllocation);
1332}
1333
1334
1335/**
1336 * Finish VT-x initialization (after ring-0 init).
1337 *
1338 * @returns VBox status code.
1339 * @param pVM The cross context VM structure.
1340 */
1341static int hmR3InitFinalizeR0Intel(PVM pVM)
1342{
1343 int rc;
1344
1345 Log(("pVM->hm.s.vmx.fSupported = %d\n", pVM->hm.s.vmx.fSupported));
1346 AssertLogRelReturn(pVM->hm.s.vmx.Msrs.u64FeatureCtrl != 0, VERR_HM_IPE_4);
1347
1348 uint64_t val;
1349 uint64_t zap;
1350
1351 LogRel(("HM: Using VT-x implementation 2.0\n"));
1352 LogRel(("HM: Host CR4 = %#RX64\n", pVM->hm.s.vmx.u64HostCr4));
1353 LogRel(("HM: Host EFER = %#RX64\n", pVM->hm.s.vmx.u64HostEfer));
1354 LogRel(("HM: MSR_IA32_SMM_MONITOR_CTL = %#RX64\n", pVM->hm.s.vmx.u64HostSmmMonitorCtl));
1355 LogRel(("HM: MSR_IA32_FEATURE_CONTROL = %#RX64\n", pVM->hm.s.vmx.Msrs.u64FeatureCtrl));
1356 if (!(pVM->hm.s.vmx.Msrs.u64FeatureCtrl & MSR_IA32_FEATURE_CONTROL_LOCK))
1357 LogRel(("HM: IA32_FEATURE_CONTROL lock bit not set, possibly bad hardware!\n"));
1358 LogRel(("HM: MSR_IA32_VMX_BASIC_INFO = %#RX64\n", pVM->hm.s.vmx.Msrs.u64BasicInfo));
1359 LogRel(("HM: VMCS id = %#x\n", MSR_IA32_VMX_BASIC_INFO_VMCS_ID(pVM->hm.s.vmx.Msrs.u64BasicInfo)));
1360 LogRel(("HM: VMCS size = %u bytes\n", MSR_IA32_VMX_BASIC_INFO_VMCS_SIZE(pVM->hm.s.vmx.Msrs.u64BasicInfo)));
1361 LogRel(("HM: VMCS physical address limit = %s\n", MSR_IA32_VMX_BASIC_INFO_VMCS_PHYS_WIDTH(pVM->hm.s.vmx.Msrs.u64BasicInfo) ? "< 4 GB" : "None"));
1362 LogRel(("HM: VMCS memory type = %#x\n", MSR_IA32_VMX_BASIC_INFO_VMCS_MEM_TYPE(pVM->hm.s.vmx.Msrs.u64BasicInfo)));
1363 LogRel(("HM: Dual-monitor treatment support = %RTbool\n", MSR_IA32_VMX_BASIC_INFO_VMCS_DUAL_MON(pVM->hm.s.vmx.Msrs.u64BasicInfo)));
1364 LogRel(("HM: OUTS & INS instruction-info = %RTbool\n", MSR_IA32_VMX_BASIC_INFO_VMCS_INS_OUTS(pVM->hm.s.vmx.Msrs.u64BasicInfo)));
1365 LogRel(("HM: Supports true capability MSRs = %RTbool\n", MSR_IA32_VMX_BASIC_INFO_TRUE_CONTROLS(pVM->hm.s.vmx.Msrs.u64BasicInfo)));
1366 LogRel(("HM: Max resume loops = %u\n", pVM->hm.s.cMaxResumeLoops));
1367
1368 LogRel(("HM: MSR_IA32_VMX_PINBASED_CTLS = %#RX64\n", pVM->hm.s.vmx.Msrs.VmxPinCtls.u));
1369 val = pVM->hm.s.vmx.Msrs.VmxPinCtls.n.allowed1;
1370 zap = pVM->hm.s.vmx.Msrs.VmxPinCtls.n.disallowed0;
1371 HMVMX_REPORT_FEATURE(val, zap, "EXT_INT_EXIT", VMX_VMCS_CTRL_PIN_EXEC_EXT_INT_EXIT);
1372 HMVMX_REPORT_FEATURE(val, zap, "NMI_EXIT", VMX_VMCS_CTRL_PIN_EXEC_NMI_EXIT);
1373 HMVMX_REPORT_FEATURE(val, zap, "VIRTUAL_NMI", VMX_VMCS_CTRL_PIN_EXEC_VIRTUAL_NMI);
1374 HMVMX_REPORT_FEATURE(val, zap, "PREEMPT_TIMER", VMX_VMCS_CTRL_PIN_EXEC_PREEMPT_TIMER);
1375 HMVMX_REPORT_FEATURE(val, zap, "POSTED_INTR", VMX_VMCS_CTRL_PIN_EXEC_POSTED_INTR);
1376
1377 LogRel(("HM: MSR_IA32_VMX_PROCBASED_CTLS = %#RX64\n", pVM->hm.s.vmx.Msrs.VmxProcCtls.u));
1378 val = pVM->hm.s.vmx.Msrs.VmxProcCtls.n.allowed1;
1379 zap = pVM->hm.s.vmx.Msrs.VmxProcCtls.n.disallowed0;
1380 HMVMX_REPORT_FEATURE(val, zap, "INT_WINDOW_EXIT", VMX_VMCS_CTRL_PROC_EXEC_INT_WINDOW_EXIT);
1381 HMVMX_REPORT_FEATURE(val, zap, "USE_TSC_OFFSETTING", VMX_VMCS_CTRL_PROC_EXEC_USE_TSC_OFFSETTING);
1382 HMVMX_REPORT_FEATURE(val, zap, "HLT_EXIT", VMX_VMCS_CTRL_PROC_EXEC_HLT_EXIT);
1383 HMVMX_REPORT_FEATURE(val, zap, "INVLPG_EXIT", VMX_VMCS_CTRL_PROC_EXEC_INVLPG_EXIT);
1384 HMVMX_REPORT_FEATURE(val, zap, "MWAIT_EXIT", VMX_VMCS_CTRL_PROC_EXEC_MWAIT_EXIT);
1385 HMVMX_REPORT_FEATURE(val, zap, "RDPMC_EXIT", VMX_VMCS_CTRL_PROC_EXEC_RDPMC_EXIT);
1386 HMVMX_REPORT_FEATURE(val, zap, "RDTSC_EXIT", VMX_VMCS_CTRL_PROC_EXEC_RDTSC_EXIT);
1387 HMVMX_REPORT_FEATURE(val, zap, "CR3_LOAD_EXIT", VMX_VMCS_CTRL_PROC_EXEC_CR3_LOAD_EXIT);
1388 HMVMX_REPORT_FEATURE(val, zap, "CR3_STORE_EXIT", VMX_VMCS_CTRL_PROC_EXEC_CR3_STORE_EXIT);
1389 HMVMX_REPORT_FEATURE(val, zap, "CR8_LOAD_EXIT", VMX_VMCS_CTRL_PROC_EXEC_CR8_LOAD_EXIT);
1390 HMVMX_REPORT_FEATURE(val, zap, "CR8_STORE_EXIT", VMX_VMCS_CTRL_PROC_EXEC_CR8_STORE_EXIT);
1391 HMVMX_REPORT_FEATURE(val, zap, "USE_TPR_SHADOW", VMX_VMCS_CTRL_PROC_EXEC_USE_TPR_SHADOW);
1392 HMVMX_REPORT_FEATURE(val, zap, "NMI_WINDOW_EXIT", VMX_VMCS_CTRL_PROC_EXEC_NMI_WINDOW_EXIT);
1393 HMVMX_REPORT_FEATURE(val, zap, "MOV_DR_EXIT", VMX_VMCS_CTRL_PROC_EXEC_MOV_DR_EXIT);
1394 HMVMX_REPORT_FEATURE(val, zap, "UNCOND_IO_EXIT", VMX_VMCS_CTRL_PROC_EXEC_UNCOND_IO_EXIT);
1395 HMVMX_REPORT_FEATURE(val, zap, "USE_IO_BITMAPS", VMX_VMCS_CTRL_PROC_EXEC_USE_IO_BITMAPS);
1396 HMVMX_REPORT_FEATURE(val, zap, "MONITOR_TRAP_FLAG", VMX_VMCS_CTRL_PROC_EXEC_MONITOR_TRAP_FLAG);
1397 HMVMX_REPORT_FEATURE(val, zap, "USE_MSR_BITMAPS", VMX_VMCS_CTRL_PROC_EXEC_USE_MSR_BITMAPS);
1398 HMVMX_REPORT_FEATURE(val, zap, "MONITOR_EXIT", VMX_VMCS_CTRL_PROC_EXEC_MONITOR_EXIT);
1399 HMVMX_REPORT_FEATURE(val, zap, "PAUSE_EXIT", VMX_VMCS_CTRL_PROC_EXEC_PAUSE_EXIT);
1400 HMVMX_REPORT_FEATURE(val, zap, "USE_SECONDARY_EXEC_CTRL", VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL);
1401 if (pVM->hm.s.vmx.Msrs.VmxProcCtls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL)
1402 {
1403 LogRel(("HM: MSR_IA32_VMX_PROCBASED_CTLS2 = %#RX64\n", pVM->hm.s.vmx.Msrs.VmxProcCtls2.u));
1404 val = pVM->hm.s.vmx.Msrs.VmxProcCtls2.n.allowed1;
1405 zap = pVM->hm.s.vmx.Msrs.VmxProcCtls2.n.disallowed0;
1406 HMVMX_REPORT_FEATURE(val, zap, "VIRT_APIC", VMX_VMCS_CTRL_PROC_EXEC2_VIRT_APIC);
1407 HMVMX_REPORT_FEATURE(val, zap, "EPT", VMX_VMCS_CTRL_PROC_EXEC2_EPT);
1408 HMVMX_REPORT_FEATURE(val, zap, "DESCRIPTOR_TABLE_EXIT", VMX_VMCS_CTRL_PROC_EXEC2_DESCRIPTOR_TABLE_EXIT);
1409 HMVMX_REPORT_FEATURE(val, zap, "RDTSCP", VMX_VMCS_CTRL_PROC_EXEC2_RDTSCP);
1410 HMVMX_REPORT_FEATURE(val, zap, "VIRT_X2APIC", VMX_VMCS_CTRL_PROC_EXEC2_VIRT_X2APIC);
1411 HMVMX_REPORT_FEATURE(val, zap, "VPID", VMX_VMCS_CTRL_PROC_EXEC2_VPID);
1412 HMVMX_REPORT_FEATURE(val, zap, "WBINVD_EXIT", VMX_VMCS_CTRL_PROC_EXEC2_WBINVD_EXIT);
1413 HMVMX_REPORT_FEATURE(val, zap, "UNRESTRICTED_GUEST", VMX_VMCS_CTRL_PROC_EXEC2_UNRESTRICTED_GUEST);
1414 HMVMX_REPORT_FEATURE(val, zap, "APIC_REG_VIRT", VMX_VMCS_CTRL_PROC_EXEC2_APIC_REG_VIRT);
1415 HMVMX_REPORT_FEATURE(val, zap, "VIRT_INTR_DELIVERY", VMX_VMCS_CTRL_PROC_EXEC2_VIRT_INTR_DELIVERY);
1416 HMVMX_REPORT_FEATURE(val, zap, "PAUSE_LOOP_EXIT", VMX_VMCS_CTRL_PROC_EXEC2_PAUSE_LOOP_EXIT);
1417 HMVMX_REPORT_FEATURE(val, zap, "RDRAND_EXIT", VMX_VMCS_CTRL_PROC_EXEC2_RDRAND_EXIT);
1418 HMVMX_REPORT_FEATURE(val, zap, "INVPCID", VMX_VMCS_CTRL_PROC_EXEC2_INVPCID);
1419 HMVMX_REPORT_FEATURE(val, zap, "VMFUNC", VMX_VMCS_CTRL_PROC_EXEC2_VMFUNC);
1420 HMVMX_REPORT_FEATURE(val, zap, "VMCS_SHADOWING", VMX_VMCS_CTRL_PROC_EXEC2_VMCS_SHADOWING);
1421 HMVMX_REPORT_FEATURE(val, zap, "ENCLS_EXIT", VMX_VMCS_CTRL_PROC_EXEC2_ENCLS_EXIT);
1422 HMVMX_REPORT_FEATURE(val, zap, "RDSEED_EXIT", VMX_VMCS_CTRL_PROC_EXEC2_RDSEED_EXIT);
1423 HMVMX_REPORT_FEATURE(val, zap, "PML", VMX_VMCS_CTRL_PROC_EXEC2_PML);
1424 HMVMX_REPORT_FEATURE(val, zap, "EPT_VE", VMX_VMCS_CTRL_PROC_EXEC2_EPT_VE);
1425 HMVMX_REPORT_FEATURE(val, zap, "CONCEAL_FROM_PT", VMX_VMCS_CTRL_PROC_EXEC2_CONCEAL_FROM_PT);
1426 HMVMX_REPORT_FEATURE(val, zap, "XSAVES_XRSTORS", VMX_VMCS_CTRL_PROC_EXEC2_XSAVES_XRSTORS);
1427 HMVMX_REPORT_FEATURE(val, zap, "TSC_SCALING", VMX_VMCS_CTRL_PROC_EXEC2_TSC_SCALING);
1428 }
1429
1430 LogRel(("HM: MSR_IA32_VMX_ENTRY_CTLS = %#RX64\n", pVM->hm.s.vmx.Msrs.VmxEntry.u));
1431 val = pVM->hm.s.vmx.Msrs.VmxEntry.n.allowed1;
1432 zap = pVM->hm.s.vmx.Msrs.VmxEntry.n.disallowed0;
1433 HMVMX_REPORT_FEATURE(val, zap, "LOAD_DEBUG", VMX_VMCS_CTRL_ENTRY_LOAD_DEBUG);
1434 HMVMX_REPORT_FEATURE(val, zap, "IA32E_MODE_GUEST", VMX_VMCS_CTRL_ENTRY_IA32E_MODE_GUEST);
1435 HMVMX_REPORT_FEATURE(val, zap, "ENTRY_SMM", VMX_VMCS_CTRL_ENTRY_ENTRY_SMM);
1436 HMVMX_REPORT_FEATURE(val, zap, "DEACTIVATE_DUALMON", VMX_VMCS_CTRL_ENTRY_DEACTIVATE_DUALMON);
1437 HMVMX_REPORT_FEATURE(val, zap, "LOAD_GUEST_PERF_MSR", VMX_VMCS_CTRL_ENTRY_LOAD_GUEST_PERF_MSR);
1438 HMVMX_REPORT_FEATURE(val, zap, "LOAD_GUEST_PAT_MSR", VMX_VMCS_CTRL_ENTRY_LOAD_GUEST_PAT_MSR);
1439 HMVMX_REPORT_FEATURE(val, zap, "LOAD_GUEST_EFER_MSR", VMX_VMCS_CTRL_ENTRY_LOAD_GUEST_EFER_MSR);
1440
1441 LogRel(("HM: MSR_IA32_VMX_EXIT_CTLS = %#RX64\n", pVM->hm.s.vmx.Msrs.VmxExit.u));
1442 val = pVM->hm.s.vmx.Msrs.VmxExit.n.allowed1;
1443 zap = pVM->hm.s.vmx.Msrs.VmxExit.n.disallowed0;
1444 HMVMX_REPORT_FEATURE(val, zap, "SAVE_DEBUG", VMX_VMCS_CTRL_EXIT_SAVE_DEBUG);
1445 HMVMX_REPORT_FEATURE(val, zap, "HOST_ADDR_SPACE_SIZE", VMX_VMCS_CTRL_EXIT_HOST_ADDR_SPACE_SIZE);
1446 HMVMX_REPORT_FEATURE(val, zap, "LOAD_PERF_MSR", VMX_VMCS_CTRL_EXIT_LOAD_PERF_MSR);
1447 HMVMX_REPORT_FEATURE(val, zap, "ACK_EXT_INT", VMX_VMCS_CTRL_EXIT_ACK_EXT_INT);
1448 HMVMX_REPORT_FEATURE(val, zap, "SAVE_GUEST_PAT_MSR", VMX_VMCS_CTRL_EXIT_SAVE_GUEST_PAT_MSR);
1449 HMVMX_REPORT_FEATURE(val, zap, "LOAD_HOST_PAT_MSR", VMX_VMCS_CTRL_EXIT_LOAD_HOST_PAT_MSR);
1450 HMVMX_REPORT_FEATURE(val, zap, "SAVE_GUEST_EFER_MSR", VMX_VMCS_CTRL_EXIT_SAVE_GUEST_EFER_MSR);
1451 HMVMX_REPORT_FEATURE(val, zap, "LOAD_HOST_EFER_MSR", VMX_VMCS_CTRL_EXIT_LOAD_HOST_EFER_MSR);
1452 HMVMX_REPORT_FEATURE(val, zap, "SAVE_VMX_PREEMPT_TIMER", VMX_VMCS_CTRL_EXIT_SAVE_VMX_PREEMPT_TIMER);
1453
1454 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps)
1455 {
1456 val = pVM->hm.s.vmx.Msrs.u64EptVpidCaps;
1457 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP = %#RX64\n", val));
1458 HMVMX_REPORT_MSR_CAPABILITY(val, "RWX_X_ONLY", MSR_IA32_VMX_EPT_VPID_CAP_RWX_X_ONLY);
1459 HMVMX_REPORT_MSR_CAPABILITY(val, "PAGE_WALK_LENGTH_4", MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4);
1460 HMVMX_REPORT_MSR_CAPABILITY(val, "EMT_UC", MSR_IA32_VMX_EPT_VPID_CAP_EMT_UC);
1461 HMVMX_REPORT_MSR_CAPABILITY(val, "EMT_WB", MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB);
1462 HMVMX_REPORT_MSR_CAPABILITY(val, "PDE_2M", MSR_IA32_VMX_EPT_VPID_CAP_PDE_2M);
1463 HMVMX_REPORT_MSR_CAPABILITY(val, "PDPTE_1G", MSR_IA32_VMX_EPT_VPID_CAP_PDPTE_1G);
1464 HMVMX_REPORT_MSR_CAPABILITY(val, "INVEPT", MSR_IA32_VMX_EPT_VPID_CAP_INVEPT);
1465 HMVMX_REPORT_MSR_CAPABILITY(val, "EPT_ACCESS_DIRTY", MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY);
1466 HMVMX_REPORT_MSR_CAPABILITY(val, "INVEPT_SINGLE_CONTEXT", MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT);
1467 HMVMX_REPORT_MSR_CAPABILITY(val, "INVEPT_ALL_CONTEXTS", MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS);
1468 HMVMX_REPORT_MSR_CAPABILITY(val, "INVVPID", MSR_IA32_VMX_EPT_VPID_CAP_INVVPID);
1469 HMVMX_REPORT_MSR_CAPABILITY(val, "INVVPID_INDIV_ADDR", MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
1470 HMVMX_REPORT_MSR_CAPABILITY(val, "INVVPID_SINGLE_CONTEXT", MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT);
1471 HMVMX_REPORT_MSR_CAPABILITY(val, "INVVPID_ALL_CONTEXTS", MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS);
1472 HMVMX_REPORT_MSR_CAPABILITY(val, "INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS", MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS);
1473 }
1474
1475 val = pVM->hm.s.vmx.Msrs.u64Misc;
1476 LogRel(("HM: MSR_IA32_VMX_MISC = %#RX64\n", val));
1477 if (MSR_IA32_VMX_MISC_PREEMPT_TSC_BIT(val) == pVM->hm.s.vmx.cPreemptTimerShift)
1478 LogRel(("HM: PREEMPT_TSC_BIT = %#x\n", MSR_IA32_VMX_MISC_PREEMPT_TSC_BIT(val)));
1479 else
1480 {
1481 LogRel(("HM: PREEMPT_TSC_BIT = %#x - erratum detected, using %#x instead\n",
1482 MSR_IA32_VMX_MISC_PREEMPT_TSC_BIT(val), pVM->hm.s.vmx.cPreemptTimerShift));
1483 }
1484
1485 LogRel(("HM: STORE_EFERLMA_VMEXIT = %RTbool\n", RT_BOOL(MSR_IA32_VMX_MISC_STORE_EFERLMA_VMEXIT(val))));
1486 LogRel(("HM: ACTIVITY_STATES = %#x\n", MSR_IA32_VMX_MISC_ACTIVITY_STATES(val)));
1487 LogRel(("HM: CR3_TARGET = %#x\n", MSR_IA32_VMX_MISC_CR3_TARGET(val)));
1488 LogRel(("HM: MAX_MSR = %u\n", MSR_IA32_VMX_MISC_MAX_MSR(val)));
1489 LogRel(("HM: RDMSR_SMBASE_MSR_SMM = %RTbool\n", RT_BOOL(MSR_IA32_VMX_MISC_RDMSR_SMBASE_MSR_SMM(val))));
1490 LogRel(("HM: SMM_MONITOR_CTL_B2 = %RTbool\n", RT_BOOL(MSR_IA32_VMX_MISC_SMM_MONITOR_CTL_B2(val))));
1491 LogRel(("HM: VMWRITE_VMEXIT_INFO = %RTbool\n", RT_BOOL(MSR_IA32_VMX_MISC_VMWRITE_VMEXIT_INFO(val))));
1492 LogRel(("HM: MSEG_ID = %#x\n", MSR_IA32_VMX_MISC_MSEG_ID(val)));
1493
1494 /* Paranoia */
1495 AssertRelease(MSR_IA32_VMX_MISC_MAX_MSR(pVM->hm.s.vmx.Msrs.u64Misc) >= 512);
1496
1497 LogRel(("HM: MSR_IA32_VMX_CR0_FIXED0 = %#RX64\n", pVM->hm.s.vmx.Msrs.u64Cr0Fixed0));
1498 LogRel(("HM: MSR_IA32_VMX_CR0_FIXED1 = %#RX64\n", pVM->hm.s.vmx.Msrs.u64Cr0Fixed1));
1499 LogRel(("HM: MSR_IA32_VMX_CR4_FIXED0 = %#RX64\n", pVM->hm.s.vmx.Msrs.u64Cr4Fixed0));
1500 LogRel(("HM: MSR_IA32_VMX_CR4_FIXED1 = %#RX64\n", pVM->hm.s.vmx.Msrs.u64Cr4Fixed1));
1501
1502 val = pVM->hm.s.vmx.Msrs.u64VmcsEnum;
1503 LogRel(("HM: MSR_IA32_VMX_VMCS_ENUM = %#RX64\n", val));
1504 LogRel(("HM: HIGHEST_INDEX = %#x\n", MSR_IA32_VMX_VMCS_ENUM_HIGHEST_INDEX(val)));
1505
1506 val = pVM->hm.s.vmx.Msrs.u64Vmfunc;
1507 if (val)
1508 {
1509 LogRel(("HM: MSR_IA32_VMX_VMFUNC = %#RX64\n", val));
1510 HMVMX_REPORT_ALLOWED_FEATURE(val, "EPTP_SWITCHING", VMX_VMCS_CTRL_VMFUNC_EPTP_SWITCHING);
1511 }
1512
1513 LogRel(("HM: APIC-access page physaddr = %#RHp\n", pVM->hm.s.vmx.HCPhysApicAccess));
1514
1515 for (VMCPUID i = 0; i < pVM->cCpus; i++)
1516 {
1517 LogRel(("HM: VCPU%3d: MSR bitmap physaddr = %#RHp\n", i, pVM->aCpus[i].hm.s.vmx.HCPhysMsrBitmap));
1518 LogRel(("HM: VCPU%3d: VMCS physaddr = %#RHp\n", i, pVM->aCpus[i].hm.s.vmx.HCPhysVmcs));
1519 }
1520
1521 /*
1522 * EPT and unhampered guest execution are determined in HMR3Init, verify the sanity of that.
1523 */
1524 AssertLogRelReturn( !pVM->hm.s.fNestedPaging
1525 || (pVM->hm.s.vmx.Msrs.VmxProcCtls2.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC2_EPT),
1526 VERR_HM_IPE_1);
1527 AssertLogRelReturn( !pVM->hm.s.vmx.fUnrestrictedGuest
1528 || ( (pVM->hm.s.vmx.Msrs.VmxProcCtls2.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC2_UNRESTRICTED_GUEST)
1529 && pVM->hm.s.fNestedPaging),
1530 VERR_HM_IPE_1);
1531
1532 /*
1533 * Enable VPID if configured and supported.
1534 */
1535 if (pVM->hm.s.vmx.Msrs.VmxProcCtls2.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC2_VPID)
1536 pVM->hm.s.vmx.fVpid = pVM->hm.s.vmx.fAllowVpid;
1537
1538#if 0
1539 /*
1540 * Enable APIC register virtualization and virtual-interrupt delivery if supported.
1541 */
1542 if ( (pVM->hm.s.vmx.Msrs.VmxProcCtls2.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC2_APIC_REG_VIRT)
1543 && (pVM->hm.s.vmx.Msrs.VmxProcCtls2.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC2_VIRT_INTR_DELIVERY))
1544 pVM->hm.s.fVirtApicRegs = true;
1545
1546 /*
1547 * Enable posted-interrupt processing if supported.
1548 */
1549 /** @todo Add and query IPRT API for host OS support for posted-interrupt IPI
1550 * here. */
1551 if ( (pVM->hm.s.vmx.Msrs.VmxPinCtls.n.allowed1 & VMX_VMCS_CTRL_PIN_EXEC_POSTED_INTR)
1552 && (pVM->hm.s.vmx.Msrs.VmxExit.n.allowed1 & VMX_VMCS_CTRL_EXIT_ACK_EXT_INT))
1553 pVM->hm.s.fPostedIntrs = true;
1554#endif
1555
1556 /*
1557 * Disallow RDTSCP in the guest if there is no secondary process-based VM execution controls as otherwise
1558 * RDTSCP would cause a #UD. There might be no CPUs out there where this happens, as RDTSCP was introduced
1559 * in Nehalems and secondary VM exec. controls should be supported in all of them, but nonetheless it's Intel...
1560 */
1561 if ( !(pVM->hm.s.vmx.Msrs.VmxProcCtls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL)
1562 && CPUMR3GetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_RDTSCP))
1563 {
1564 CPUMR3ClearGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_RDTSCP);
1565 LogRel(("HM: Disabled RDTSCP\n"));
1566 }
1567
1568 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
1569 {
1570 /* Allocate three pages for the TSS we need for real mode emulation. (2 pages for the IO bitmap) */
1571 rc = PDMR3VmmDevHeapAlloc(pVM, HM_VTX_TOTAL_DEVHEAP_MEM, hmR3VmmDevHeapNotify, (RTR3PTR *)&pVM->hm.s.vmx.pRealModeTSS);
1572 if (RT_SUCCESS(rc))
1573 {
1574 /* The IO bitmap starts right after the virtual interrupt redirection bitmap.
1575 Refer Intel spec. 20.3.3 "Software Interrupt Handling in Virtual-8086 mode"
1576 esp. Figure 20-5.*/
1577 ASMMemZero32(pVM->hm.s.vmx.pRealModeTSS, sizeof(*pVM->hm.s.vmx.pRealModeTSS));
1578 pVM->hm.s.vmx.pRealModeTSS->offIoBitmap = sizeof(*pVM->hm.s.vmx.pRealModeTSS);
1579
1580 /* Bit set to 0 means software interrupts are redirected to the
1581 8086 program interrupt handler rather than switching to
1582 protected-mode handler. */
1583 memset(pVM->hm.s.vmx.pRealModeTSS->IntRedirBitmap, 0, sizeof(pVM->hm.s.vmx.pRealModeTSS->IntRedirBitmap));
1584
1585 /* Allow all port IO, so that port IO instructions do not cause
1586 exceptions and would instead cause a VM-exit (based on VT-x's
1587 IO bitmap which we currently configure to always cause an exit). */
1588 memset(pVM->hm.s.vmx.pRealModeTSS + 1, 0, PAGE_SIZE * 2);
1589 *((unsigned char *)pVM->hm.s.vmx.pRealModeTSS + HM_VTX_TSS_SIZE - 2) = 0xff;
1590
1591 /*
1592 * Construct a 1024 element page directory with 4 MB pages for the identity mapped
1593 * page table used in real and protected mode without paging with EPT.
1594 */
1595 pVM->hm.s.vmx.pNonPagingModeEPTPageTable = (PX86PD)((char *)pVM->hm.s.vmx.pRealModeTSS + PAGE_SIZE * 3);
1596 for (uint32_t i = 0; i < X86_PG_ENTRIES; i++)
1597 {
1598 pVM->hm.s.vmx.pNonPagingModeEPTPageTable->a[i].u = _4M * i;
1599 pVM->hm.s.vmx.pNonPagingModeEPTPageTable->a[i].u |= X86_PDE4M_P | X86_PDE4M_RW | X86_PDE4M_US
1600 | X86_PDE4M_A | X86_PDE4M_D | X86_PDE4M_PS
1601 | X86_PDE4M_G;
1602 }
1603
1604 /* We convert it here every time as PCI regions could be reconfigured. */
1605 if (PDMVmmDevHeapIsEnabled(pVM))
1606 {
1607 RTGCPHYS GCPhys;
1608 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
1609 AssertRCReturn(rc, rc);
1610 LogRel(("HM: Real Mode TSS guest physaddr = %#RGp\n", GCPhys));
1611
1612 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
1613 AssertRCReturn(rc, rc);
1614 LogRel(("HM: Non-Paging Mode EPT CR3 = %#RGp\n", GCPhys));
1615 }
1616 }
1617 else
1618 {
1619 LogRel(("HM: No real mode VT-x support (PDMR3VMMDevHeapAlloc returned %Rrc)\n", rc));
1620 pVM->hm.s.vmx.pRealModeTSS = NULL;
1621 pVM->hm.s.vmx.pNonPagingModeEPTPageTable = NULL;
1622 return VMSetError(pVM, rc, RT_SRC_POS,
1623 "HM failure: No real mode VT-x support (PDMR3VMMDevHeapAlloc returned %Rrc)", rc);
1624 }
1625 }
1626
1627 LogRel((pVM->hm.s.fAllow64BitGuests
1628 ? "HM: Guest support: 32-bit and 64-bit\n"
1629 : "HM: Guest support: 32-bit only\n"));
1630
1631 /*
1632 * Call ring-0 to set up the VM.
1633 */
1634 rc = SUPR3CallVMMR0Ex(pVM->pVMR0, 0 /* idCpu */, VMMR0_DO_HM_SETUP_VM, 0 /* u64Arg */, NULL /* pReqHdr */);
1635 if (rc != VINF_SUCCESS)
1636 {
1637 AssertMsgFailed(("%Rrc\n", rc));
1638 LogRel(("HM: VMX setup failed with rc=%Rrc!\n", rc));
1639 for (VMCPUID i = 0; i < pVM->cCpus; i++)
1640 {
1641 PVMCPU pVCpu = &pVM->aCpus[i];
1642 LogRel(("HM: CPU[%u] Last instruction error %#x\n", i, pVCpu->hm.s.vmx.LastError.u32InstrError));
1643 LogRel(("HM: CPU[%u] HM error %#x (%u)\n", i, pVCpu->hm.s.u32HMError, pVCpu->hm.s.u32HMError));
1644 }
1645 HMR3CheckError(pVM, rc);
1646 return VMSetError(pVM, rc, RT_SRC_POS, "VT-x setup failed: %Rrc", rc);
1647 }
1648
1649 LogRel(("HM: Supports VMCS EFER fields = %RTbool\n", pVM->hm.s.vmx.fSupportsVmcsEfer));
1650 LogRel(("HM: Enabled VMX\n"));
1651 pVM->hm.s.vmx.fEnabled = true;
1652
1653 hmR3DisableRawMode(pVM); /** @todo make this go away! */
1654
1655 /*
1656 * Change the CPU features.
1657 */
1658 CPUMR3SetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_SEP);
1659 if (pVM->hm.s.fAllow64BitGuests)
1660 {
1661 CPUMR3SetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_PAE);
1662 CPUMR3SetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_LONG_MODE);
1663 CPUMR3SetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_SYSCALL); /* 64 bits only on Intel CPUs */
1664 CPUMR3SetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_LAHF);
1665 CPUMR3SetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_NX);
1666 }
1667 /* Turn on NXE if PAE has been enabled *and* the host has turned on NXE
1668 (we reuse the host EFER in the switcher). */
1669 /** @todo this needs to be fixed properly!! */
1670 else if (CPUMR3GetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_PAE))
1671 {
1672 if (pVM->hm.s.vmx.u64HostEfer & MSR_K6_EFER_NXE)
1673 CPUMR3SetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_NX);
1674 else
1675 LogRel(("HM: NX not enabled on the host, unavailable to PAE guest\n"));
1676 }
1677
1678 /*
1679 * Log configuration details.
1680 */
1681 if (pVM->hm.s.fNestedPaging)
1682 {
1683 LogRel(("HM: Enabled nested paging\n"));
1684 if (pVM->hm.s.vmx.enmTlbFlushEpt == VMXTLBFLUSHEPT_SINGLE_CONTEXT)
1685 LogRel(("HM: EPT flush type = Single context\n"));
1686 else if (pVM->hm.s.vmx.enmTlbFlushEpt == VMXTLBFLUSHEPT_ALL_CONTEXTS)
1687 LogRel(("HM: EPT flush type = All contexts\n"));
1688 else if (pVM->hm.s.vmx.enmTlbFlushEpt == VMXTLBFLUSHEPT_NOT_SUPPORTED)
1689 LogRel(("HM: EPT flush type = Not supported\n"));
1690 else
1691 LogRel(("HM: EPT flush type = %#x\n", pVM->hm.s.vmx.enmTlbFlushEpt));
1692
1693 if (pVM->hm.s.vmx.fUnrestrictedGuest)
1694 LogRel(("HM: Enabled unrestricted guest execution\n"));
1695
1696#if HC_ARCH_BITS == 64
1697 if (pVM->hm.s.fLargePages)
1698 {
1699 /* Use large (2 MB) pages for our EPT PDEs where possible. */
1700 PGMSetLargePageUsage(pVM, true);
1701 LogRel(("HM: Enabled large page support\n"));
1702 }
1703#endif
1704 }
1705 else
1706 Assert(!pVM->hm.s.vmx.fUnrestrictedGuest);
1707
1708 if (pVM->hm.s.fVirtApicRegs)
1709 LogRel(("HM: Enabled APIC-register virtualization support\n"));
1710
1711 if (pVM->hm.s.fPostedIntrs)
1712 LogRel(("HM: Enabled posted-interrupt processing support\n"));
1713
1714 if (pVM->hm.s.vmx.fVpid)
1715 {
1716 LogRel(("HM: Enabled VPID\n"));
1717 if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_INDIV_ADDR)
1718 LogRel(("HM: VPID flush type = Individual addresses\n"));
1719 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
1720 LogRel(("HM: VPID flush type = Single context\n"));
1721 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
1722 LogRel(("HM: VPID flush type = All contexts\n"));
1723 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
1724 LogRel(("HM: VPID flush type = Single context retain globals\n"));
1725 else
1726 LogRel(("HM: VPID flush type = %#x\n", pVM->hm.s.vmx.enmTlbFlushVpid));
1727 }
1728 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_NOT_SUPPORTED)
1729 LogRel(("HM: Ignoring VPID capabilities of CPU\n"));
1730
1731 if (pVM->hm.s.vmx.fUsePreemptTimer)
1732 LogRel(("HM: Enabled VMX-preemption timer (cPreemptTimerShift=%u)\n", pVM->hm.s.vmx.cPreemptTimerShift));
1733 else
1734 LogRel(("HM: Disabled VMX-preemption timer\n"));
1735
1736 return VINF_SUCCESS;
1737}
1738
1739
1740/**
1741 * Finish AMD-V initialization (after ring-0 init).
1742 *
1743 * @returns VBox status code.
1744 * @param pVM The cross context VM structure.
1745 */
1746static int hmR3InitFinalizeR0Amd(PVM pVM)
1747{
1748 Log(("pVM->hm.s.svm.fSupported = %d\n", pVM->hm.s.svm.fSupported));
1749
1750 LogRel(("HM: Using AMD-V implementation 2.0\n"));
1751
1752 uint32_t u32Family;
1753 uint32_t u32Model;
1754 uint32_t u32Stepping;
1755 if (HMAmdIsSubjectToErratum170(&u32Family, &u32Model, &u32Stepping))
1756 LogRel(("HM: AMD Cpu with erratum 170 family %#x model %#x stepping %#x\n", u32Family, u32Model, u32Stepping));
1757 LogRel(("HM: Max resume loops = %u\n", pVM->hm.s.cMaxResumeLoops));
1758 LogRel(("HM: CPUID 0x80000001.u32AMDFeatureECX = %#RX32\n", pVM->hm.s.cpuid.u32AMDFeatureECX));
1759 LogRel(("HM: CPUID 0x80000001.u32AMDFeatureEDX = %#RX32\n", pVM->hm.s.cpuid.u32AMDFeatureEDX));
1760 LogRel(("HM: AMD HWCR MSR = %#RX64\n", pVM->hm.s.svm.u64MsrHwcr));
1761 LogRel(("HM: AMD-V revision = %#x\n", pVM->hm.s.svm.u32Rev));
1762 LogRel(("HM: AMD-V max ASID = %RU32\n", pVM->hm.s.uMaxAsid));
1763 LogRel(("HM: AMD-V features = %#x\n", pVM->hm.s.svm.u32Features));
1764
1765 /*
1766 * Enumerate AMD-V features.
1767 */
1768 static const struct { uint32_t fFlag; const char *pszName; } s_aSvmFeatures[] =
1769 {
1770#define HMSVM_REPORT_FEATURE(a_StrDesc, a_Define) { a_Define, a_StrDesc }
1771 HMSVM_REPORT_FEATURE("NESTED_PAGING", X86_CPUID_SVM_FEATURE_EDX_NESTED_PAGING),
1772 HMSVM_REPORT_FEATURE("LBR_VIRT", X86_CPUID_SVM_FEATURE_EDX_LBR_VIRT),
1773 HMSVM_REPORT_FEATURE("SVM_LOCK", X86_CPUID_SVM_FEATURE_EDX_SVM_LOCK),
1774 HMSVM_REPORT_FEATURE("NRIP_SAVE", X86_CPUID_SVM_FEATURE_EDX_NRIP_SAVE),
1775 HMSVM_REPORT_FEATURE("TSC_RATE_MSR", X86_CPUID_SVM_FEATURE_EDX_TSC_RATE_MSR),
1776 HMSVM_REPORT_FEATURE("VMCB_CLEAN", X86_CPUID_SVM_FEATURE_EDX_VMCB_CLEAN),
1777 HMSVM_REPORT_FEATURE("FLUSH_BY_ASID", X86_CPUID_SVM_FEATURE_EDX_FLUSH_BY_ASID),
1778 HMSVM_REPORT_FEATURE("DECODE_ASSISTS", X86_CPUID_SVM_FEATURE_EDX_DECODE_ASSISTS),
1779 HMSVM_REPORT_FEATURE("PAUSE_FILTER", X86_CPUID_SVM_FEATURE_EDX_PAUSE_FILTER),
1780 HMSVM_REPORT_FEATURE("PAUSE_FILTER_THRESHOLD", X86_CPUID_SVM_FEATURE_EDX_PAUSE_FILTER_THRESHOLD),
1781 HMSVM_REPORT_FEATURE("AVIC", X86_CPUID_SVM_FEATURE_EDX_AVIC),
1782 HMSVM_REPORT_FEATURE("VIRT_VMSAVE_VMLOAD", X86_CPUID_SVM_FEATURE_EDX_VIRT_VMSAVE_VMLOAD),
1783 HMSVM_REPORT_FEATURE("VGIF", X86_CPUID_SVM_FEATURE_EDX_VGIF),
1784#undef HMSVM_REPORT_FEATURE
1785 };
1786
1787 uint32_t fSvmFeatures = pVM->hm.s.svm.u32Features;
1788 for (unsigned i = 0; i < RT_ELEMENTS(s_aSvmFeatures); i++)
1789 if (fSvmFeatures & s_aSvmFeatures[i].fFlag)
1790 {
1791 LogRel(("HM: %s\n", s_aSvmFeatures[i].pszName));
1792 fSvmFeatures &= ~s_aSvmFeatures[i].fFlag;
1793 }
1794 if (fSvmFeatures)
1795 for (unsigned iBit = 0; iBit < 32; iBit++)
1796 if (RT_BIT_32(iBit) & fSvmFeatures)
1797 LogRel(("HM: Reserved bit %u\n", iBit));
1798
1799 /*
1800 * Nested paging is determined in HMR3Init, verify the sanity of that.
1801 */
1802 AssertLogRelReturn( !pVM->hm.s.fNestedPaging
1803 || (pVM->hm.s.svm.u32Features & X86_CPUID_SVM_FEATURE_EDX_NESTED_PAGING),
1804 VERR_HM_IPE_1);
1805
1806#if 0
1807 /** @todo Add and query IPRT API for host OS support for posted-interrupt IPI
1808 * here. */
1809 if (RTR0IsPostIpiSupport())
1810 pVM->hm.s.fPostedIntrs = true;
1811#endif
1812
1813 /*
1814 * Call ring-0 to set up the VM.
1815 */
1816 int rc = SUPR3CallVMMR0Ex(pVM->pVMR0, 0 /*idCpu*/, VMMR0_DO_HM_SETUP_VM, 0, NULL);
1817 if (rc != VINF_SUCCESS)
1818 {
1819 AssertMsgFailed(("%Rrc\n", rc));
1820 LogRel(("HM: AMD-V setup failed with rc=%Rrc!\n", rc));
1821 return VMSetError(pVM, rc, RT_SRC_POS, "AMD-V setup failed: %Rrc", rc);
1822 }
1823
1824 LogRel(("HM: Enabled SVM\n"));
1825 pVM->hm.s.svm.fEnabled = true;
1826
1827 if (pVM->hm.s.fNestedPaging)
1828 {
1829 LogRel(("HM: Enabled nested paging\n"));
1830
1831 /*
1832 * Enable large pages (2 MB) if applicable.
1833 */
1834#if HC_ARCH_BITS == 64
1835 if (pVM->hm.s.fLargePages)
1836 {
1837 PGMSetLargePageUsage(pVM, true);
1838 LogRel(("HM: Enabled large page support\n"));
1839 }
1840#endif
1841 }
1842
1843 if (pVM->hm.s.fVirtApicRegs)
1844 LogRel(("HM: Enabled APIC-register virtualization support\n"));
1845
1846 if (pVM->hm.s.fPostedIntrs)
1847 LogRel(("HM: Enabled posted-interrupt processing support\n"));
1848
1849 hmR3DisableRawMode(pVM);
1850
1851 /*
1852 * Change the CPU features.
1853 */
1854 CPUMR3SetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_SEP);
1855 CPUMR3SetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_SYSCALL);
1856 if (pVM->hm.s.fAllow64BitGuests)
1857 {
1858 CPUMR3SetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_PAE);
1859 CPUMR3SetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_LONG_MODE);
1860 CPUMR3SetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_NX);
1861 CPUMR3SetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_LAHF);
1862 }
1863 /* Turn on NXE if PAE has been enabled. */
1864 else if (CPUMR3GetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_PAE))
1865 CPUMR3SetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_NX);
1866
1867 LogRel(("HM: %s TPR patching\n", (pVM->hm.s.fTprPatchingAllowed) ? "Enabled" : "Disabled"));
1868
1869 LogRel((pVM->hm.s.fAllow64BitGuests
1870 ? "HM: Guest support: 32-bit and 64-bit\n"
1871 : "HM: Guest support: 32-bit only\n"));
1872
1873 return VINF_SUCCESS;
1874}
1875
1876
1877/**
1878 * Applies relocations to data and code managed by this
1879 * component. This function will be called at init and
1880 * whenever the VMM need to relocate it self inside the GC.
1881 *
1882 * @param pVM The cross context VM structure.
1883 */
1884VMMR3_INT_DECL(void) HMR3Relocate(PVM pVM)
1885{
1886 Log(("HMR3Relocate to %RGv\n", MMHyperGetArea(pVM, 0)));
1887
1888 /* Fetch the current paging mode during the relocate callback during state loading. */
1889 if (VMR3GetState(pVM) == VMSTATE_LOADING)
1890 {
1891 for (VMCPUID i = 0; i < pVM->cCpus; i++)
1892 {
1893 PVMCPU pVCpu = &pVM->aCpus[i];
1894 pVCpu->hm.s.enmShadowMode = PGMGetShadowMode(pVCpu);
1895 }
1896 }
1897#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
1898 if (HMIsEnabled(pVM))
1899 {
1900 switch (PGMGetHostMode(pVM))
1901 {
1902 case PGMMODE_32_BIT:
1903 pVM->hm.s.pfnHost32ToGuest64R0 = VMMR3GetHostToGuestSwitcher(pVM, VMMSWITCHER_32_TO_AMD64);
1904 break;
1905
1906 case PGMMODE_PAE:
1907 case PGMMODE_PAE_NX:
1908 pVM->hm.s.pfnHost32ToGuest64R0 = VMMR3GetHostToGuestSwitcher(pVM, VMMSWITCHER_PAE_TO_AMD64);
1909 break;
1910
1911 default:
1912 AssertFailed();
1913 break;
1914 }
1915 }
1916#endif
1917 return;
1918}
1919
1920
1921/**
1922 * Terminates the HM.
1923 *
1924 * Termination means cleaning up and freeing all resources,
1925 * the VM itself is, at this point, powered off or suspended.
1926 *
1927 * @returns VBox status code.
1928 * @param pVM The cross context VM structure.
1929 */
1930VMMR3_INT_DECL(int) HMR3Term(PVM pVM)
1931{
1932 if (pVM->hm.s.vmx.pRealModeTSS)
1933 {
1934 PDMR3VmmDevHeapFree(pVM, pVM->hm.s.vmx.pRealModeTSS);
1935 pVM->hm.s.vmx.pRealModeTSS = 0;
1936 }
1937 hmR3TermCPU(pVM);
1938 return 0;
1939}
1940
1941
1942/**
1943 * Terminates the per-VCPU HM.
1944 *
1945 * @returns VBox status code.
1946 * @param pVM The cross context VM structure.
1947 */
1948static int hmR3TermCPU(PVM pVM)
1949{
1950 for (VMCPUID i = 0; i < pVM->cCpus; i++)
1951 {
1952 PVMCPU pVCpu = &pVM->aCpus[i]; NOREF(pVCpu);
1953
1954#ifdef VBOX_WITH_STATISTICS
1955 if (pVCpu->hm.s.paStatExitReason)
1956 {
1957 MMHyperFree(pVM, pVCpu->hm.s.paStatExitReason);
1958 pVCpu->hm.s.paStatExitReason = NULL;
1959 pVCpu->hm.s.paStatExitReasonR0 = NIL_RTR0PTR;
1960 }
1961 if (pVCpu->hm.s.paStatInjectedIrqs)
1962 {
1963 MMHyperFree(pVM, pVCpu->hm.s.paStatInjectedIrqs);
1964 pVCpu->hm.s.paStatInjectedIrqs = NULL;
1965 pVCpu->hm.s.paStatInjectedIrqsR0 = NIL_RTR0PTR;
1966 }
1967#endif
1968
1969#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1970 memset(pVCpu->hm.s.vmx.VMCSCache.aMagic, 0, sizeof(pVCpu->hm.s.vmx.VMCSCache.aMagic));
1971 pVCpu->hm.s.vmx.VMCSCache.uMagic = 0;
1972 pVCpu->hm.s.vmx.VMCSCache.uPos = 0xffffffff;
1973#endif
1974 }
1975 return 0;
1976}
1977
1978
1979/**
1980 * Resets a virtual CPU.
1981 *
1982 * Used by HMR3Reset and CPU hot plugging.
1983 *
1984 * @param pVCpu The cross context virtual CPU structure to reset.
1985 */
1986VMMR3_INT_DECL(void) HMR3ResetCpu(PVMCPU pVCpu)
1987{
1988 /* Sync. entire state on VM reset R0-reentry. It's safe to reset
1989 the HM flags here, all other EMTs are in ring-3. See VMR3Reset(). */
1990 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT | HM_CHANGED_ALL_GUEST;
1991
1992 pVCpu->hm.s.fActive = false;
1993 pVCpu->hm.s.Event.fPending = false;
1994 pVCpu->hm.s.vmx.fWasInRealMode = true;
1995 pVCpu->hm.s.vmx.u64MsrApicBase = 0;
1996 pVCpu->hm.s.vmx.fSwitchedTo64on32 = false;
1997
1998 /* Reset the contents of the read cache. */
1999 PVMCSCACHE pCache = &pVCpu->hm.s.vmx.VMCSCache;
2000 for (unsigned j = 0; j < pCache->Read.cValidEntries; j++)
2001 pCache->Read.aFieldVal[j] = 0;
2002
2003#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2004 /* Magic marker for searching in crash dumps. */
2005 strcpy((char *)pCache->aMagic, "VMCSCACHE Magic");
2006 pCache->uMagic = UINT64_C(0xDEADBEEFDEADBEEF);
2007#endif
2008}
2009
2010
2011/**
2012 * The VM is being reset.
2013 *
2014 * For the HM component this means that any GDT/LDT/TSS monitors
2015 * needs to be removed.
2016 *
2017 * @param pVM The cross context VM structure.
2018 */
2019VMMR3_INT_DECL(void) HMR3Reset(PVM pVM)
2020{
2021 LogFlow(("HMR3Reset:\n"));
2022
2023 if (HMIsEnabled(pVM))
2024 hmR3DisableRawMode(pVM);
2025
2026 for (VMCPUID i = 0; i < pVM->cCpus; i++)
2027 {
2028 PVMCPU pVCpu = &pVM->aCpus[i];
2029
2030 HMR3ResetCpu(pVCpu);
2031 }
2032
2033 /* Clear all patch information. */
2034 pVM->hm.s.pGuestPatchMem = 0;
2035 pVM->hm.s.pFreeGuestPatchMem = 0;
2036 pVM->hm.s.cbGuestPatchMem = 0;
2037 pVM->hm.s.cPatches = 0;
2038 pVM->hm.s.PatchTree = 0;
2039 pVM->hm.s.fTPRPatchingActive = false;
2040 ASMMemZero32(pVM->hm.s.aPatches, sizeof(pVM->hm.s.aPatches));
2041}
2042
2043
2044/**
2045 * Callback to patch a TPR instruction (vmmcall or mov cr8).
2046 *
2047 * @returns VBox strict status code.
2048 * @param pVM The cross context VM structure.
2049 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
2050 * @param pvUser Unused.
2051 */
2052static DECLCALLBACK(VBOXSTRICTRC) hmR3RemovePatches(PVM pVM, PVMCPU pVCpu, void *pvUser)
2053{
2054 VMCPUID idCpu = (VMCPUID)(uintptr_t)pvUser;
2055
2056 /* Only execute the handler on the VCPU the original patch request was issued. */
2057 if (pVCpu->idCpu != idCpu)
2058 return VINF_SUCCESS;
2059
2060 Log(("hmR3RemovePatches\n"));
2061 for (unsigned i = 0; i < pVM->hm.s.cPatches; i++)
2062 {
2063 uint8_t abInstr[15];
2064 PHMTPRPATCH pPatch = &pVM->hm.s.aPatches[i];
2065 RTGCPTR pInstrGC = (RTGCPTR)pPatch->Core.Key;
2066 int rc;
2067
2068#ifdef LOG_ENABLED
2069 char szOutput[256];
2070 rc = DBGFR3DisasInstrEx(pVM->pUVM, pVCpu->idCpu, CPUMGetGuestCS(pVCpu), pInstrGC, DBGF_DISAS_FLAGS_DEFAULT_MODE,
2071 szOutput, sizeof(szOutput), NULL);
2072 if (RT_SUCCESS(rc))
2073 Log(("Patched instr: %s\n", szOutput));
2074#endif
2075
2076 /* Check if the instruction is still the same. */
2077 rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pInstrGC, pPatch->cbNewOp);
2078 if (rc != VINF_SUCCESS)
2079 {
2080 Log(("Patched code removed? (rc=%Rrc0\n", rc));
2081 continue; /* swapped out or otherwise removed; skip it. */
2082 }
2083
2084 if (memcmp(abInstr, pPatch->aNewOpcode, pPatch->cbNewOp))
2085 {
2086 Log(("Patched instruction was changed! (rc=%Rrc0\n", rc));
2087 continue; /* skip it. */
2088 }
2089
2090 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pInstrGC, pPatch->aOpcode, pPatch->cbOp);
2091 AssertRC(rc);
2092
2093#ifdef LOG_ENABLED
2094 rc = DBGFR3DisasInstrEx(pVM->pUVM, pVCpu->idCpu, CPUMGetGuestCS(pVCpu), pInstrGC, DBGF_DISAS_FLAGS_DEFAULT_MODE,
2095 szOutput, sizeof(szOutput), NULL);
2096 if (RT_SUCCESS(rc))
2097 Log(("Original instr: %s\n", szOutput));
2098#endif
2099 }
2100 pVM->hm.s.cPatches = 0;
2101 pVM->hm.s.PatchTree = 0;
2102 pVM->hm.s.pFreeGuestPatchMem = pVM->hm.s.pGuestPatchMem;
2103 pVM->hm.s.fTPRPatchingActive = false;
2104 return VINF_SUCCESS;
2105}
2106
2107
2108/**
2109 * Worker for enabling patching in a VT-x/AMD-V guest.
2110 *
2111 * @returns VBox status code.
2112 * @param pVM The cross context VM structure.
2113 * @param idCpu VCPU to execute hmR3RemovePatches on.
2114 * @param pPatchMem Patch memory range.
2115 * @param cbPatchMem Size of the memory range.
2116 */
2117static int hmR3EnablePatching(PVM pVM, VMCPUID idCpu, RTRCPTR pPatchMem, unsigned cbPatchMem)
2118{
2119 int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONE_BY_ONE, hmR3RemovePatches, (void *)(uintptr_t)idCpu);
2120 AssertRC(rc);
2121
2122 pVM->hm.s.pGuestPatchMem = pPatchMem;
2123 pVM->hm.s.pFreeGuestPatchMem = pPatchMem;
2124 pVM->hm.s.cbGuestPatchMem = cbPatchMem;
2125 return VINF_SUCCESS;
2126}
2127
2128
2129/**
2130 * Enable patching in a VT-x/AMD-V guest
2131 *
2132 * @returns VBox status code.
2133 * @param pVM The cross context VM structure.
2134 * @param pPatchMem Patch memory range.
2135 * @param cbPatchMem Size of the memory range.
2136 */
2137VMMR3_INT_DECL(int) HMR3EnablePatching(PVM pVM, RTGCPTR pPatchMem, unsigned cbPatchMem)
2138{
2139 VM_ASSERT_EMT(pVM);
2140 Log(("HMR3EnablePatching %RGv size %x\n", pPatchMem, cbPatchMem));
2141 if (pVM->cCpus > 1)
2142 {
2143 /* We own the IOM lock here and could cause a deadlock by waiting for a VCPU that is blocking on the IOM lock. */
2144 int rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE,
2145 (PFNRT)hmR3EnablePatching, 4, pVM, VMMGetCpuId(pVM), (RTRCPTR)pPatchMem, cbPatchMem);
2146 AssertRC(rc);
2147 return rc;
2148 }
2149 return hmR3EnablePatching(pVM, VMMGetCpuId(pVM), (RTRCPTR)pPatchMem, cbPatchMem);
2150}
2151
2152
2153/**
2154 * Disable patching in a VT-x/AMD-V guest.
2155 *
2156 * @returns VBox status code.
2157 * @param pVM The cross context VM structure.
2158 * @param pPatchMem Patch memory range.
2159 * @param cbPatchMem Size of the memory range.
2160 */
2161VMMR3_INT_DECL(int) HMR3DisablePatching(PVM pVM, RTGCPTR pPatchMem, unsigned cbPatchMem)
2162{
2163 Log(("HMR3DisablePatching %RGv size %x\n", pPatchMem, cbPatchMem));
2164 RT_NOREF2(pPatchMem, cbPatchMem);
2165
2166 Assert(pVM->hm.s.pGuestPatchMem == pPatchMem);
2167 Assert(pVM->hm.s.cbGuestPatchMem == cbPatchMem);
2168
2169 /** @todo Potential deadlock when other VCPUs are waiting on the IOM lock (we own it)!! */
2170 int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONE_BY_ONE, hmR3RemovePatches,
2171 (void *)(uintptr_t)VMMGetCpuId(pVM));
2172 AssertRC(rc);
2173
2174 pVM->hm.s.pGuestPatchMem = 0;
2175 pVM->hm.s.pFreeGuestPatchMem = 0;
2176 pVM->hm.s.cbGuestPatchMem = 0;
2177 pVM->hm.s.fTPRPatchingActive = false;
2178 return VINF_SUCCESS;
2179}
2180
2181
2182/**
2183 * Callback to patch a TPR instruction (vmmcall or mov cr8).
2184 *
2185 * @returns VBox strict status code.
2186 * @param pVM The cross context VM structure.
2187 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
2188 * @param pvUser User specified CPU context.
2189 *
2190 */
2191static DECLCALLBACK(VBOXSTRICTRC) hmR3ReplaceTprInstr(PVM pVM, PVMCPU pVCpu, void *pvUser)
2192{
2193 /*
2194 * Only execute the handler on the VCPU the original patch request was
2195 * issued. (The other CPU(s) might not yet have switched to protected
2196 * mode, nor have the correct memory context.)
2197 */
2198 VMCPUID idCpu = (VMCPUID)(uintptr_t)pvUser;
2199 if (pVCpu->idCpu != idCpu)
2200 return VINF_SUCCESS;
2201
2202 /*
2203 * We're racing other VCPUs here, so don't try patch the instruction twice
2204 * and make sure there is still room for our patch record.
2205 */
2206 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2207 PHMTPRPATCH pPatch = (PHMTPRPATCH)RTAvloU32Get(&pVM->hm.s.PatchTree, (AVLOU32KEY)pCtx->eip);
2208 if (pPatch)
2209 {
2210 Log(("hmR3ReplaceTprInstr: already patched %RGv\n", pCtx->rip));
2211 return VINF_SUCCESS;
2212 }
2213 uint32_t const idx = pVM->hm.s.cPatches;
2214 if (idx >= RT_ELEMENTS(pVM->hm.s.aPatches))
2215 {
2216 Log(("hmR3ReplaceTprInstr: no available patch slots (%RGv)\n", pCtx->rip));
2217 return VINF_SUCCESS;
2218 }
2219 pPatch = &pVM->hm.s.aPatches[idx];
2220
2221 Log(("hmR3ReplaceTprInstr: rip=%RGv idxPatch=%u\n", pCtx->rip, idx));
2222
2223 /*
2224 * Disassembler the instruction and get cracking.
2225 */
2226 DBGFR3_DISAS_INSTR_CUR_LOG(pVCpu, "hmR3ReplaceTprInstr");
2227 PDISCPUSTATE pDis = &pVCpu->hm.s.DisState;
2228 uint32_t cbOp;
2229 int rc = EMInterpretDisasCurrent(pVM, pVCpu, pDis, &cbOp);
2230 AssertRC(rc);
2231 if ( rc == VINF_SUCCESS
2232 && pDis->pCurInstr->uOpcode == OP_MOV
2233 && cbOp >= 3)
2234 {
2235 static uint8_t const s_abVMMCall[3] = { 0x0f, 0x01, 0xd9 };
2236
2237 rc = PGMPhysSimpleReadGCPtr(pVCpu, pPatch->aOpcode, pCtx->rip, cbOp);
2238 AssertRC(rc);
2239
2240 pPatch->cbOp = cbOp;
2241
2242 if (pDis->Param1.fUse == DISUSE_DISPLACEMENT32)
2243 {
2244 /* write. */
2245 if (pDis->Param2.fUse == DISUSE_REG_GEN32)
2246 {
2247 pPatch->enmType = HMTPRINSTR_WRITE_REG;
2248 pPatch->uSrcOperand = pDis->Param2.Base.idxGenReg;
2249 Log(("hmR3ReplaceTprInstr: HMTPRINSTR_WRITE_REG %u\n", pDis->Param2.Base.idxGenReg));
2250 }
2251 else
2252 {
2253 Assert(pDis->Param2.fUse == DISUSE_IMMEDIATE32);
2254 pPatch->enmType = HMTPRINSTR_WRITE_IMM;
2255 pPatch->uSrcOperand = pDis->Param2.uValue;
2256 Log(("hmR3ReplaceTprInstr: HMTPRINSTR_WRITE_IMM %#llx\n", pDis->Param2.uValue));
2257 }
2258 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, s_abVMMCall, sizeof(s_abVMMCall));
2259 AssertRC(rc);
2260
2261 memcpy(pPatch->aNewOpcode, s_abVMMCall, sizeof(s_abVMMCall));
2262 pPatch->cbNewOp = sizeof(s_abVMMCall);
2263 STAM_COUNTER_INC(&pVM->hm.s.StatTprReplaceSuccessVmc);
2264 }
2265 else
2266 {
2267 /*
2268 * TPR Read.
2269 *
2270 * Found:
2271 * mov eax, dword [fffe0080] (5 bytes)
2272 * Check if next instruction is:
2273 * shr eax, 4
2274 */
2275 Assert(pDis->Param1.fUse == DISUSE_REG_GEN32);
2276
2277 uint8_t const idxMmioReg = pDis->Param1.Base.idxGenReg;
2278 uint8_t const cbOpMmio = cbOp;
2279 uint64_t const uSavedRip = pCtx->rip;
2280
2281 pCtx->rip += cbOp;
2282 rc = EMInterpretDisasCurrent(pVM, pVCpu, pDis, &cbOp);
2283 DBGFR3_DISAS_INSTR_CUR_LOG(pVCpu, "Following read");
2284 pCtx->rip = uSavedRip;
2285
2286 if ( rc == VINF_SUCCESS
2287 && pDis->pCurInstr->uOpcode == OP_SHR
2288 && pDis->Param1.fUse == DISUSE_REG_GEN32
2289 && pDis->Param1.Base.idxGenReg == idxMmioReg
2290 && pDis->Param2.fUse == DISUSE_IMMEDIATE8
2291 && pDis->Param2.uValue == 4
2292 && cbOpMmio + cbOp < sizeof(pVM->hm.s.aPatches[idx].aOpcode))
2293 {
2294 uint8_t abInstr[15];
2295
2296 /* Replacing the two instructions above with an AMD-V specific lock-prefixed 32-bit MOV CR8 instruction so as to
2297 access CR8 in 32-bit mode and not cause a #VMEXIT. */
2298 rc = PGMPhysSimpleReadGCPtr(pVCpu, &pPatch->aOpcode, pCtx->rip, cbOpMmio + cbOp);
2299 AssertRC(rc);
2300
2301 pPatch->cbOp = cbOpMmio + cbOp;
2302
2303 /* 0xF0, 0x0F, 0x20, 0xC0 = mov eax, cr8 */
2304 abInstr[0] = 0xF0;
2305 abInstr[1] = 0x0F;
2306 abInstr[2] = 0x20;
2307 abInstr[3] = 0xC0 | pDis->Param1.Base.idxGenReg;
2308 for (unsigned i = 4; i < pPatch->cbOp; i++)
2309 abInstr[i] = 0x90; /* nop */
2310
2311 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, abInstr, pPatch->cbOp);
2312 AssertRC(rc);
2313
2314 memcpy(pPatch->aNewOpcode, abInstr, pPatch->cbOp);
2315 pPatch->cbNewOp = pPatch->cbOp;
2316 STAM_COUNTER_INC(&pVM->hm.s.StatTprReplaceSuccessCr8);
2317
2318 Log(("Acceptable read/shr candidate!\n"));
2319 pPatch->enmType = HMTPRINSTR_READ_SHR4;
2320 }
2321 else
2322 {
2323 pPatch->enmType = HMTPRINSTR_READ;
2324 pPatch->uDstOperand = idxMmioReg;
2325
2326 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, s_abVMMCall, sizeof(s_abVMMCall));
2327 AssertRC(rc);
2328
2329 memcpy(pPatch->aNewOpcode, s_abVMMCall, sizeof(s_abVMMCall));
2330 pPatch->cbNewOp = sizeof(s_abVMMCall);
2331 STAM_COUNTER_INC(&pVM->hm.s.StatTprReplaceSuccessVmc);
2332 Log(("hmR3ReplaceTprInstr: HMTPRINSTR_READ %u\n", pPatch->uDstOperand));
2333 }
2334 }
2335
2336 pPatch->Core.Key = pCtx->eip;
2337 rc = RTAvloU32Insert(&pVM->hm.s.PatchTree, &pPatch->Core);
2338 AssertRC(rc);
2339
2340 pVM->hm.s.cPatches++;
2341 return VINF_SUCCESS;
2342 }
2343
2344 /*
2345 * Save invalid patch, so we will not try again.
2346 */
2347 Log(("hmR3ReplaceTprInstr: Failed to patch instr!\n"));
2348 pPatch->Core.Key = pCtx->eip;
2349 pPatch->enmType = HMTPRINSTR_INVALID;
2350 rc = RTAvloU32Insert(&pVM->hm.s.PatchTree, &pPatch->Core);
2351 AssertRC(rc);
2352 pVM->hm.s.cPatches++;
2353 STAM_COUNTER_INC(&pVM->hm.s.StatTprReplaceFailure);
2354 return VINF_SUCCESS;
2355}
2356
2357
2358/**
2359 * Callback to patch a TPR instruction (jump to generated code).
2360 *
2361 * @returns VBox strict status code.
2362 * @param pVM The cross context VM structure.
2363 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
2364 * @param pvUser User specified CPU context.
2365 *
2366 */
2367static DECLCALLBACK(VBOXSTRICTRC) hmR3PatchTprInstr(PVM pVM, PVMCPU pVCpu, void *pvUser)
2368{
2369 /*
2370 * Only execute the handler on the VCPU the original patch request was
2371 * issued. (The other CPU(s) might not yet have switched to protected
2372 * mode, nor have the correct memory context.)
2373 */
2374 VMCPUID idCpu = (VMCPUID)(uintptr_t)pvUser;
2375 if (pVCpu->idCpu != idCpu)
2376 return VINF_SUCCESS;
2377
2378 /*
2379 * We're racing other VCPUs here, so don't try patch the instruction twice
2380 * and make sure there is still room for our patch record.
2381 */
2382 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2383 PHMTPRPATCH pPatch = (PHMTPRPATCH)RTAvloU32Get(&pVM->hm.s.PatchTree, (AVLOU32KEY)pCtx->eip);
2384 if (pPatch)
2385 {
2386 Log(("hmR3PatchTprInstr: already patched %RGv\n", pCtx->rip));
2387 return VINF_SUCCESS;
2388 }
2389 uint32_t const idx = pVM->hm.s.cPatches;
2390 if (idx >= RT_ELEMENTS(pVM->hm.s.aPatches))
2391 {
2392 Log(("hmR3PatchTprInstr: no available patch slots (%RGv)\n", pCtx->rip));
2393 return VINF_SUCCESS;
2394 }
2395 pPatch = &pVM->hm.s.aPatches[idx];
2396
2397 Log(("hmR3PatchTprInstr: rip=%RGv idxPatch=%u\n", pCtx->rip, idx));
2398 DBGFR3_DISAS_INSTR_CUR_LOG(pVCpu, "hmR3PatchTprInstr");
2399
2400 /*
2401 * Disassemble the instruction and get cracking.
2402 */
2403 PDISCPUSTATE pDis = &pVCpu->hm.s.DisState;
2404 uint32_t cbOp;
2405 int rc = EMInterpretDisasCurrent(pVM, pVCpu, pDis, &cbOp);
2406 AssertRC(rc);
2407 if ( rc == VINF_SUCCESS
2408 && pDis->pCurInstr->uOpcode == OP_MOV
2409 && cbOp >= 5)
2410 {
2411 uint8_t aPatch[64];
2412 uint32_t off = 0;
2413
2414 rc = PGMPhysSimpleReadGCPtr(pVCpu, pPatch->aOpcode, pCtx->rip, cbOp);
2415 AssertRC(rc);
2416
2417 pPatch->cbOp = cbOp;
2418 pPatch->enmType = HMTPRINSTR_JUMP_REPLACEMENT;
2419
2420 if (pDis->Param1.fUse == DISUSE_DISPLACEMENT32)
2421 {
2422 /*
2423 * TPR write:
2424 *
2425 * push ECX [51]
2426 * push EDX [52]
2427 * push EAX [50]
2428 * xor EDX,EDX [31 D2]
2429 * mov EAX,EAX [89 C0]
2430 * or
2431 * mov EAX,0000000CCh [B8 CC 00 00 00]
2432 * mov ECX,0C0000082h [B9 82 00 00 C0]
2433 * wrmsr [0F 30]
2434 * pop EAX [58]
2435 * pop EDX [5A]
2436 * pop ECX [59]
2437 * jmp return_address [E9 return_address]
2438 */
2439 bool fUsesEax = (pDis->Param2.fUse == DISUSE_REG_GEN32 && pDis->Param2.Base.idxGenReg == DISGREG_EAX);
2440
2441 aPatch[off++] = 0x51; /* push ecx */
2442 aPatch[off++] = 0x52; /* push edx */
2443 if (!fUsesEax)
2444 aPatch[off++] = 0x50; /* push eax */
2445 aPatch[off++] = 0x31; /* xor edx, edx */
2446 aPatch[off++] = 0xD2;
2447 if (pDis->Param2.fUse == DISUSE_REG_GEN32)
2448 {
2449 if (!fUsesEax)
2450 {
2451 aPatch[off++] = 0x89; /* mov eax, src_reg */
2452 aPatch[off++] = MAKE_MODRM(3, pDis->Param2.Base.idxGenReg, DISGREG_EAX);
2453 }
2454 }
2455 else
2456 {
2457 Assert(pDis->Param2.fUse == DISUSE_IMMEDIATE32);
2458 aPatch[off++] = 0xB8; /* mov eax, immediate */
2459 *(uint32_t *)&aPatch[off] = pDis->Param2.uValue;
2460 off += sizeof(uint32_t);
2461 }
2462 aPatch[off++] = 0xB9; /* mov ecx, 0xc0000082 */
2463 *(uint32_t *)&aPatch[off] = MSR_K8_LSTAR;
2464 off += sizeof(uint32_t);
2465
2466 aPatch[off++] = 0x0F; /* wrmsr */
2467 aPatch[off++] = 0x30;
2468 if (!fUsesEax)
2469 aPatch[off++] = 0x58; /* pop eax */
2470 aPatch[off++] = 0x5A; /* pop edx */
2471 aPatch[off++] = 0x59; /* pop ecx */
2472 }
2473 else
2474 {
2475 /*
2476 * TPR read:
2477 *
2478 * push ECX [51]
2479 * push EDX [52]
2480 * push EAX [50]
2481 * mov ECX,0C0000082h [B9 82 00 00 C0]
2482 * rdmsr [0F 32]
2483 * mov EAX,EAX [89 C0]
2484 * pop EAX [58]
2485 * pop EDX [5A]
2486 * pop ECX [59]
2487 * jmp return_address [E9 return_address]
2488 */
2489 Assert(pDis->Param1.fUse == DISUSE_REG_GEN32);
2490
2491 if (pDis->Param1.Base.idxGenReg != DISGREG_ECX)
2492 aPatch[off++] = 0x51; /* push ecx */
2493 if (pDis->Param1.Base.idxGenReg != DISGREG_EDX )
2494 aPatch[off++] = 0x52; /* push edx */
2495 if (pDis->Param1.Base.idxGenReg != DISGREG_EAX)
2496 aPatch[off++] = 0x50; /* push eax */
2497
2498 aPatch[off++] = 0x31; /* xor edx, edx */
2499 aPatch[off++] = 0xD2;
2500
2501 aPatch[off++] = 0xB9; /* mov ecx, 0xc0000082 */
2502 *(uint32_t *)&aPatch[off] = MSR_K8_LSTAR;
2503 off += sizeof(uint32_t);
2504
2505 aPatch[off++] = 0x0F; /* rdmsr */
2506 aPatch[off++] = 0x32;
2507
2508 if (pDis->Param1.Base.idxGenReg != DISGREG_EAX)
2509 {
2510 aPatch[off++] = 0x89; /* mov dst_reg, eax */
2511 aPatch[off++] = MAKE_MODRM(3, DISGREG_EAX, pDis->Param1.Base.idxGenReg);
2512 }
2513
2514 if (pDis->Param1.Base.idxGenReg != DISGREG_EAX)
2515 aPatch[off++] = 0x58; /* pop eax */
2516 if (pDis->Param1.Base.idxGenReg != DISGREG_EDX )
2517 aPatch[off++] = 0x5A; /* pop edx */
2518 if (pDis->Param1.Base.idxGenReg != DISGREG_ECX)
2519 aPatch[off++] = 0x59; /* pop ecx */
2520 }
2521 aPatch[off++] = 0xE9; /* jmp return_address */
2522 *(RTRCUINTPTR *)&aPatch[off] = ((RTRCUINTPTR)pCtx->eip + cbOp) - ((RTRCUINTPTR)pVM->hm.s.pFreeGuestPatchMem + off + 4);
2523 off += sizeof(RTRCUINTPTR);
2524
2525 if (pVM->hm.s.pFreeGuestPatchMem + off <= pVM->hm.s.pGuestPatchMem + pVM->hm.s.cbGuestPatchMem)
2526 {
2527 /* Write new code to the patch buffer. */
2528 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pVM->hm.s.pFreeGuestPatchMem, aPatch, off);
2529 AssertRC(rc);
2530
2531#ifdef LOG_ENABLED
2532 uint32_t cbCurInstr;
2533 for (RTGCPTR GCPtrInstr = pVM->hm.s.pFreeGuestPatchMem;
2534 GCPtrInstr < pVM->hm.s.pFreeGuestPatchMem + off;
2535 GCPtrInstr += RT_MAX(cbCurInstr, 1))
2536 {
2537 char szOutput[256];
2538 rc = DBGFR3DisasInstrEx(pVM->pUVM, pVCpu->idCpu, pCtx->cs.Sel, GCPtrInstr, DBGF_DISAS_FLAGS_DEFAULT_MODE,
2539 szOutput, sizeof(szOutput), &cbCurInstr);
2540 if (RT_SUCCESS(rc))
2541 Log(("Patch instr %s\n", szOutput));
2542 else
2543 Log(("%RGv: rc=%Rrc\n", GCPtrInstr, rc));
2544 }
2545#endif
2546
2547 pPatch->aNewOpcode[0] = 0xE9;
2548 *(RTRCUINTPTR *)&pPatch->aNewOpcode[1] = ((RTRCUINTPTR)pVM->hm.s.pFreeGuestPatchMem) - ((RTRCUINTPTR)pCtx->eip + 5);
2549
2550 /* Overwrite the TPR instruction with a jump. */
2551 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->eip, pPatch->aNewOpcode, 5);
2552 AssertRC(rc);
2553
2554 DBGFR3_DISAS_INSTR_CUR_LOG(pVCpu, "Jump");
2555
2556 pVM->hm.s.pFreeGuestPatchMem += off;
2557 pPatch->cbNewOp = 5;
2558
2559 pPatch->Core.Key = pCtx->eip;
2560 rc = RTAvloU32Insert(&pVM->hm.s.PatchTree, &pPatch->Core);
2561 AssertRC(rc);
2562
2563 pVM->hm.s.cPatches++;
2564 pVM->hm.s.fTPRPatchingActive = true;
2565 STAM_COUNTER_INC(&pVM->hm.s.StatTprPatchSuccess);
2566 return VINF_SUCCESS;
2567 }
2568
2569 Log(("Ran out of space in our patch buffer!\n"));
2570 }
2571 else
2572 Log(("hmR3PatchTprInstr: Failed to patch instr!\n"));
2573
2574
2575 /*
2576 * Save invalid patch, so we will not try again.
2577 */
2578 pPatch = &pVM->hm.s.aPatches[idx];
2579 pPatch->Core.Key = pCtx->eip;
2580 pPatch->enmType = HMTPRINSTR_INVALID;
2581 rc = RTAvloU32Insert(&pVM->hm.s.PatchTree, &pPatch->Core);
2582 AssertRC(rc);
2583 pVM->hm.s.cPatches++;
2584 STAM_COUNTER_INC(&pVM->hm.s.StatTprPatchFailure);
2585 return VINF_SUCCESS;
2586}
2587
2588
2589/**
2590 * Attempt to patch TPR mmio instructions.
2591 *
2592 * @returns VBox status code.
2593 * @param pVM The cross context VM structure.
2594 * @param pVCpu The cross context virtual CPU structure.
2595 */
2596VMMR3_INT_DECL(int) HMR3PatchTprInstr(PVM pVM, PVMCPU pVCpu)
2597{
2598 int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONE_BY_ONE,
2599 pVM->hm.s.pGuestPatchMem ? hmR3PatchTprInstr : hmR3ReplaceTprInstr,
2600 (void *)(uintptr_t)pVCpu->idCpu);
2601 AssertRC(rc);
2602 return rc;
2603}
2604
2605
2606/**
2607 * Checks if a code selector (CS) is suitable for execution
2608 * within VMX when unrestricted execution isn't available.
2609 *
2610 * @returns true if selector is suitable for VMX, otherwise
2611 * false.
2612 * @param pSel Pointer to the selector to check (CS).
2613 * @param uStackDpl The CPL, aka the DPL of the stack segment.
2614 */
2615static bool hmR3IsCodeSelectorOkForVmx(PCPUMSELREG pSel, unsigned uStackDpl)
2616{
2617 /*
2618 * Segment must be an accessed code segment, it must be present and it must
2619 * be usable.
2620 * Note! These are all standard requirements and if CS holds anything else
2621 * we've got buggy code somewhere!
2622 */
2623 AssertCompile(X86DESCATTR_TYPE == 0xf);
2624 AssertMsgReturn( (pSel->Attr.u & (X86_SEL_TYPE_ACCESSED | X86_SEL_TYPE_CODE | X86DESCATTR_DT | X86DESCATTR_P | X86DESCATTR_UNUSABLE))
2625 == (X86_SEL_TYPE_ACCESSED | X86_SEL_TYPE_CODE | X86DESCATTR_DT | X86DESCATTR_P),
2626 ("%#x\n", pSel->Attr.u),
2627 false);
2628
2629 /* For conforming segments, CS.DPL must be <= SS.DPL, while CS.DPL
2630 must equal SS.DPL for non-confroming segments.
2631 Note! This is also a hard requirement like above. */
2632 AssertMsgReturn( pSel->Attr.n.u4Type & X86_SEL_TYPE_CONF
2633 ? pSel->Attr.n.u2Dpl <= uStackDpl
2634 : pSel->Attr.n.u2Dpl == uStackDpl,
2635 ("u4Type=%#x u2Dpl=%u uStackDpl=%u\n", pSel->Attr.n.u4Type, pSel->Attr.n.u2Dpl, uStackDpl),
2636 false);
2637
2638 /*
2639 * The following two requirements are VT-x specific:
2640 * - G bit must be set if any high limit bits are set.
2641 * - G bit must be clear if any low limit bits are clear.
2642 */
2643 if ( ((pSel->u32Limit & 0xfff00000) == 0x00000000 || pSel->Attr.n.u1Granularity)
2644 && ((pSel->u32Limit & 0x00000fff) == 0x00000fff || !pSel->Attr.n.u1Granularity))
2645 return true;
2646 return false;
2647}
2648
2649
2650/**
2651 * Checks if a data selector (DS/ES/FS/GS) is suitable for
2652 * execution within VMX when unrestricted execution isn't
2653 * available.
2654 *
2655 * @returns true if selector is suitable for VMX, otherwise
2656 * false.
2657 * @param pSel Pointer to the selector to check
2658 * (DS/ES/FS/GS).
2659 */
2660static bool hmR3IsDataSelectorOkForVmx(PCPUMSELREG pSel)
2661{
2662 /*
2663 * Unusable segments are OK. These days they should be marked as such, as
2664 * but as an alternative we for old saved states and AMD<->VT-x migration
2665 * we also treat segments with all the attributes cleared as unusable.
2666 */
2667 if (pSel->Attr.n.u1Unusable || !pSel->Attr.u)
2668 return true;
2669
2670 /** @todo tighten these checks. Will require CPUM load adjusting. */
2671
2672 /* Segment must be accessed. */
2673 if (pSel->Attr.u & X86_SEL_TYPE_ACCESSED)
2674 {
2675 /* Code segments must also be readable. */
2676 if ( !(pSel->Attr.u & X86_SEL_TYPE_CODE)
2677 || (pSel->Attr.u & X86_SEL_TYPE_READ))
2678 {
2679 /* The S bit must be set. */
2680 if (pSel->Attr.n.u1DescType)
2681 {
2682 /* Except for conforming segments, DPL >= RPL. */
2683 if ( pSel->Attr.n.u2Dpl >= (pSel->Sel & X86_SEL_RPL)
2684 || pSel->Attr.n.u4Type >= X86_SEL_TYPE_ER_ACC)
2685 {
2686 /* Segment must be present. */
2687 if (pSel->Attr.n.u1Present)
2688 {
2689 /*
2690 * The following two requirements are VT-x specific:
2691 * - G bit must be set if any high limit bits are set.
2692 * - G bit must be clear if any low limit bits are clear.
2693 */
2694 if ( ((pSel->u32Limit & 0xfff00000) == 0x00000000 || pSel->Attr.n.u1Granularity)
2695 && ((pSel->u32Limit & 0x00000fff) == 0x00000fff || !pSel->Attr.n.u1Granularity))
2696 return true;
2697 }
2698 }
2699 }
2700 }
2701 }
2702
2703 return false;
2704}
2705
2706
2707/**
2708 * Checks if the stack selector (SS) is suitable for execution
2709 * within VMX when unrestricted execution isn't available.
2710 *
2711 * @returns true if selector is suitable for VMX, otherwise
2712 * false.
2713 * @param pSel Pointer to the selector to check (SS).
2714 */
2715static bool hmR3IsStackSelectorOkForVmx(PCPUMSELREG pSel)
2716{
2717 /*
2718 * Unusable segments are OK. These days they should be marked as such, as
2719 * but as an alternative we for old saved states and AMD<->VT-x migration
2720 * we also treat segments with all the attributes cleared as unusable.
2721 */
2722 /** @todo r=bird: actually all zeroes isn't gonna cut it... SS.DPL == CPL. */
2723 if (pSel->Attr.n.u1Unusable || !pSel->Attr.u)
2724 return true;
2725
2726 /*
2727 * Segment must be an accessed writable segment, it must be present.
2728 * Note! These are all standard requirements and if SS holds anything else
2729 * we've got buggy code somewhere!
2730 */
2731 AssertCompile(X86DESCATTR_TYPE == 0xf);
2732 AssertMsgReturn( (pSel->Attr.u & (X86_SEL_TYPE_ACCESSED | X86_SEL_TYPE_WRITE | X86DESCATTR_DT | X86DESCATTR_P | X86_SEL_TYPE_CODE))
2733 == (X86_SEL_TYPE_ACCESSED | X86_SEL_TYPE_WRITE | X86DESCATTR_DT | X86DESCATTR_P),
2734 ("%#x\n", pSel->Attr.u), false);
2735
2736 /* DPL must equal RPL.
2737 Note! This is also a hard requirement like above. */
2738 AssertMsgReturn(pSel->Attr.n.u2Dpl == (pSel->Sel & X86_SEL_RPL),
2739 ("u2Dpl=%u Sel=%#x\n", pSel->Attr.n.u2Dpl, pSel->Sel), false);
2740
2741 /*
2742 * The following two requirements are VT-x specific:
2743 * - G bit must be set if any high limit bits are set.
2744 * - G bit must be clear if any low limit bits are clear.
2745 */
2746 if ( ((pSel->u32Limit & 0xfff00000) == 0x00000000 || pSel->Attr.n.u1Granularity)
2747 && ((pSel->u32Limit & 0x00000fff) == 0x00000fff || !pSel->Attr.n.u1Granularity))
2748 return true;
2749 return false;
2750}
2751
2752
2753/**
2754 * Checks if we can currently use hardware accelerated raw mode.
2755 *
2756 * @returns true if we can currently use hardware acceleration, otherwise false.
2757 * @param pVM The cross context VM structure.
2758 * @param pCtx Partial VM execution context.
2759 */
2760VMMR3DECL(bool) HMR3CanExecuteGuest(PVM pVM, PCPUMCTX pCtx)
2761{
2762 PVMCPU pVCpu = VMMGetCpu(pVM);
2763
2764 Assert(HMIsEnabled(pVM));
2765
2766#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
2767 if (CPUMIsGuestInNestedHwVirtMode(pCtx))
2768 {
2769 Log(("HMR3CanExecuteGuest: In nested-guest mode - returning false"));
2770 return false;
2771 }
2772#endif
2773
2774 /* AMD-V supports real & protected mode with or without paging. */
2775 if (pVM->hm.s.svm.fEnabled)
2776 {
2777 pVCpu->hm.s.fActive = true;
2778 return true;
2779 }
2780
2781 pVCpu->hm.s.fActive = false;
2782
2783 /* Note! The context supplied by REM is partial. If we add more checks here, be sure to verify that REM provides this info! */
2784 Assert( (pVM->hm.s.vmx.fUnrestrictedGuest && !pVM->hm.s.vmx.pRealModeTSS)
2785 || (!pVM->hm.s.vmx.fUnrestrictedGuest && pVM->hm.s.vmx.pRealModeTSS));
2786
2787 bool fSupportsRealMode = pVM->hm.s.vmx.fUnrestrictedGuest || PDMVmmDevHeapIsEnabled(pVM);
2788 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
2789 {
2790 /*
2791 * The VMM device heap is a requirement for emulating real mode or protected mode without paging with the unrestricted
2792 * guest execution feature is missing (VT-x only).
2793 */
2794 if (fSupportsRealMode)
2795 {
2796 if (CPUMIsGuestInRealModeEx(pCtx))
2797 {
2798 /*
2799 * In V86 mode (VT-x or not), the CPU enforces real-mode compatible selector
2800 * bases and limits, i.e. limit must be 64K and base must be selector * 16.
2801 * If this is not true, we cannot execute real mode as V86 and have to fall
2802 * back to emulation.
2803 */
2804 if ( pCtx->cs.Sel != (pCtx->cs.u64Base >> 4)
2805 || pCtx->ds.Sel != (pCtx->ds.u64Base >> 4)
2806 || pCtx->es.Sel != (pCtx->es.u64Base >> 4)
2807 || pCtx->ss.Sel != (pCtx->ss.u64Base >> 4)
2808 || pCtx->fs.Sel != (pCtx->fs.u64Base >> 4)
2809 || pCtx->gs.Sel != (pCtx->gs.u64Base >> 4))
2810 {
2811 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxCheckBadRmSelBase);
2812 return false;
2813 }
2814 if ( (pCtx->cs.u32Limit != 0xffff)
2815 || (pCtx->ds.u32Limit != 0xffff)
2816 || (pCtx->es.u32Limit != 0xffff)
2817 || (pCtx->ss.u32Limit != 0xffff)
2818 || (pCtx->fs.u32Limit != 0xffff)
2819 || (pCtx->gs.u32Limit != 0xffff))
2820 {
2821 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxCheckBadRmSelLimit);
2822 return false;
2823 }
2824 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxCheckRmOk);
2825 }
2826 else
2827 {
2828 /*
2829 * Verify the requirements for executing code in protected mode. VT-x can't
2830 * handle the CPU state right after a switch from real to protected mode
2831 * (all sorts of RPL & DPL assumptions).
2832 */
2833 if (pVCpu->hm.s.vmx.fWasInRealMode)
2834 {
2835 /** @todo If guest is in V86 mode, these checks should be different! */
2836 if ((pCtx->cs.Sel & X86_SEL_RPL) != (pCtx->ss.Sel & X86_SEL_RPL))
2837 {
2838 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxCheckBadRpl);
2839 return false;
2840 }
2841 if ( !hmR3IsCodeSelectorOkForVmx(&pCtx->cs, pCtx->ss.Attr.n.u2Dpl)
2842 || !hmR3IsDataSelectorOkForVmx(&pCtx->ds)
2843 || !hmR3IsDataSelectorOkForVmx(&pCtx->es)
2844 || !hmR3IsDataSelectorOkForVmx(&pCtx->fs)
2845 || !hmR3IsDataSelectorOkForVmx(&pCtx->gs)
2846 || !hmR3IsStackSelectorOkForVmx(&pCtx->ss))
2847 {
2848 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxCheckBadSel);
2849 return false;
2850 }
2851 }
2852 /* VT-x also chokes on invalid TR or LDTR selectors (minix). */
2853 if (pCtx->gdtr.cbGdt)
2854 {
2855 if ((pCtx->tr.Sel | X86_SEL_RPL_LDT) > pCtx->gdtr.cbGdt)
2856 {
2857 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxCheckBadTr);
2858 return false;
2859 }
2860 else if ((pCtx->ldtr.Sel | X86_SEL_RPL_LDT) > pCtx->gdtr.cbGdt)
2861 {
2862 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxCheckBadLdt);
2863 return false;
2864 }
2865 }
2866 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxCheckPmOk);
2867 }
2868 }
2869 else
2870 {
2871 if ( !CPUMIsGuestInLongModeEx(pCtx)
2872 && !pVM->hm.s.vmx.fUnrestrictedGuest)
2873 {
2874 if ( !pVM->hm.s.fNestedPaging /* Requires a fake PD for real *and* protected mode without paging - stored in the VMM device heap */
2875 || CPUMIsGuestInRealModeEx(pCtx)) /* Requires a fake TSS for real mode - stored in the VMM device heap */
2876 return false;
2877
2878 /* Too early for VT-x; Solaris guests will fail with a guru meditation otherwise; same for XP. */
2879 if (pCtx->idtr.pIdt == 0 || pCtx->idtr.cbIdt == 0 || pCtx->tr.Sel == 0)
2880 return false;
2881
2882 /*
2883 * The guest is about to complete the switch to protected mode. Wait a bit longer.
2884 * Windows XP; switch to protected mode; all selectors are marked not present
2885 * in the hidden registers (possible recompiler bug; see load_seg_vm).
2886 */
2887 /** @todo Is this supposed recompiler bug still relevant with IEM? */
2888 if (pCtx->cs.Attr.n.u1Present == 0)
2889 return false;
2890 if (pCtx->ss.Attr.n.u1Present == 0)
2891 return false;
2892
2893 /*
2894 * Windows XP: possible same as above, but new recompiler requires new
2895 * heuristics? VT-x doesn't seem to like something about the guest state and
2896 * this stuff avoids it.
2897 */
2898 /** @todo This check is actually wrong, it doesn't take the direction of the
2899 * stack segment into account. But, it does the job for now. */
2900 if (pCtx->rsp >= pCtx->ss.u32Limit)
2901 return false;
2902 }
2903 }
2904 }
2905
2906 if (pVM->hm.s.vmx.fEnabled)
2907 {
2908 uint32_t uCR0Mask;
2909
2910 /* If bit N is set in cr0_fixed0, then it must be set in the guest's cr0. */
2911 uCR0Mask = (uint32_t)pVM->hm.s.vmx.Msrs.u64Cr0Fixed0;
2912
2913 /* We ignore the NE bit here on purpose; see HMR0.cpp for details. */
2914 uCR0Mask &= ~X86_CR0_NE;
2915
2916 if (fSupportsRealMode)
2917 {
2918 /* We ignore the PE & PG bits here on purpose; we emulate real and protected mode without paging. */
2919 uCR0Mask &= ~(X86_CR0_PG|X86_CR0_PE);
2920 }
2921 else
2922 {
2923 /* We support protected mode without paging using identity mapping. */
2924 uCR0Mask &= ~X86_CR0_PG;
2925 }
2926 if ((pCtx->cr0 & uCR0Mask) != uCR0Mask)
2927 return false;
2928
2929 /* If bit N is cleared in cr0_fixed1, then it must be zero in the guest's cr0. */
2930 uCR0Mask = (uint32_t)~pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
2931 if ((pCtx->cr0 & uCR0Mask) != 0)
2932 return false;
2933
2934 /* If bit N is set in cr4_fixed0, then it must be set in the guest's cr4. */
2935 uCR0Mask = (uint32_t)pVM->hm.s.vmx.Msrs.u64Cr4Fixed0;
2936 uCR0Mask &= ~X86_CR4_VMXE;
2937 if ((pCtx->cr4 & uCR0Mask) != uCR0Mask)
2938 return false;
2939
2940 /* If bit N is cleared in cr4_fixed1, then it must be zero in the guest's cr4. */
2941 uCR0Mask = (uint32_t)~pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
2942 if ((pCtx->cr4 & uCR0Mask) != 0)
2943 return false;
2944
2945 pVCpu->hm.s.fActive = true;
2946 return true;
2947 }
2948
2949 return false;
2950}
2951
2952
2953/**
2954 * Checks if we need to reschedule due to VMM device heap changes.
2955 *
2956 * @returns true if a reschedule is required, otherwise false.
2957 * @param pVM The cross context VM structure.
2958 * @param pCtx VM execution context.
2959 */
2960VMMR3_INT_DECL(bool) HMR3IsRescheduleRequired(PVM pVM, PCPUMCTX pCtx)
2961{
2962 /*
2963 * The VMM device heap is a requirement for emulating real-mode or protected-mode without paging
2964 * when the unrestricted guest execution feature is missing (VT-x only).
2965 */
2966 if ( pVM->hm.s.vmx.fEnabled
2967 && !pVM->hm.s.vmx.fUnrestrictedGuest
2968 && CPUMIsGuestInRealModeEx(pCtx)
2969 && !PDMVmmDevHeapIsEnabled(pVM))
2970 {
2971 return true;
2972 }
2973
2974 return false;
2975}
2976
2977
2978/**
2979 * Noticiation callback from DBGF when interrupt breakpoints or generic debug
2980 * event settings changes.
2981 *
2982 * DBGF will call HMR3NotifyDebugEventChangedPerCpu on each CPU afterwards, this
2983 * function is just updating the VM globals.
2984 *
2985 * @param pVM The VM cross context VM structure.
2986 * @thread EMT(0)
2987 */
2988VMMR3_INT_DECL(void) HMR3NotifyDebugEventChanged(PVM pVM)
2989{
2990 /* Interrupts. */
2991 bool fUseDebugLoop = pVM->dbgf.ro.cSoftIntBreakpoints > 0
2992 || pVM->dbgf.ro.cHardIntBreakpoints > 0;
2993
2994 /* CPU Exceptions. */
2995 for (DBGFEVENTTYPE enmEvent = DBGFEVENT_XCPT_FIRST;
2996 !fUseDebugLoop && enmEvent <= DBGFEVENT_XCPT_LAST;
2997 enmEvent = (DBGFEVENTTYPE)(enmEvent + 1))
2998 fUseDebugLoop = DBGF_IS_EVENT_ENABLED(pVM, enmEvent);
2999
3000 /* Common VM exits. */
3001 for (DBGFEVENTTYPE enmEvent = DBGFEVENT_EXIT_FIRST;
3002 !fUseDebugLoop && enmEvent <= DBGFEVENT_EXIT_LAST_COMMON;
3003 enmEvent = (DBGFEVENTTYPE)(enmEvent + 1))
3004 fUseDebugLoop = DBGF_IS_EVENT_ENABLED(pVM, enmEvent);
3005
3006 /* Vendor specific VM exits. */
3007 if (HMR3IsVmxEnabled(pVM->pUVM))
3008 for (DBGFEVENTTYPE enmEvent = DBGFEVENT_EXIT_VMX_FIRST;
3009 !fUseDebugLoop && enmEvent <= DBGFEVENT_EXIT_VMX_LAST;
3010 enmEvent = (DBGFEVENTTYPE)(enmEvent + 1))
3011 fUseDebugLoop = DBGF_IS_EVENT_ENABLED(pVM, enmEvent);
3012 else
3013 for (DBGFEVENTTYPE enmEvent = DBGFEVENT_EXIT_SVM_FIRST;
3014 !fUseDebugLoop && enmEvent <= DBGFEVENT_EXIT_SVM_LAST;
3015 enmEvent = (DBGFEVENTTYPE)(enmEvent + 1))
3016 fUseDebugLoop = DBGF_IS_EVENT_ENABLED(pVM, enmEvent);
3017
3018 /* Done. */
3019 pVM->hm.s.fUseDebugLoop = fUseDebugLoop;
3020}
3021
3022
3023/**
3024 * Follow up notification callback to HMR3NotifyDebugEventChanged for each CPU.
3025 *
3026 * HM uses this to combine the decision made by HMR3NotifyDebugEventChanged with
3027 * per CPU settings.
3028 *
3029 * @param pVM The VM cross context VM structure.
3030 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
3031 */
3032VMMR3_INT_DECL(void) HMR3NotifyDebugEventChangedPerCpu(PVM pVM, PVMCPU pVCpu)
3033{
3034 pVCpu->hm.s.fUseDebugLoop = pVCpu->hm.s.fSingleInstruction | pVM->hm.s.fUseDebugLoop;
3035}
3036
3037
3038/**
3039 * Checks if we are currently using hardware acceleration.
3040 *
3041 * @returns true if hardware acceleration is being used, otherwise false.
3042 * @param pVCpu The cross context virtual CPU structure.
3043 */
3044VMMR3_INT_DECL(bool) HMR3IsActive(PVMCPU pVCpu)
3045{
3046 return pVCpu->hm.s.fActive;
3047}
3048
3049
3050/**
3051 * External interface for querying whether hardware acceleration is enabled.
3052 *
3053 * @returns true if VT-x or AMD-V is being used, otherwise false.
3054 * @param pUVM The user mode VM handle.
3055 * @sa HMIsEnabled, HMIsEnabledNotMacro.
3056 */
3057VMMR3DECL(bool) HMR3IsEnabled(PUVM pUVM)
3058{
3059 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
3060 PVM pVM = pUVM->pVM;
3061 VM_ASSERT_VALID_EXT_RETURN(pVM, false);
3062 return pVM->fHMEnabled; /* Don't use the macro as the GUI may query us very very early. */
3063}
3064
3065
3066/**
3067 * External interface for querying whether VT-x is being used.
3068 *
3069 * @returns true if VT-x is being used, otherwise false.
3070 * @param pUVM The user mode VM handle.
3071 * @sa HMR3IsSvmEnabled, HMIsEnabled
3072 */
3073VMMR3DECL(bool) HMR3IsVmxEnabled(PUVM pUVM)
3074{
3075 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
3076 PVM pVM = pUVM->pVM;
3077 VM_ASSERT_VALID_EXT_RETURN(pVM, false);
3078 return pVM->hm.s.vmx.fEnabled
3079 && pVM->hm.s.vmx.fSupported
3080 && pVM->fHMEnabled;
3081}
3082
3083
3084/**
3085 * External interface for querying whether AMD-V is being used.
3086 *
3087 * @returns true if VT-x is being used, otherwise false.
3088 * @param pUVM The user mode VM handle.
3089 * @sa HMR3IsVmxEnabled, HMIsEnabled
3090 */
3091VMMR3DECL(bool) HMR3IsSvmEnabled(PUVM pUVM)
3092{
3093 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
3094 PVM pVM = pUVM->pVM;
3095 VM_ASSERT_VALID_EXT_RETURN(pVM, false);
3096 return pVM->hm.s.svm.fEnabled
3097 && pVM->hm.s.svm.fSupported
3098 && pVM->fHMEnabled;
3099}
3100
3101
3102/**
3103 * Checks if we are currently using nested paging.
3104 *
3105 * @returns true if nested paging is being used, otherwise false.
3106 * @param pUVM The user mode VM handle.
3107 */
3108VMMR3DECL(bool) HMR3IsNestedPagingActive(PUVM pUVM)
3109{
3110 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
3111 PVM pVM = pUVM->pVM;
3112 VM_ASSERT_VALID_EXT_RETURN(pVM, false);
3113 return pVM->hm.s.fNestedPaging;
3114}
3115
3116
3117/**
3118 * Checks if virtualized APIC registers is enabled.
3119 *
3120 * When enabled this feature allows the hardware to access most of the
3121 * APIC registers in the virtual-APIC page without causing VM-exits. See
3122 * Intel spec. 29.1.1 "Virtualized APIC Registers".
3123 *
3124 * @returns true if virtualized APIC registers is enabled, otherwise
3125 * false.
3126 * @param pUVM The user mode VM handle.
3127 */
3128VMMR3DECL(bool) HMR3IsVirtApicRegsEnabled(PUVM pUVM)
3129{
3130 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
3131 PVM pVM = pUVM->pVM;
3132 VM_ASSERT_VALID_EXT_RETURN(pVM, false);
3133 return pVM->hm.s.fVirtApicRegs;
3134}
3135
3136
3137/**
3138 * Checks if APIC posted-interrupt processing is enabled.
3139 *
3140 * This returns whether we can deliver interrupts to the guest without
3141 * leaving guest-context by updating APIC state from host-context.
3142 *
3143 * @returns true if APIC posted-interrupt processing is enabled,
3144 * otherwise false.
3145 * @param pUVM The user mode VM handle.
3146 */
3147VMMR3DECL(bool) HMR3IsPostedIntrsEnabled(PUVM pUVM)
3148{
3149 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
3150 PVM pVM = pUVM->pVM;
3151 VM_ASSERT_VALID_EXT_RETURN(pVM, false);
3152 return pVM->hm.s.fPostedIntrs;
3153}
3154
3155
3156/**
3157 * Checks if we are currently using VPID in VT-x mode.
3158 *
3159 * @returns true if VPID is being used, otherwise false.
3160 * @param pUVM The user mode VM handle.
3161 */
3162VMMR3DECL(bool) HMR3IsVpidActive(PUVM pUVM)
3163{
3164 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
3165 PVM pVM = pUVM->pVM;
3166 VM_ASSERT_VALID_EXT_RETURN(pVM, false);
3167 return pVM->hm.s.vmx.fVpid;
3168}
3169
3170
3171/**
3172 * Checks if we are currently using VT-x unrestricted execution,
3173 * aka UX.
3174 *
3175 * @returns true if UX is being used, otherwise false.
3176 * @param pUVM The user mode VM handle.
3177 */
3178VMMR3DECL(bool) HMR3IsUXActive(PUVM pUVM)
3179{
3180 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
3181 PVM pVM = pUVM->pVM;
3182 VM_ASSERT_VALID_EXT_RETURN(pVM, false);
3183 return pVM->hm.s.vmx.fUnrestrictedGuest
3184 || pVM->hm.s.svm.fSupported;
3185}
3186
3187
3188/**
3189 * Checks if internal events are pending. In that case we are not allowed to dispatch interrupts.
3190 *
3191 * @returns true if an internal event is pending, otherwise false.
3192 * @param pVCpu The cross context virtual CPU structure.
3193 */
3194VMMR3_INT_DECL(bool) HMR3IsEventPending(PVMCPU pVCpu)
3195{
3196 return HMIsEnabled(pVCpu->pVMR3) && pVCpu->hm.s.Event.fPending;
3197}
3198
3199
3200/**
3201 * Checks if the VMX-preemption timer is being used.
3202 *
3203 * @returns true if the VMX-preemption timer is being used, otherwise false.
3204 * @param pVM The cross context VM structure.
3205 */
3206VMMR3_INT_DECL(bool) HMR3IsVmxPreemptionTimerUsed(PVM pVM)
3207{
3208 return HMIsEnabled(pVM)
3209 && pVM->hm.s.vmx.fEnabled
3210 && pVM->hm.s.vmx.fUsePreemptTimer;
3211}
3212
3213
3214/**
3215 * Check fatal VT-x/AMD-V error and produce some meaningful
3216 * log release message.
3217 *
3218 * @param pVM The cross context VM structure.
3219 * @param iStatusCode VBox status code.
3220 */
3221VMMR3_INT_DECL(void) HMR3CheckError(PVM pVM, int iStatusCode)
3222{
3223 for (VMCPUID i = 0; i < pVM->cCpus; i++)
3224 {
3225 PVMCPU pVCpu = &pVM->aCpus[i];
3226 switch (iStatusCode)
3227 {
3228 /** @todo r=ramshankar: Are all EMTs out of ring-0 at this point!? If not, we
3229 * might be getting inaccurate values for non-guru'ing EMTs. */
3230 case VERR_VMX_INVALID_VMCS_FIELD:
3231 break;
3232
3233 case VERR_VMX_INVALID_VMCS_PTR:
3234 LogRel(("HM: VERR_VMX_INVALID_VMCS_PTR:\n"));
3235 LogRel(("HM: CPU[%u] Current pointer %#RGp vs %#RGp\n", i, pVCpu->hm.s.vmx.LastError.u64VMCSPhys,
3236 pVCpu->hm.s.vmx.HCPhysVmcs));
3237 LogRel(("HM: CPU[%u] Current VMCS version %#x\n", i, pVCpu->hm.s.vmx.LastError.u32VMCSRevision));
3238 LogRel(("HM: CPU[%u] Entered Host Cpu %u\n", i, pVCpu->hm.s.vmx.LastError.idEnteredCpu));
3239 LogRel(("HM: CPU[%u] Current Host Cpu %u\n", i, pVCpu->hm.s.vmx.LastError.idCurrentCpu));
3240 break;
3241
3242 case VERR_VMX_UNABLE_TO_START_VM:
3243 LogRel(("HM: VERR_VMX_UNABLE_TO_START_VM:\n"));
3244 LogRel(("HM: CPU[%u] Instruction error %#x\n", i, pVCpu->hm.s.vmx.LastError.u32InstrError));
3245 LogRel(("HM: CPU[%u] Exit reason %#x\n", i, pVCpu->hm.s.vmx.LastError.u32ExitReason));
3246
3247 if ( pVM->aCpus[i].hm.s.vmx.LastError.u32InstrError == VMX_ERROR_VMLAUCH_NON_CLEAR_VMCS
3248 || pVM->aCpus[i].hm.s.vmx.LastError.u32InstrError == VMX_ERROR_VMRESUME_NON_LAUNCHED_VMCS)
3249 {
3250 LogRel(("HM: CPU[%u] Entered Host Cpu %u\n", i, pVCpu->hm.s.vmx.LastError.idEnteredCpu));
3251 LogRel(("HM: CPU[%u] Current Host Cpu %u\n", i, pVCpu->hm.s.vmx.LastError.idCurrentCpu));
3252 }
3253 else if (pVM->aCpus[i].hm.s.vmx.LastError.u32InstrError == VMX_ERROR_VMENTRY_INVALID_CONTROL_FIELDS)
3254 {
3255 LogRel(("HM: CPU[%u] PinCtls %#RX32\n", i, pVCpu->hm.s.vmx.u32PinCtls));
3256 {
3257 uint32_t const u32Val = pVCpu->hm.s.vmx.u32PinCtls;
3258 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PIN_EXEC_EXT_INT_EXIT );
3259 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PIN_EXEC_NMI_EXIT );
3260 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PIN_EXEC_VIRTUAL_NMI );
3261 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PIN_EXEC_PREEMPT_TIMER);
3262 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PIN_EXEC_POSTED_INTR );
3263 }
3264 LogRel(("HM: CPU[%u] ProcCtls %#RX32\n", i, pVCpu->hm.s.vmx.u32ProcCtls));
3265 {
3266 uint32_t const u32Val = pVCpu->hm.s.vmx.u32ProcCtls;
3267 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_INT_WINDOW_EXIT );
3268 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_USE_TSC_OFFSETTING);
3269 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_HLT_EXIT );
3270 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_INVLPG_EXIT );
3271 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_MWAIT_EXIT );
3272 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_RDPMC_EXIT );
3273 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_RDTSC_EXIT );
3274 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_CR3_LOAD_EXIT );
3275 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_CR3_STORE_EXIT );
3276 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_CR8_LOAD_EXIT );
3277 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_CR8_STORE_EXIT );
3278 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_USE_TPR_SHADOW );
3279 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_NMI_WINDOW_EXIT );
3280 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_MOV_DR_EXIT );
3281 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_UNCOND_IO_EXIT );
3282 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_USE_IO_BITMAPS );
3283 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_MONITOR_TRAP_FLAG );
3284 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_USE_MSR_BITMAPS );
3285 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_MONITOR_EXIT );
3286 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_PAUSE_EXIT );
3287 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL);
3288 }
3289 LogRel(("HM: CPU[%u] ProcCtls2 %#RX32\n", i, pVCpu->hm.s.vmx.u32ProcCtls2));
3290 {
3291 uint32_t const u32Val = pVCpu->hm.s.vmx.u32ProcCtls2;
3292 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_VIRT_APIC );
3293 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_EPT );
3294 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_DESCRIPTOR_TABLE_EXIT);
3295 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_RDTSCP );
3296 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_VIRT_X2APIC );
3297 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_VPID );
3298 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_WBINVD_EXIT );
3299 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_UNRESTRICTED_GUEST );
3300 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_APIC_REG_VIRT );
3301 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_VIRT_INTR_DELIVERY );
3302 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_PAUSE_LOOP_EXIT );
3303 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_RDRAND_EXIT );
3304 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_INVPCID );
3305 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_VMFUNC );
3306 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_VMCS_SHADOWING );
3307 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_ENCLS_EXIT );
3308 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_RDSEED_EXIT );
3309 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_PML );
3310 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_EPT_VE );
3311 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_CONCEAL_FROM_PT );
3312 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_XSAVES_XRSTORS );
3313 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_PROC_EXEC2_TSC_SCALING );
3314 }
3315 LogRel(("HM: CPU[%u] EntryCtls %#RX32\n", i, pVCpu->hm.s.vmx.u32EntryCtls));
3316 {
3317 uint32_t const u32Val = pVCpu->hm.s.vmx.u32EntryCtls;
3318 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_ENTRY_LOAD_DEBUG );
3319 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_ENTRY_IA32E_MODE_GUEST );
3320 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_ENTRY_ENTRY_SMM );
3321 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_ENTRY_DEACTIVATE_DUALMON );
3322 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_ENTRY_LOAD_GUEST_PERF_MSR);
3323 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_ENTRY_LOAD_GUEST_PAT_MSR );
3324 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_ENTRY_LOAD_GUEST_EFER_MSR);
3325 }
3326 LogRel(("HM: CPU[%u] ExitCtls %#RX32\n", i, pVCpu->hm.s.vmx.u32ExitCtls));
3327 {
3328 uint32_t const u32Val = pVCpu->hm.s.vmx.u32ExitCtls;
3329 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_EXIT_SAVE_DEBUG );
3330 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_EXIT_HOST_ADDR_SPACE_SIZE );
3331 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_EXIT_LOAD_PERF_MSR );
3332 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_EXIT_ACK_EXT_INT );
3333 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_EXIT_SAVE_GUEST_PAT_MSR );
3334 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_EXIT_LOAD_HOST_PAT_MSR );
3335 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_EXIT_SAVE_GUEST_EFER_MSR );
3336 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_EXIT_LOAD_HOST_EFER_MSR );
3337 HMVMX_LOGREL_FEAT(u32Val, VMX_VMCS_CTRL_EXIT_SAVE_VMX_PREEMPT_TIMER);
3338 }
3339 LogRel(("HM: CPU[%u] HCPhysMsrBitmap %#RHp\n", i, pVCpu->hm.s.vmx.HCPhysMsrBitmap));
3340 LogRel(("HM: CPU[%u] HCPhysGuestMsr %#RHp\n", i, pVCpu->hm.s.vmx.HCPhysGuestMsr));
3341 LogRel(("HM: CPU[%u] HCPhysHostMsr %#RHp\n", i, pVCpu->hm.s.vmx.HCPhysHostMsr));
3342 LogRel(("HM: CPU[%u] cMsrs %u\n", i, pVCpu->hm.s.vmx.cMsrs));
3343 }
3344 /** @todo Log VM-entry event injection control fields
3345 * VMX_VMCS_CTRL_ENTRY_IRQ_INFO, VMX_VMCS_CTRL_ENTRY_EXCEPTION_ERRCODE
3346 * and VMX_VMCS_CTRL_ENTRY_INSTR_LENGTH from the VMCS. */
3347 break;
3348
3349 /* The guru will dump the HM error and exit history. Nothing extra to report for these errors. */
3350 case VERR_VMX_INVALID_VMXON_PTR:
3351 case VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO:
3352 case VERR_VMX_INVALID_GUEST_STATE:
3353 case VERR_VMX_UNEXPECTED_EXIT:
3354 case VERR_SVM_UNKNOWN_EXIT:
3355 case VERR_SVM_UNEXPECTED_EXIT:
3356 case VERR_SVM_UNEXPECTED_PATCH_TYPE:
3357 case VERR_SVM_UNEXPECTED_XCPT_EXIT:
3358 case VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE:
3359 break;
3360 }
3361 }
3362
3363 if (iStatusCode == VERR_VMX_UNABLE_TO_START_VM)
3364 {
3365 LogRel(("HM: VERR_VMX_UNABLE_TO_START_VM: VM-entry allowed %#RX32\n", pVM->hm.s.vmx.Msrs.VmxEntry.n.allowed1));
3366 LogRel(("HM: VERR_VMX_UNABLE_TO_START_VM: VM-entry disallowed %#RX32\n", pVM->hm.s.vmx.Msrs.VmxEntry.n.disallowed0));
3367 }
3368 else if (iStatusCode == VERR_VMX_INVALID_VMXON_PTR)
3369 LogRel(("HM: HCPhysVmxEnableError = %#RHp\n", pVM->hm.s.vmx.HCPhysVmxEnableError));
3370}
3371
3372
3373/**
3374 * Execute state save operation.
3375 *
3376 * Save only data that cannot be re-loaded while entering HM ring-0 code. This
3377 * is because we always save the VM state from ring-3 and thus most HM state
3378 * will be re-synced dynamically at runtime and don't need to be part of the VM
3379 * saved state.
3380 *
3381 * @returns VBox status code.
3382 * @param pVM The cross context VM structure.
3383 * @param pSSM SSM operation handle.
3384 */
3385static DECLCALLBACK(int) hmR3Save(PVM pVM, PSSMHANDLE pSSM)
3386{
3387 int rc;
3388
3389 Log(("hmR3Save:\n"));
3390
3391 for (VMCPUID i = 0; i < pVM->cCpus; i++)
3392 {
3393 Assert(!pVM->aCpus[i].hm.s.Event.fPending);
3394 if (pVM->cpum.ro.GuestFeatures.fSvm)
3395 {
3396 PCSVMNESTEDVMCBCACHE pVmcbNstGstCache = &pVM->aCpus[i].hm.s.svm.NstGstVmcbCache;
3397 rc = SSMR3PutBool(pSSM, pVmcbNstGstCache->fCacheValid);
3398 rc |= SSMR3PutU16(pSSM, pVmcbNstGstCache->u16InterceptRdCRx);
3399 rc |= SSMR3PutU16(pSSM, pVmcbNstGstCache->u16InterceptWrCRx);
3400 rc |= SSMR3PutU16(pSSM, pVmcbNstGstCache->u16InterceptRdDRx);
3401 rc |= SSMR3PutU16(pSSM, pVmcbNstGstCache->u16InterceptWrDRx);
3402 rc |= SSMR3PutU16(pSSM, pVmcbNstGstCache->u16PauseFilterThreshold);
3403 rc |= SSMR3PutU16(pSSM, pVmcbNstGstCache->u16PauseFilterCount);
3404 rc |= SSMR3PutU32(pSSM, pVmcbNstGstCache->u32InterceptXcpt);
3405 rc |= SSMR3PutU64(pSSM, pVmcbNstGstCache->u64InterceptCtrl);
3406 rc |= SSMR3PutU64(pSSM, pVmcbNstGstCache->u64TSCOffset);
3407 rc |= SSMR3PutBool(pSSM, pVmcbNstGstCache->fVIntrMasking);
3408 rc |= SSMR3PutBool(pSSM, pVmcbNstGstCache->fNestedPaging);
3409 rc |= SSMR3PutBool(pSSM, pVmcbNstGstCache->fLbrVirt);
3410 AssertRCReturn(rc, rc);
3411 }
3412 }
3413
3414 /* Save the guest patch data. */
3415 rc = SSMR3PutGCPtr(pSSM, pVM->hm.s.pGuestPatchMem);
3416 rc |= SSMR3PutGCPtr(pSSM, pVM->hm.s.pFreeGuestPatchMem);
3417 rc |= SSMR3PutU32(pSSM, pVM->hm.s.cbGuestPatchMem);
3418
3419 /* Store all the guest patch records too. */
3420 rc |= SSMR3PutU32(pSSM, pVM->hm.s.cPatches);
3421 AssertRCReturn(rc, rc);
3422
3423 for (uint32_t i = 0; i < pVM->hm.s.cPatches; i++)
3424 {
3425 AssertCompileSize(HMTPRINSTR, 4);
3426 PCHMTPRPATCH pPatch = &pVM->hm.s.aPatches[i];
3427 rc = SSMR3PutU32(pSSM, pPatch->Core.Key);
3428 rc |= SSMR3PutMem(pSSM, pPatch->aOpcode, sizeof(pPatch->aOpcode));
3429 rc |= SSMR3PutU32(pSSM, pPatch->cbOp);
3430 rc |= SSMR3PutMem(pSSM, pPatch->aNewOpcode, sizeof(pPatch->aNewOpcode));
3431 rc |= SSMR3PutU32(pSSM, pPatch->cbNewOp);
3432 rc |= SSMR3PutU32(pSSM, (uint32_t)pPatch->enmType);
3433 rc |= SSMR3PutU32(pSSM, pPatch->uSrcOperand);
3434 rc |= SSMR3PutU32(pSSM, pPatch->uDstOperand);
3435 rc |= SSMR3PutU32(pSSM, pPatch->pJumpTarget);
3436 rc |= SSMR3PutU32(pSSM, pPatch->cFaults);
3437 AssertRCReturn(rc, rc);
3438 }
3439
3440 return VINF_SUCCESS;
3441}
3442
3443
3444/**
3445 * Execute state load operation.
3446 *
3447 * @returns VBox status code.
3448 * @param pVM The cross context VM structure.
3449 * @param pSSM SSM operation handle.
3450 * @param uVersion Data layout version.
3451 * @param uPass The data pass.
3452 */
3453static DECLCALLBACK(int) hmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
3454{
3455 int rc;
3456
3457 LogFlowFunc(("uVersion=%u\n", uVersion));
3458 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
3459
3460 /*
3461 * Validate version.
3462 */
3463 if ( uVersion != HM_SAVED_STATE_VERSION_SVM_NESTED_HWVIRT
3464 && uVersion != HM_SAVED_STATE_VERSION_TPR_PATCHING
3465 && uVersion != HM_SAVED_STATE_VERSION_NO_TPR_PATCHING
3466 && uVersion != HM_SAVED_STATE_VERSION_2_0_X)
3467 {
3468 AssertMsgFailed(("hmR3Load: Invalid version uVersion=%d!\n", uVersion));
3469 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
3470 }
3471
3472 /*
3473 * Load per-VCPU state.
3474 */
3475 for (VMCPUID i = 0; i < pVM->cCpus; i++)
3476 {
3477 if (uVersion >= HM_SAVED_STATE_VERSION_SVM_NESTED_HWVIRT)
3478 {
3479 /* Load the SVM nested hw.virt state if the VM is configured for it. */
3480 if (pVM->cpum.ro.GuestFeatures.fSvm)
3481 {
3482 PSVMNESTEDVMCBCACHE pVmcbNstGstCache = &pVM->aCpus[i].hm.s.svm.NstGstVmcbCache;
3483 rc = SSMR3GetBool(pSSM, &pVmcbNstGstCache->fCacheValid);
3484 rc |= SSMR3GetU16(pSSM, &pVmcbNstGstCache->u16InterceptRdCRx);
3485 rc |= SSMR3GetU16(pSSM, &pVmcbNstGstCache->u16InterceptWrCRx);
3486 rc |= SSMR3GetU16(pSSM, &pVmcbNstGstCache->u16InterceptRdDRx);
3487 rc |= SSMR3GetU16(pSSM, &pVmcbNstGstCache->u16InterceptWrDRx);
3488 rc |= SSMR3GetU16(pSSM, &pVmcbNstGstCache->u16PauseFilterThreshold);
3489 rc |= SSMR3GetU16(pSSM, &pVmcbNstGstCache->u16PauseFilterCount);
3490 rc |= SSMR3GetU32(pSSM, &pVmcbNstGstCache->u32InterceptXcpt);
3491 rc |= SSMR3GetU64(pSSM, &pVmcbNstGstCache->u64InterceptCtrl);
3492 rc |= SSMR3GetU64(pSSM, &pVmcbNstGstCache->u64TSCOffset);
3493 rc |= SSMR3GetBool(pSSM, &pVmcbNstGstCache->fVIntrMasking);
3494 rc |= SSMR3GetBool(pSSM, &pVmcbNstGstCache->fNestedPaging);
3495 rc |= SSMR3GetBool(pSSM, &pVmcbNstGstCache->fLbrVirt);
3496 AssertRCReturn(rc, rc);
3497 }
3498 }
3499 else
3500 {
3501 /* Pending HM event (obsolete for a long time since TPRM holds the info.) */
3502 rc = SSMR3GetU32(pSSM, &pVM->aCpus[i].hm.s.Event.fPending);
3503 rc |= SSMR3GetU32(pSSM, &pVM->aCpus[i].hm.s.Event.u32ErrCode);
3504 rc |= SSMR3GetU64(pSSM, &pVM->aCpus[i].hm.s.Event.u64IntInfo);
3505
3506 /* VMX fWasInRealMode related data. */
3507 uint32_t uDummy;
3508 rc |= SSMR3GetU32(pSSM, &uDummy); AssertRCReturn(rc, rc);
3509 rc |= SSMR3GetU32(pSSM, &uDummy); AssertRCReturn(rc, rc);
3510 rc |= SSMR3GetU32(pSSM, &uDummy); AssertRCReturn(rc, rc);
3511 AssertRCReturn(rc, rc);
3512 }
3513 }
3514
3515 /*
3516 * Load TPR patching data.
3517 */
3518 if (uVersion >= HM_SAVED_STATE_VERSION_TPR_PATCHING)
3519 {
3520 rc = SSMR3GetGCPtr(pSSM, &pVM->hm.s.pGuestPatchMem);
3521 rc |= SSMR3GetGCPtr(pSSM, &pVM->hm.s.pFreeGuestPatchMem);
3522 rc |= SSMR3GetU32(pSSM, &pVM->hm.s.cbGuestPatchMem);
3523
3524 /* Fetch all TPR patch records. */
3525 rc |= SSMR3GetU32(pSSM, &pVM->hm.s.cPatches);
3526 AssertRCReturn(rc, rc);
3527 for (uint32_t i = 0; i < pVM->hm.s.cPatches; i++)
3528 {
3529 PHMTPRPATCH pPatch = &pVM->hm.s.aPatches[i];
3530 rc = SSMR3GetU32(pSSM, &pPatch->Core.Key);
3531 rc |= SSMR3GetMem(pSSM, pPatch->aOpcode, sizeof(pPatch->aOpcode));
3532 rc |= SSMR3GetU32(pSSM, &pPatch->cbOp);
3533 rc |= SSMR3GetMem(pSSM, pPatch->aNewOpcode, sizeof(pPatch->aNewOpcode));
3534 rc |= SSMR3GetU32(pSSM, &pPatch->cbNewOp);
3535 rc |= SSMR3GetU32(pSSM, (uint32_t *)&pPatch->enmType);
3536
3537 if (pPatch->enmType == HMTPRINSTR_JUMP_REPLACEMENT)
3538 pVM->hm.s.fTPRPatchingActive = true;
3539 Assert(pPatch->enmType == HMTPRINSTR_JUMP_REPLACEMENT || pVM->hm.s.fTPRPatchingActive == false);
3540
3541 rc |= SSMR3GetU32(pSSM, &pPatch->uSrcOperand);
3542 rc |= SSMR3GetU32(pSSM, &pPatch->uDstOperand);
3543 rc |= SSMR3GetU32(pSSM, &pPatch->cFaults);
3544 rc |= SSMR3GetU32(pSSM, &pPatch->pJumpTarget);
3545 AssertRCReturn(rc, rc);
3546
3547 LogFlow(("hmR3Load: patch %d\n", i));
3548 LogFlow(("Key = %x\n", pPatch->Core.Key));
3549 LogFlow(("cbOp = %d\n", pPatch->cbOp));
3550 LogFlow(("cbNewOp = %d\n", pPatch->cbNewOp));
3551 LogFlow(("type = %d\n", pPatch->enmType));
3552 LogFlow(("srcop = %d\n", pPatch->uSrcOperand));
3553 LogFlow(("dstop = %d\n", pPatch->uDstOperand));
3554 LogFlow(("cFaults = %d\n", pPatch->cFaults));
3555 LogFlow(("target = %x\n", pPatch->pJumpTarget));
3556
3557 rc = RTAvloU32Insert(&pVM->hm.s.PatchTree, &pPatch->Core);
3558 AssertRCReturn(rc, rc);
3559 }
3560 }
3561
3562 return VINF_SUCCESS;
3563}
3564
3565
3566/**
3567 * Gets the name of a VT-x exit code.
3568 *
3569 * @returns Pointer to read only string if @a uExit is known, otherwise NULL.
3570 * @param uExit The VT-x exit to name.
3571 */
3572VMMR3DECL(const char *) HMR3GetVmxExitName(uint32_t uExit)
3573{
3574 if (uExit < RT_ELEMENTS(g_apszVTxExitReasons))
3575 return g_apszVTxExitReasons[uExit];
3576 return NULL;
3577}
3578
3579
3580/**
3581 * Gets the name of an AMD-V exit code.
3582 *
3583 * @returns Pointer to read only string if @a uExit is known, otherwise NULL.
3584 * @param uExit The AMD-V exit to name.
3585 */
3586VMMR3DECL(const char *) HMR3GetSvmExitName(uint32_t uExit)
3587{
3588 if (uExit < RT_ELEMENTS(g_apszAmdVExitReasons))
3589 return g_apszAmdVExitReasons[uExit];
3590 return hmSvmGetSpecialExitReasonDesc(uExit);
3591}
3592
3593
3594/**
3595 * Displays HM info.
3596 *
3597 * @param pVM The cross context VM structure.
3598 * @param pHlp The info helper functions.
3599 * @param pszArgs Arguments, ignored.
3600 */
3601static DECLCALLBACK(void) hmR3Info(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
3602{
3603 NOREF(pszArgs);
3604 PVMCPU pVCpu = VMMGetCpu(pVM);
3605 if (!pVCpu)
3606 pVCpu = &pVM->aCpus[0];
3607
3608 if (HMIsEnabled(pVM))
3609 {
3610 if (pVM->hm.s.vmx.fSupported)
3611 pHlp->pfnPrintf(pHlp, "CPU[%u]: VT-x info:\n", pVCpu->idCpu);
3612 else
3613 pHlp->pfnPrintf(pHlp, "CPU[%u]: AMD-V info:\n", pVCpu->idCpu);
3614 pHlp->pfnPrintf(pHlp, " HM error = %#x (%u)\n", pVCpu->hm.s.u32HMError, pVCpu->hm.s.u32HMError);
3615 pHlp->pfnPrintf(pHlp, " rcLastExitToR3 = %Rrc\n", pVCpu->hm.s.rcLastExitToR3);
3616 }
3617 else
3618 pHlp->pfnPrintf(pHlp, "HM is not enabled for this VM!\n");
3619}
3620
3621
3622/**
3623 * Displays the HM pending event.
3624 *
3625 * @param pVM The cross context VM structure.
3626 * @param pHlp The info helper functions.
3627 * @param pszArgs Arguments, ignored.
3628 */
3629static DECLCALLBACK(void) hmR3InfoEventPending(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
3630{
3631 NOREF(pszArgs);
3632 PVMCPU pVCpu = VMMGetCpu(pVM);
3633 if (!pVCpu)
3634 pVCpu = &pVM->aCpus[0];
3635
3636 if (HMIsEnabled(pVM))
3637 {
3638 pHlp->pfnPrintf(pHlp, "CPU[%u]: HM event (fPending=%RTbool)\n", pVCpu->idCpu, pVCpu->hm.s.Event.fPending);
3639 if (pVCpu->hm.s.Event.fPending)
3640 {
3641 pHlp->pfnPrintf(pHlp, " u64IntInfo = %#RX64\n", pVCpu->hm.s.Event.u64IntInfo);
3642 pHlp->pfnPrintf(pHlp, " u32ErrCode = %#RX64\n", pVCpu->hm.s.Event.u32ErrCode);
3643 pHlp->pfnPrintf(pHlp, " cbInstr = %u bytes\n", pVCpu->hm.s.Event.cbInstr);
3644 pHlp->pfnPrintf(pHlp, " GCPtrFaultAddress = %#RGp\n", pVCpu->hm.s.Event.GCPtrFaultAddress);
3645 }
3646 }
3647 else
3648 pHlp->pfnPrintf(pHlp, "HM is not enabled for this VM!\n");
3649}
3650
3651
3652/**
3653 * Displays the SVM nested-guest VMCB cache.
3654 *
3655 * @param pVM The cross context VM structure.
3656 * @param pHlp The info helper functions.
3657 * @param pszArgs Arguments, ignored.
3658 */
3659static DECLCALLBACK(void) hmR3InfoSvmNstGstVmcbCache(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
3660{
3661 NOREF(pszArgs);
3662 PVMCPU pVCpu = VMMGetCpu(pVM);
3663 if (!pVCpu)
3664 pVCpu = &pVM->aCpus[0];
3665
3666 bool const fSvmEnabled = HMR3IsSvmEnabled(pVM->pUVM);
3667 if ( fSvmEnabled
3668 && pVM->cpum.ro.GuestFeatures.fSvm)
3669 {
3670 PCSVMNESTEDVMCBCACHE pVmcbNstGstCache = &pVCpu->hm.s.svm.NstGstVmcbCache;
3671 pHlp->pfnPrintf(pHlp, "CPU[%u]: HM SVM nested-guest VMCB cache\n", pVCpu->idCpu);
3672 pHlp->pfnPrintf(pHlp, " fCacheValid = %#RTbool\n", pVmcbNstGstCache->fCacheValid);
3673 pHlp->pfnPrintf(pHlp, " u16InterceptRdCRx = %#RX16\n", pVmcbNstGstCache->u16InterceptRdCRx);
3674 pHlp->pfnPrintf(pHlp, " u16InterceptWrCRx = %#RX16\n", pVmcbNstGstCache->u16InterceptWrCRx);
3675 pHlp->pfnPrintf(pHlp, " u16InterceptRdDRx = %#RX16\n", pVmcbNstGstCache->u16InterceptRdDRx);
3676 pHlp->pfnPrintf(pHlp, " u16InterceptWrDRx = %#RX16\n", pVmcbNstGstCache->u16InterceptWrDRx);
3677 pHlp->pfnPrintf(pHlp, " u16PauseFilterThreshold = %#RX16\n", pVmcbNstGstCache->u16PauseFilterThreshold);
3678 pHlp->pfnPrintf(pHlp, " u16PauseFilterCount = %#RX16\n", pVmcbNstGstCache->u16PauseFilterCount);
3679 pHlp->pfnPrintf(pHlp, " u32InterceptXcpt = %#RX32\n", pVmcbNstGstCache->u32InterceptXcpt);
3680 pHlp->pfnPrintf(pHlp, " u64InterceptCtrl = %#RX64\n", pVmcbNstGstCache->u64InterceptCtrl);
3681 pHlp->pfnPrintf(pHlp, " u64TSCOffset = %#RX64\n", pVmcbNstGstCache->u64TSCOffset);
3682 pHlp->pfnPrintf(pHlp, " fVIntrMasking = %RTbool\n", pVmcbNstGstCache->fVIntrMasking);
3683 pHlp->pfnPrintf(pHlp, " fNestedPaging = %RTbool\n", pVmcbNstGstCache->fNestedPaging);
3684 pHlp->pfnPrintf(pHlp, " fLbrVirt = %RTbool\n", pVmcbNstGstCache->fLbrVirt);
3685 }
3686 else
3687 {
3688 if (!fSvmEnabled)
3689 pHlp->pfnPrintf(pHlp, "HM SVM is not enabled for this VM!\n");
3690 else
3691 pHlp->pfnPrintf(pHlp, "SVM feature is not exposed to the guest!\n");
3692 }
3693}
3694
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