VirtualBox

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

Last change on this file since 48526 was 48450, checked in by vboxsync, 12 years ago

Corrected hmR3IsCodeSelectorOkForVmx, hmR3IsStackSelectorOkForVmx and hmR3IsDataSelectorOkForVmx as they wasn't taking the unused bit into account and was mixing VT-x requirements with x86/AMD64 CPU requirements.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 138.0 KB
Line 
1/* $Id: HM.cpp 48450 2013-09-12 15:00:15Z vboxsync $ */
2/** @file
3 * HM - Intel/AMD VM Hardware Support Manager.
4 */
5
6/*
7 * Copyright (C) 2006-2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_HM
23#include <VBox/vmm/cpum.h>
24#include <VBox/vmm/stam.h>
25#include <VBox/vmm/mm.h>
26#include <VBox/vmm/pdmapi.h>
27#include <VBox/vmm/pgm.h>
28#include <VBox/vmm/ssm.h>
29#include <VBox/vmm/trpm.h>
30#include <VBox/vmm/dbgf.h>
31#include <VBox/vmm/iom.h>
32#include <VBox/vmm/patm.h>
33#include <VBox/vmm/csam.h>
34#include <VBox/vmm/selm.h>
35#ifdef VBOX_WITH_REM
36# include <VBox/vmm/rem.h>
37#endif
38#include <VBox/vmm/hm_vmx.h>
39#include <VBox/vmm/hm_svm.h>
40#include "HMInternal.h"
41#include <VBox/vmm/vm.h>
42#include <VBox/vmm/uvm.h>
43#include <VBox/err.h>
44#include <VBox/param.h>
45
46#include <iprt/assert.h>
47#include <VBox/log.h>
48#include <iprt/asm.h>
49#include <iprt/asm-amd64-x86.h>
50#include <iprt/string.h>
51#include <iprt/env.h>
52#include <iprt/thread.h>
53
54
55/*******************************************************************************
56* Global Variables *
57*******************************************************************************/
58#ifdef VBOX_WITH_STATISTICS
59# define EXIT_REASON(def, val, str) #def " - " #val " - " str
60# define EXIT_REASON_NIL() NULL
61/** Exit reason descriptions for VT-x, used to describe statistics. */
62static const char * const g_apszVTxExitReasons[MAX_EXITREASON_STAT] =
63{
64 EXIT_REASON(VMX_EXIT_XCPT_OR_NMI , 0, "Exception or non-maskable interrupt (NMI)."),
65 EXIT_REASON(VMX_EXIT_EXT_INT , 1, "External interrupt."),
66 EXIT_REASON(VMX_EXIT_TRIPLE_FAULT , 2, "Triple fault."),
67 EXIT_REASON(VMX_EXIT_INIT_SIGNAL , 3, "INIT signal."),
68 EXIT_REASON(VMX_EXIT_SIPI , 4, "Start-up IPI (SIPI)."),
69 EXIT_REASON(VMX_EXIT_IO_SMI_IRQ , 5, "I/O system-management interrupt (SMI)."),
70 EXIT_REASON(VMX_EXIT_SMI_IRQ , 6, "Other SMI."),
71 EXIT_REASON(VMX_EXIT_INT_WINDOW , 7, "Interrupt window."),
72 EXIT_REASON_NIL(),
73 EXIT_REASON(VMX_EXIT_TASK_SWITCH , 9, "Task switch."),
74 EXIT_REASON(VMX_EXIT_CPUID , 10, "Guest attempted to execute CPUID."),
75 EXIT_REASON_NIL(),
76 EXIT_REASON(VMX_EXIT_HLT , 12, "Guest attempted to execute HLT."),
77 EXIT_REASON(VMX_EXIT_INVD , 13, "Guest attempted to execute INVD."),
78 EXIT_REASON(VMX_EXIT_INVLPG , 14, "Guest attempted to execute INVLPG."),
79 EXIT_REASON(VMX_EXIT_RDPMC , 15, "Guest attempted to execute RDPMC."),
80 EXIT_REASON(VMX_EXIT_RDTSC , 16, "Guest attempted to execute RDTSC."),
81 EXIT_REASON(VMX_EXIT_RSM , 17, "Guest attempted to execute RSM in SMM."),
82 EXIT_REASON(VMX_EXIT_VMCALL , 18, "Guest attempted to execute VMCALL."),
83 EXIT_REASON(VMX_EXIT_VMCLEAR , 19, "Guest attempted to execute VMCLEAR."),
84 EXIT_REASON(VMX_EXIT_VMLAUNCH , 20, "Guest attempted to execute VMLAUNCH."),
85 EXIT_REASON(VMX_EXIT_VMPTRLD , 21, "Guest attempted to execute VMPTRLD."),
86 EXIT_REASON(VMX_EXIT_VMPTRST , 22, "Guest attempted to execute VMPTRST."),
87 EXIT_REASON(VMX_EXIT_VMREAD , 23, "Guest attempted to execute VMREAD."),
88 EXIT_REASON(VMX_EXIT_VMRESUME , 24, "Guest attempted to execute VMRESUME."),
89 EXIT_REASON(VMX_EXIT_VMWRITE , 25, "Guest attempted to execute VMWRITE."),
90 EXIT_REASON(VMX_EXIT_VMXOFF , 26, "Guest attempted to execute VMXOFF."),
91 EXIT_REASON(VMX_EXIT_VMXON , 27, "Guest attempted to execute VMXON."),
92 EXIT_REASON(VMX_EXIT_MOV_CRX , 28, "Control-register accesses."),
93 EXIT_REASON(VMX_EXIT_MOV_DRX , 29, "Debug-register accesses."),
94 EXIT_REASON(VMX_EXIT_PORT_IO , 30, "I/O instruction."),
95 EXIT_REASON(VMX_EXIT_RDMSR , 31, "Guest attempted to execute RDMSR."),
96 EXIT_REASON(VMX_EXIT_WRMSR , 32, "Guest attempted to execute WRMSR."),
97 EXIT_REASON(VMX_EXIT_ERR_INVALID_GUEST_STATE, 33, "VM-entry failure due to invalid guest state."),
98 EXIT_REASON(VMX_EXIT_ERR_MSR_LOAD , 34, "VM-entry failure due to MSR loading."),
99 EXIT_REASON_NIL(),
100 EXIT_REASON(VMX_EXIT_MWAIT , 36, "Guest executed MWAIT."),
101 EXIT_REASON(VMX_EXIT_MTF , 37, "Monitor Trap Flag."),
102 EXIT_REASON_NIL(),
103 EXIT_REASON(VMX_EXIT_MONITOR , 39, "Guest attempted to execute MONITOR."),
104 EXIT_REASON(VMX_EXIT_PAUSE , 40, "Guest attempted to execute PAUSE."),
105 EXIT_REASON(VMX_EXIT_ERR_MACHINE_CHECK , 41, "VM-entry failure due to machine-check."),
106 EXIT_REASON_NIL(),
107 EXIT_REASON(VMX_EXIT_TPR_BELOW_THRESHOLD, 43, "TPR below threshold. Guest attempted to execute MOV to CR8."),
108 EXIT_REASON(VMX_EXIT_APIC_ACCESS , 44, "APIC access. Guest attempted to access memory at a physical address on the APIC-access page."),
109 EXIT_REASON_NIL(),
110 EXIT_REASON(VMX_EXIT_XDTR_ACCESS , 46, "Access to GDTR or IDTR. Guest attempted to execute LGDT, LIDT, SGDT, or SIDT."),
111 EXIT_REASON(VMX_EXIT_TR_ACCESS , 47, "Access to LDTR or TR. Guest attempted to execute LLDT, LTR, SLDT, or STR."),
112 EXIT_REASON(VMX_EXIT_EPT_VIOLATION , 48, "EPT violation. An attempt to access memory with a guest-physical address was disallowed by the configuration of the EPT paging structures."),
113 EXIT_REASON(VMX_EXIT_EPT_MISCONFIG , 49, "EPT misconfiguration. An attempt to access memory with a guest-physical address encountered a misconfigured EPT paging-structure entry."),
114 EXIT_REASON(VMX_EXIT_INVEPT , 50, "Guest attempted to execute INVEPT."),
115 EXIT_REASON(VMX_EXIT_RDTSCP , 51, "Guest attempted to execute RDTSCP."),
116 EXIT_REASON(VMX_EXIT_PREEMPT_TIMER , 52, "VMX-preemption timer expired."),
117 EXIT_REASON(VMX_EXIT_INVVPID , 53, "Guest attempted to execute INVVPID."),
118 EXIT_REASON(VMX_EXIT_WBINVD , 54, "Guest attempted to execute WBINVD."),
119 EXIT_REASON(VMX_EXIT_XSETBV , 55, "Guest attempted to execute XSETBV."),
120 EXIT_REASON_NIL(),
121 EXIT_REASON(VMX_EXIT_RDRAND , 57, "Guest attempted to execute RDRAND."),
122 EXIT_REASON(VMX_EXIT_INVPCID , 58, "Guest attempted to execute INVPCID."),
123 EXIT_REASON(VMX_EXIT_VMFUNC , 59, "Guest attempted to execute VMFUNC.")
124};
125/** Exit reason descriptions for AMD-V, used to describe statistics. */
126static const char * const g_apszAmdVExitReasons[MAX_EXITREASON_STAT] =
127{
128 EXIT_REASON(SVM_EXIT_READ_CR0 , 0, "Read CR0."),
129 EXIT_REASON(SVM_EXIT_READ_CR1 , 1, "Read CR1."),
130 EXIT_REASON(SVM_EXIT_READ_CR2 , 2, "Read CR2."),
131 EXIT_REASON(SVM_EXIT_READ_CR3 , 3, "Read CR3."),
132 EXIT_REASON(SVM_EXIT_READ_CR4 , 4, "Read CR4."),
133 EXIT_REASON(SVM_EXIT_READ_CR5 , 5, "Read CR5."),
134 EXIT_REASON(SVM_EXIT_READ_CR6 , 6, "Read CR6."),
135 EXIT_REASON(SVM_EXIT_READ_CR7 , 7, "Read CR7."),
136 EXIT_REASON(SVM_EXIT_READ_CR8 , 8, "Read CR8."),
137 EXIT_REASON(SVM_EXIT_READ_CR9 , 9, "Read CR9."),
138 EXIT_REASON(SVM_EXIT_READ_CR10 , 10, "Read CR10."),
139 EXIT_REASON(SVM_EXIT_READ_CR11 , 11, "Read CR11."),
140 EXIT_REASON(SVM_EXIT_READ_CR12 , 12, "Read CR12."),
141 EXIT_REASON(SVM_EXIT_READ_CR13 , 13, "Read CR13."),
142 EXIT_REASON(SVM_EXIT_READ_CR14 , 14, "Read CR14."),
143 EXIT_REASON(SVM_EXIT_READ_CR15 , 15, "Read CR15."),
144 EXIT_REASON(SVM_EXIT_WRITE_CR0 , 16, "Write CR0."),
145 EXIT_REASON(SVM_EXIT_WRITE_CR1 , 17, "Write CR1."),
146 EXIT_REASON(SVM_EXIT_WRITE_CR2 , 18, "Write CR2."),
147 EXIT_REASON(SVM_EXIT_WRITE_CR3 , 19, "Write CR3."),
148 EXIT_REASON(SVM_EXIT_WRITE_CR4 , 20, "Write CR4."),
149 EXIT_REASON(SVM_EXIT_WRITE_CR5 , 21, "Write CR5."),
150 EXIT_REASON(SVM_EXIT_WRITE_CR6 , 22, "Write CR6."),
151 EXIT_REASON(SVM_EXIT_WRITE_CR7 , 23, "Write CR7."),
152 EXIT_REASON(SVM_EXIT_WRITE_CR8 , 24, "Write CR8."),
153 EXIT_REASON(SVM_EXIT_WRITE_CR9 , 25, "Write CR9."),
154 EXIT_REASON(SVM_EXIT_WRITE_CR10 , 26, "Write CR10."),
155 EXIT_REASON(SVM_EXIT_WRITE_CR11 , 27, "Write CR11."),
156 EXIT_REASON(SVM_EXIT_WRITE_CR12 , 28, "Write CR12."),
157 EXIT_REASON(SVM_EXIT_WRITE_CR13 , 29, "Write CR13."),
158 EXIT_REASON(SVM_EXIT_WRITE_CR14 , 30, "Write CR14."),
159 EXIT_REASON(SVM_EXIT_WRITE_CR15 , 31, "Write CR15."),
160 EXIT_REASON(SVM_EXIT_READ_DR0 , 32, "Read DR0."),
161 EXIT_REASON(SVM_EXIT_READ_DR1 , 33, "Read DR1."),
162 EXIT_REASON(SVM_EXIT_READ_DR2 , 34, "Read DR2."),
163 EXIT_REASON(SVM_EXIT_READ_DR3 , 35, "Read DR3."),
164 EXIT_REASON(SVM_EXIT_READ_DR4 , 36, "Read DR4."),
165 EXIT_REASON(SVM_EXIT_READ_DR5 , 37, "Read DR5."),
166 EXIT_REASON(SVM_EXIT_READ_DR6 , 38, "Read DR6."),
167 EXIT_REASON(SVM_EXIT_READ_DR7 , 39, "Read DR7."),
168 EXIT_REASON(SVM_EXIT_READ_DR8 , 40, "Read DR8."),
169 EXIT_REASON(SVM_EXIT_READ_DR9 , 41, "Read DR9."),
170 EXIT_REASON(SVM_EXIT_READ_DR10 , 42, "Read DR10."),
171 EXIT_REASON(SVM_EXIT_READ_DR11 , 43, "Read DR11"),
172 EXIT_REASON(SVM_EXIT_READ_DR12 , 44, "Read DR12."),
173 EXIT_REASON(SVM_EXIT_READ_DR13 , 45, "Read DR13."),
174 EXIT_REASON(SVM_EXIT_READ_DR14 , 46, "Read DR14."),
175 EXIT_REASON(SVM_EXIT_READ_DR15 , 47, "Read DR15."),
176 EXIT_REASON(SVM_EXIT_WRITE_DR0 , 48, "Write DR0."),
177 EXIT_REASON(SVM_EXIT_WRITE_DR1 , 49, "Write DR1."),
178 EXIT_REASON(SVM_EXIT_WRITE_DR2 , 50, "Write DR2."),
179 EXIT_REASON(SVM_EXIT_WRITE_DR3 , 51, "Write DR3."),
180 EXIT_REASON(SVM_EXIT_WRITE_DR4 , 52, "Write DR4."),
181 EXIT_REASON(SVM_EXIT_WRITE_DR5 , 53, "Write DR5."),
182 EXIT_REASON(SVM_EXIT_WRITE_DR6 , 54, "Write DR6."),
183 EXIT_REASON(SVM_EXIT_WRITE_DR7 , 55, "Write DR7."),
184 EXIT_REASON(SVM_EXIT_WRITE_DR8 , 56, "Write DR8."),
185 EXIT_REASON(SVM_EXIT_WRITE_DR9 , 57, "Write DR9."),
186 EXIT_REASON(SVM_EXIT_WRITE_DR10 , 58, "Write DR10."),
187 EXIT_REASON(SVM_EXIT_WRITE_DR11 , 59, "Write DR11."),
188 EXIT_REASON(SVM_EXIT_WRITE_DR12 , 60, "Write DR12."),
189 EXIT_REASON(SVM_EXIT_WRITE_DR13 , 61, "Write DR13."),
190 EXIT_REASON(SVM_EXIT_WRITE_DR14 , 62, "Write DR14."),
191 EXIT_REASON(SVM_EXIT_WRITE_DR15 , 63, "Write DR15."),
192 EXIT_REASON(SVM_EXIT_EXCEPTION_0 , 64, "Exception Vector 0 (#DE)."),
193 EXIT_REASON(SVM_EXIT_EXCEPTION_1 , 65, "Exception Vector 1 (#DB)."),
194 EXIT_REASON(SVM_EXIT_EXCEPTION_2 , 66, "Exception Vector 2 (#NMI)."),
195 EXIT_REASON(SVM_EXIT_EXCEPTION_3 , 67, "Exception Vector 3 (#BP)."),
196 EXIT_REASON(SVM_EXIT_EXCEPTION_4 , 68, "Exception Vector 4 (#OF)."),
197 EXIT_REASON(SVM_EXIT_EXCEPTION_5 , 69, "Exception Vector 5 (#BR)."),
198 EXIT_REASON(SVM_EXIT_EXCEPTION_6 , 70, "Exception Vector 6 (#UD)."),
199 EXIT_REASON(SVM_EXIT_EXCEPTION_7 , 71, "Exception Vector 7 (#NM)."),
200 EXIT_REASON(SVM_EXIT_EXCEPTION_8 , 72, "Exception Vector 8 (#DF)."),
201 EXIT_REASON(SVM_EXIT_EXCEPTION_9 , 73, "Exception Vector 9 (#CO_SEG_OVERRUN)."),
202 EXIT_REASON(SVM_EXIT_EXCEPTION_A , 74, "Exception Vector 10 (#TS)."),
203 EXIT_REASON(SVM_EXIT_EXCEPTION_B , 75, "Exception Vector 11 (#NP)."),
204 EXIT_REASON(SVM_EXIT_EXCEPTION_C , 76, "Exception Vector 12 (#SS)."),
205 EXIT_REASON(SVM_EXIT_EXCEPTION_D , 77, "Exception Vector 13 (#GP)."),
206 EXIT_REASON(SVM_EXIT_EXCEPTION_E , 78, "Exception Vector 14 (#PF)."),
207 EXIT_REASON(SVM_EXIT_EXCEPTION_F , 79, "Exception Vector 15 (0x0f)."),
208 EXIT_REASON(SVM_EXIT_EXCEPTION_10 , 80, "Exception Vector 16 (#MF)."),
209 EXIT_REASON(SVM_EXIT_EXCEPTION_11 , 81, "Exception Vector 17 (#AC)."),
210 EXIT_REASON(SVM_EXIT_EXCEPTION_12 , 82, "Exception Vector 18 (#MC)."),
211 EXIT_REASON(SVM_EXIT_EXCEPTION_13 , 83, "Exception Vector 19 (#XF)."),
212 EXIT_REASON(SVM_EXIT_EXCEPTION_14 , 84, "Exception Vector 20 (0x14)."),
213 EXIT_REASON(SVM_EXIT_EXCEPTION_15 , 85, "Exception Vector 22 (0x15)."),
214 EXIT_REASON(SVM_EXIT_EXCEPTION_16 , 86, "Exception Vector 22 (0x16)."),
215 EXIT_REASON(SVM_EXIT_EXCEPTION_17 , 87, "Exception Vector 23 (0x17)."),
216 EXIT_REASON(SVM_EXIT_EXCEPTION_18 , 88, "Exception Vector 24 (0x18)."),
217 EXIT_REASON(SVM_EXIT_EXCEPTION_19 , 89, "Exception Vector 25 (0x19)."),
218 EXIT_REASON(SVM_EXIT_EXCEPTION_1A , 90, "Exception Vector 26 (0x1A)."),
219 EXIT_REASON(SVM_EXIT_EXCEPTION_1B , 91, "Exception Vector 27 (0x1B)."),
220 EXIT_REASON(SVM_EXIT_EXCEPTION_1C , 92, "Exception Vector 28 (0x1C)."),
221 EXIT_REASON(SVM_EXIT_EXCEPTION_1D , 93, "Exception Vector 29 (0x1D)."),
222 EXIT_REASON(SVM_EXIT_EXCEPTION_1E , 94, "Exception Vector 30 (0x1E)."),
223 EXIT_REASON(SVM_EXIT_EXCEPTION_1F , 95, "Exception Vector 31 (0x1F)."),
224 EXIT_REASON(SVM_EXIT_INTR , 96, "Physical maskable interrupt (host)."),
225 EXIT_REASON(SVM_EXIT_NMI , 97, "Physical non-maskable interrupt (host)."),
226 EXIT_REASON(SVM_EXIT_SMI , 98, "System management interrupt (host)."),
227 EXIT_REASON(SVM_EXIT_INIT , 99, "Physical INIT signal (host)."),
228 EXIT_REASON(SVM_EXIT_VINTR ,100, "Virtual interrupt-window exit."),
229 EXIT_REASON(SVM_EXIT_CR0_SEL_WRITE ,101, "Write to CR0 that changed any bits other than CR0.TS or CR0.MP."),
230 EXIT_REASON(SVM_EXIT_IDTR_READ ,102, "Read IDTR"),
231 EXIT_REASON(SVM_EXIT_GDTR_READ ,103, "Read GDTR"),
232 EXIT_REASON(SVM_EXIT_LDTR_READ ,104, "Read LDTR."),
233 EXIT_REASON(SVM_EXIT_TR_READ ,105, "Read TR."),
234 EXIT_REASON(SVM_EXIT_TR_READ ,106, "Write IDTR."),
235 EXIT_REASON(SVM_EXIT_TR_READ ,107, "Write GDTR."),
236 EXIT_REASON(SVM_EXIT_TR_READ ,108, "Write LDTR."),
237 EXIT_REASON(SVM_EXIT_TR_READ ,109, "Write TR."),
238 EXIT_REASON(SVM_EXIT_RDTSC ,110, "RDTSC instruction."),
239 EXIT_REASON(SVM_EXIT_RDPMC ,111, "RDPMC instruction."),
240 EXIT_REASON(SVM_EXIT_PUSHF ,112, "PUSHF instruction."),
241 EXIT_REASON(SVM_EXIT_POPF ,113, "POPF instruction."),
242 EXIT_REASON(SVM_EXIT_CPUID ,114, "CPUID instruction."),
243 EXIT_REASON(SVM_EXIT_RSM ,115, "RSM instruction."),
244 EXIT_REASON(SVM_EXIT_IRET ,116, "IRET instruction."),
245 EXIT_REASON(SVM_EXIT_SWINT ,117, "Software interrupt (INTn instructions)."),
246 EXIT_REASON(SVM_EXIT_INVD ,118, "INVD instruction."),
247 EXIT_REASON(SVM_EXIT_PAUSE ,119, "PAUSE instruction."),
248 EXIT_REASON(SVM_EXIT_HLT ,120, "HLT instruction."),
249 EXIT_REASON(SVM_EXIT_INVLPG ,121, "INVLPG instruction."),
250 EXIT_REASON(SVM_EXIT_INVLPGA ,122, "INVLPGA instruction."),
251 EXIT_REASON(SVM_EXIT_IOIO ,123, "IN/OUT accessing protected port."),
252 EXIT_REASON(SVM_EXIT_MSR ,124, "RDMSR or WRMSR access to protected MSR."),
253 EXIT_REASON(SVM_EXIT_TASK_SWITCH ,125, "Task switch."),
254 EXIT_REASON(SVM_EXIT_FERR_FREEZE ,126, "Legacy FPU handling enabled; processor is frozen in an x87/mmx instruction waiting for an interrupt"),
255 EXIT_REASON(SVM_EXIT_SHUTDOWN ,127, "Shutdown."),
256 EXIT_REASON(SVM_EXIT_VMRUN ,128, "VMRUN instruction."),
257 EXIT_REASON(SVM_EXIT_VMMCALL ,129, "VMCALL instruction."),
258 EXIT_REASON(SVM_EXIT_VMLOAD ,130, "VMLOAD instruction."),
259 EXIT_REASON(SVM_EXIT_VMSAVE ,131, "VMSAVE instruction."),
260 EXIT_REASON(SVM_EXIT_STGI ,132, "STGI instruction."),
261 EXIT_REASON(SVM_EXIT_CLGI ,133, "CLGI instruction."),
262 EXIT_REASON(SVM_EXIT_SKINIT ,134, "SKINIT instruction."),
263 EXIT_REASON(SVM_EXIT_RDTSCP ,135, "RDTSCP instruction."),
264 EXIT_REASON(SVM_EXIT_ICEBP ,136, "ICEBP instruction."),
265 EXIT_REASON(SVM_EXIT_WBINVD ,137, "WBINVD instruction."),
266 EXIT_REASON(SVM_EXIT_MONITOR ,138, "MONITOR instruction."),
267 EXIT_REASON(SVM_EXIT_MWAIT ,139, "MWAIT instruction."),
268 EXIT_REASON(SVM_EXIT_MWAIT_ARMED ,140, "MWAIT instruction when armed."),
269 EXIT_REASON(SVM_EXIT_NPF ,1024, "Nested paging fault."),
270 EXIT_REASON_NIL()
271};
272# undef EXIT_REASON
273# undef EXIT_REASON_NIL
274#endif /* VBOX_WITH_STATISTICS */
275
276#define HMVMX_REPORT_FEATURE(allowed1, disallowed0, featflag) \
277 do { \
278 if ((allowed1) & (featflag)) \
279 LogRel(("HM: " #featflag "\n")); \
280 else \
281 LogRel(("HM: " #featflag " *must* be cleared\n")); \
282 if ((disallowed0) & (featflag)) \
283 LogRel(("HM: " #featflag " *must* be set\n")); \
284 } while (0)
285
286#define HMVMX_REPORT_ALLOWED_FEATURE(allowed1, featflag) \
287 do { \
288 if ((allowed1) & (featflag)) \
289 LogRel(("HM: " #featflag "\n")); \
290 else \
291 LogRel(("HM: " #featflag " not supported\n")); \
292 } while (0)
293
294#define HMVMX_REPORT_CAPABILITY(msrcaps, cap) \
295 do { \
296 if ((msrcaps) & (cap)) \
297 LogRel(("HM: " #cap "\n")); \
298 } while (0)
299
300
301/*******************************************************************************
302* Internal Functions *
303*******************************************************************************/
304static DECLCALLBACK(int) hmR3Save(PVM pVM, PSSMHANDLE pSSM);
305static DECLCALLBACK(int) hmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
306static int hmR3InitCPU(PVM pVM);
307static int hmR3InitFinalizeR0(PVM pVM);
308static int hmR3InitFinalizeR0Intel(PVM pVM);
309static int hmR3InitFinalizeR0Amd(PVM pVM);
310static int hmR3TermCPU(PVM pVM);
311
312
313
314/**
315 * Initializes the HM.
316 *
317 * This reads the config and check whether VT-x or AMD-V hardware is available
318 * if configured to use it. This is one of the very first components to be
319 * initialized after CFGM, so that we can fall back to raw-mode early in the
320 * initialization process.
321 *
322 * Note that a lot of the set up work is done in ring-0 and thus postponed till
323 * the ring-3 and ring-0 callback to HMR3InitCompleted.
324 *
325 * @returns VBox status code.
326 * @param pVM Pointer to the VM.
327 *
328 * @remarks Be careful with what we call here, since most of the VMM components
329 * are uninitialized.
330 */
331VMMR3_INT_DECL(int) HMR3Init(PVM pVM)
332{
333 LogFlow(("HMR3Init\n"));
334
335 /*
336 * Assert alignment and sizes.
337 */
338 AssertCompileMemberAlignment(VM, hm.s, 32);
339 AssertCompile(sizeof(pVM->hm.s) <= sizeof(pVM->hm.padding));
340
341 /*
342 * Register the saved state data unit.
343 */
344 int rc = SSMR3RegisterInternal(pVM, "HWACCM", 0, HM_SSM_VERSION, sizeof(HM),
345 NULL, NULL, NULL,
346 NULL, hmR3Save, NULL,
347 NULL, hmR3Load, NULL);
348 if (RT_FAILURE(rc))
349 return rc;
350
351 /*
352 * Misc initialisation.
353 */
354 //pVM->hm.s.vmx.fSupported = false;
355 //pVM->hm.s.svm.fSupported = false;
356 //pVM->hm.s.vmx.fEnabled = false;
357 //pVM->hm.s.svm.fEnabled = false;
358 //pVM->hm.s.fNestedPaging = false;
359
360
361 /*
362 * Read configuration.
363 */
364 PCFGMNODE pCfgHM = CFGMR3GetChild(CFGMR3GetRoot(pVM), "HM/");
365
366 /** @cfgm{/HM/HMForced, bool, false}
367 * Forces hardware virtualization, no falling back on raw-mode. HM must be
368 * enabled, i.e. /HMEnabled must be true. */
369 bool fHMForced;
370#ifdef VBOX_WITH_RAW_MODE
371 rc = CFGMR3QueryBoolDef(pCfgHM, "HMForced", &fHMForced, false);
372 AssertRCReturn(rc, rc);
373 AssertLogRelMsgReturn(!fHMForced || pVM->fHMEnabled, ("Configuration error: HM forced but not enabled!\n"),
374 VERR_INVALID_PARAMETER);
375# if defined(RT_OS_DARWIN)
376 if (pVM->fHMEnabled)
377 fHMForced = true;
378# endif
379 AssertLogRelMsgReturn(pVM->cCpus == 1 || pVM->fHMEnabled, ("Configuration error: SMP requires HM to be enabled!\n"),
380 VERR_INVALID_PARAMETER);
381 if (pVM->cCpus > 1)
382 fHMForced = true;
383#else /* !VBOX_WITH_RAW_MODE */
384 AssertRelease(pVM->fHMEnabled);
385 fHMForced = true;
386#endif /* !VBOX_WITH_RAW_MODE */
387
388 /** @cfgm{/HM/EnableNestedPaging, bool, false}
389 * Enables nested paging (aka extended page tables). */
390 rc = CFGMR3QueryBoolDef(pCfgHM, "EnableNestedPaging", &pVM->hm.s.fAllowNestedPaging, false);
391 AssertRCReturn(rc, rc);
392
393 /** @cfgm{/HM/EnableUX, bool, true}
394 * Enables the VT-x unrestricted execution feature. */
395 rc = CFGMR3QueryBoolDef(pCfgHM, "EnableUX", &pVM->hm.s.vmx.fAllowUnrestricted, true);
396 AssertRCReturn(rc, rc);
397
398 /** @cfgm{/HM/EnableLargePages, bool, false}
399 * Enables using large pages (2 MB) for guest memory, thus saving on (nested)
400 * page table walking and maybe better TLB hit rate in some cases. */
401 rc = CFGMR3QueryBoolDef(pCfgHM, "EnableLargePages", &pVM->hm.s.fLargePages, false);
402 AssertRCReturn(rc, rc);
403
404 /** @cfgm{/HM/EnableVPID, bool, false}
405 * Enables the VT-x VPID feature. */
406 rc = CFGMR3QueryBoolDef(pCfgHM, "EnableVPID", &pVM->hm.s.vmx.fAllowVpid, false);
407 AssertRCReturn(rc, rc);
408
409 /** @cfgm{/HM/TPRPatchingEnabled, bool, false}
410 * Enables TPR patching for 32-bit windows guests with IO-APIC. */
411 rc = CFGMR3QueryBoolDef(pCfgHM, "TPRPatchingEnabled", &pVM->hm.s.fTRPPatchingAllowed, false);
412 AssertRCReturn(rc, rc);
413
414 /** @cfgm{/HM/64bitEnabled, bool, 32-bit:false, 64-bit:true}
415 * Enables AMD64 cpu features.
416 * On 32-bit hosts this isn't default and require host CPU support. 64-bit hosts
417 * already have the support. */
418#ifdef VBOX_ENABLE_64_BITS_GUESTS
419 rc = CFGMR3QueryBoolDef(pCfgHM, "64bitEnabled", &pVM->hm.s.fAllow64BitGuests, HC_ARCH_BITS == 64);
420 AssertLogRelRCReturn(rc, rc);
421#else
422 pVM->hm.s.fAllow64BitGuests = false;
423#endif
424
425 /** @cfgm{/HM/Exclusive, bool}
426 * Determines the init method for AMD-V and VT-x. If set to true, HM will do a
427 * global init for each host CPU. If false, we do local init each time we wish
428 * to execute guest code.
429 *
430 * Default is false for Mac OS X and Windows due to the higher risk of conflicts
431 * with other hypervisors.
432 */
433 rc = CFGMR3QueryBoolDef(pCfgHM, "Exclusive", &pVM->hm.s.fGlobalInit,
434#if defined(RT_OS_DARWIN) || defined(RT_OS_WINDOWS)
435 false
436#else
437 true
438#endif
439 );
440 AssertLogRelRCReturn(rc, rc);
441
442 /** @cfgm{/HM/MaxResumeLoops, uint32_t}
443 * The number of times to resume guest execution before we forcibly return to
444 * ring-3. The return value of RTThreadPreemptIsPendingTrusty in ring-0
445 * determines the default value. */
446 rc = CFGMR3QueryU32Def(pCfgHM, "MaxResumeLoops", &pVM->hm.s.cMaxResumeLoops, 0 /* set by R0 later */);
447 AssertLogRelRCReturn(rc, rc);
448
449 /*
450 * Check if VT-x or AMD-v support according to the users wishes.
451 */
452 /** @todo SUPR3QueryVTCaps won't catch VERR_VMX_IN_VMX_ROOT_MODE or
453 * VERR_SVM_IN_USE. */
454 if (pVM->fHMEnabled)
455 {
456 uint32_t fCaps;
457 rc = SUPR3QueryVTCaps(&fCaps);
458 if (RT_SUCCESS(rc))
459 {
460 if (fCaps & SUPVTCAPS_AMD_V)
461 LogRel(("HMR3Init: AMD-V%s\n", fCaps & SUPVTCAPS_NESTED_PAGING ? " w/ nested paging" : ""));
462 else if (fCaps & SUPVTCAPS_VT_X)
463 {
464 rc = SUPR3QueryVTxSupported();
465 if (RT_SUCCESS(rc))
466 LogRel(("HMR3Init: VT-x%s\n", fCaps & SUPVTCAPS_NESTED_PAGING ? " w/ nested paging" : ""));
467 else
468 {
469#ifdef RT_OS_LINUX
470 const char *pszMinReq = " Linux 2.6.13 or newer required!";
471#else
472 const char *pszMinReq = "";
473#endif
474 if (fHMForced)
475 return VMSetError(pVM, rc, RT_SRC_POS, "The host kernel does not support VT-x.%s\n", pszMinReq);
476
477 /* Fall back to raw-mode. */
478 LogRel(("HMR3Init: Falling back to raw-mode: The host kernel does not support VT-x.%s\n", pszMinReq));
479 pVM->fHMEnabled = false;
480 }
481 }
482 else
483 AssertLogRelMsgFailedReturn(("SUPR3QueryVTCaps didn't return either AMD-V or VT-x flag set (%#x)!\n", fCaps),
484 VERR_INTERNAL_ERROR_5);
485
486 /*
487 * Do we require a little bit or raw-mode for 64-bit guest execution?
488 */
489 pVM->fHMNeedRawModeCtx = HC_ARCH_BITS == 32
490 && pVM->fHMEnabled
491 && pVM->hm.s.fAllow64BitGuests;
492 }
493 else
494 {
495 const char *pszMsg;
496 switch (rc)
497 {
498 case VERR_UNSUPPORTED_CPU:
499 pszMsg = "Unknown CPU, VT-x or AMD-v features cannot be ascertained.";
500 break;
501
502 case VERR_VMX_NO_VMX:
503 pszMsg = "VT-x is not available.";
504 break;
505
506 case VERR_VMX_MSR_VMXON_DISABLED:
507 pszMsg = "VT-x is disabled in the BIOS.";
508 break;
509
510 case VERR_VMX_MSR_SMX_VMXON_DISABLED:
511 pszMsg = "VT-x is disabled in the BIOS for Safer-Mode/Trusted Extensions.";
512 break;
513
514 case VERR_VMX_MSR_LOCKING_FAILED:
515 pszMsg = "Failed to enable and lock VT-x features.";
516 break;
517
518 case VERR_SVM_NO_SVM:
519 pszMsg = "AMD-V is not available.";
520 break;
521
522 case VERR_SVM_DISABLED:
523 pszMsg = "AMD-V is disabled in the BIOS (or by the host OS).";
524 break;
525
526 default:
527 pszMsg = NULL;
528 break;
529 }
530 if (fHMForced && pszMsg)
531 return VM_SET_ERROR(pVM, rc, pszMsg);
532 if (!pszMsg)
533 return VMSetError(pVM, rc, RT_SRC_POS, "SUPR3QueryVTCaps failed with %Rrc", rc);
534
535 /* Fall back to raw-mode. */
536 LogRel(("HMR3Init: Falling back to raw-mode: %s\n", pszMsg));
537 pVM->fHMEnabled = false;
538 }
539 }
540
541 /* It's now OK to use the predicate function. */
542 pVM->fHMEnabledFixed = true;
543 return VINF_SUCCESS;
544}
545
546
547/**
548 * Initializes the per-VCPU HM.
549 *
550 * @returns VBox status code.
551 * @param pVM Pointer to the VM.
552 */
553static int hmR3InitCPU(PVM pVM)
554{
555 LogFlow(("HMR3InitCPU\n"));
556
557 if (!HMIsEnabled(pVM))
558 return VINF_SUCCESS;
559
560 for (VMCPUID i = 0; i < pVM->cCpus; i++)
561 {
562 PVMCPU pVCpu = &pVM->aCpus[i];
563 pVCpu->hm.s.fActive = false;
564 }
565
566#ifdef VBOX_WITH_STATISTICS
567 STAM_REG(pVM, &pVM->hm.s.StatTprPatchSuccess, STAMTYPE_COUNTER, "/HM/TPR/Patch/Success", STAMUNIT_OCCURENCES, "Number of times an instruction was successfully patched.");
568 STAM_REG(pVM, &pVM->hm.s.StatTprPatchFailure, STAMTYPE_COUNTER, "/HM/TPR/Patch/Failed", STAMUNIT_OCCURENCES, "Number of unsuccessful patch attempts.");
569 STAM_REG(pVM, &pVM->hm.s.StatTprReplaceSuccess, STAMTYPE_COUNTER, "/HM/TPR/Replace/Success",STAMUNIT_OCCURENCES, "Number of times an instruction was successfully patched.");
570 STAM_REG(pVM, &pVM->hm.s.StatTprReplaceFailure, STAMTYPE_COUNTER, "/HM/TPR/Replace/Failed", STAMUNIT_OCCURENCES, "Number of unsuccessful patch attempts.");
571#endif
572
573 /*
574 * Statistics.
575 */
576 for (VMCPUID i = 0; i < pVM->cCpus; i++)
577 {
578 PVMCPU pVCpu = &pVM->aCpus[i];
579 int rc;
580
581#ifdef VBOX_WITH_STATISTICS
582 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatPoke, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
583 "Profiling of RTMpPokeCpu",
584 "/PROF/CPU%d/HM/Poke", i);
585 AssertRC(rc);
586 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatSpinPoke, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
587 "Profiling of poke wait",
588 "/PROF/CPU%d/HM/PokeWait", i);
589 AssertRC(rc);
590 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatSpinPokeFailed, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
591 "Profiling of poke wait when RTMpPokeCpu fails",
592 "/PROF/CPU%d/HM/PokeWaitFailed", i);
593 AssertRC(rc);
594 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatEntry, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
595 "Profiling of VMXR0RunGuestCode entry",
596 "/PROF/CPU%d/HM/StatEntry", i);
597 AssertRC(rc);
598 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatExit1, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
599 "Profiling of VMXR0RunGuestCode exit part 1",
600 "/PROF/CPU%d/HM/SwitchFromGC_1", i);
601 AssertRC(rc);
602 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatExit2, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
603 "Profiling of VMXR0RunGuestCode exit part 2",
604 "/PROF/CPU%d/HM/SwitchFromGC_2", i);
605 AssertRC(rc);
606
607 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatExitIO, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
608 "I/O",
609 "/PROF/CPU%d/HM/SwitchFromGC_2/IO", i);
610 AssertRC(rc);
611 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatExitMovCRx, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
612 "MOV CRx",
613 "/PROF/CPU%d/HM/SwitchFromGC_2/MovCRx", i);
614 AssertRC(rc);
615 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatExitXcptNmi, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
616 "Exceptions, NMIs",
617 "/PROF/CPU%d/HM/SwitchFromGC_2/XcptNmi", i);
618 AssertRC(rc);
619
620 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatLoadGuestState, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
621 "Profiling of VMXR0LoadGuestState",
622 "/PROF/CPU%d/HM/StatLoadGuestState", i);
623 AssertRC(rc);
624 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatInGC, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL,
625 "Profiling of VMLAUNCH/VMRESUME.",
626 "/PROF/CPU%d/HM/InGC", i);
627 AssertRC(rc);
628
629# if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS) && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)
630 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatWorldSwitch3264, STAMTYPE_PROFILE, STAMVISIBILITY_USED,
631 STAMUNIT_TICKS_PER_CALL, "Profiling of the 32/64 switcher.",
632 "/PROF/CPU%d/HM/Switcher3264", i);
633 AssertRC(rc);
634# endif
635
636# ifdef HM_PROFILE_EXIT_DISPATCH
637 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatExitDispatch, STAMTYPE_PROFILE_ADV, STAMVISIBILITY_USED,
638 STAMUNIT_TICKS_PER_CALL, "Profiling the dispatching of exit handlers.",
639 "/PROF/CPU%d/HM/ExitDispatch", i);
640 AssertRC(rc);
641# endif
642
643#endif
644# define HM_REG_COUNTER(a, b, desc) \
645 rc = STAMR3RegisterF(pVM, a, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, desc, b, i); \
646 AssertRC(rc);
647
648#ifdef VBOX_WITH_STATISTICS
649 HM_REG_COUNTER(&pVCpu->hm.s.StatExitShadowNM, "/HM/CPU%d/Exit/Trap/Shw/#NM", "Shadow #NM (device not available, no math co-processor) exception.");
650 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestNM, "/HM/CPU%d/Exit/Trap/Gst/#NM", "Guest #NM (device not available, no math co-processor) exception.");
651 HM_REG_COUNTER(&pVCpu->hm.s.StatExitShadowPF, "/HM/CPU%d/Exit/Trap/Shw/#PF", "Shadow #PF (page fault) exception.");
652 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.");
653 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestPF, "/HM/CPU%d/Exit/Trap/Gst/#PF", "Guest #PF (page fault) exception.");
654 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestUD, "/HM/CPU%d/Exit/Trap/Gst/#UD", "Guest #UD (undefined opcode) exception.");
655 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestSS, "/HM/CPU%d/Exit/Trap/Gst/#SS", "Guest #SS (stack-segment fault) exception.");
656 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestNP, "/HM/CPU%d/Exit/Trap/Gst/#NP", "Guest #NP (segment not present) exception.");
657 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestGP, "/HM/CPU%d/Exit/Trap/Gst/#GP", "Guest #GP (general protection) execption.");
658 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestMF, "/HM/CPU%d/Exit/Trap/Gst/#MF", "Guest #MF (x87 FPU error, math fault) exception.");
659 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestDE, "/HM/CPU%d/Exit/Trap/Gst/#DE", "Guest #DE (divide error) exception.");
660 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestDB, "/HM/CPU%d/Exit/Trap/Gst/#DB", "Guest #DB (debug) exception.");
661 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestBP, "/HM/CPU%d/Exit/Trap/Gst/#BP", "Guest #BP (breakpoint) exception.");
662 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestXF, "/HM/CPU%d/Exit/Trap/Gst/#XF", "Guest #XF (extended math fault, SIMD FPU) exception.");
663 HM_REG_COUNTER(&pVCpu->hm.s.StatExitGuestXcpUnk, "/HM/CPU%d/Exit/Trap/Gst/Other", "Other guest exceptions.");
664 HM_REG_COUNTER(&pVCpu->hm.s.StatExitInvlpg, "/HM/CPU%d/Exit/Instr/Invlpg", "Guest attempted to execute INVLPG.");
665 HM_REG_COUNTER(&pVCpu->hm.s.StatExitInvd, "/HM/CPU%d/Exit/Instr/Invd", "Guest attempted to execute INVD.");
666 HM_REG_COUNTER(&pVCpu->hm.s.StatExitWbinvd, "/HM/CPU%d/Exit/Instr/Wbinvd", "Guest attempted to execute WBINVD.");
667 HM_REG_COUNTER(&pVCpu->hm.s.StatExitPause, "/HM/CPU%d/Exit/Instr/Pause", "Guest attempted to execute PAUSE.");
668 HM_REG_COUNTER(&pVCpu->hm.s.StatExitCpuid, "/HM/CPU%d/Exit/Instr/Cpuid", "Guest attempted to execute CPUID.");
669 HM_REG_COUNTER(&pVCpu->hm.s.StatExitRdtsc, "/HM/CPU%d/Exit/Instr/Rdtsc", "Guest attempted to execute RDTSC.");
670 HM_REG_COUNTER(&pVCpu->hm.s.StatExitRdtscp, "/HM/CPU%d/Exit/Instr/Rdtscp", "Guest attempted to execute RDTSCP.");
671 HM_REG_COUNTER(&pVCpu->hm.s.StatExitRdpmc, "/HM/CPU%d/Exit/Instr/Rdpmc", "Guest attempted to execute RDPMC.");
672 HM_REG_COUNTER(&pVCpu->hm.s.StatExitRdrand, "/HM/CPU%d/Exit/Instr/Rdrand", "Guest attempted to execute RDRAND.");
673 HM_REG_COUNTER(&pVCpu->hm.s.StatExitRdmsr, "/HM/CPU%d/Exit/Instr/Rdmsr", "Guest attempted to execute RDMSR.");
674 HM_REG_COUNTER(&pVCpu->hm.s.StatExitWrmsr, "/HM/CPU%d/Exit/Instr/Wrmsr", "Guest attempted to execute WRMSR.");
675 HM_REG_COUNTER(&pVCpu->hm.s.StatExitMwait, "/HM/CPU%d/Exit/Instr/Mwait", "Guest attempted to execute MWAIT.");
676 HM_REG_COUNTER(&pVCpu->hm.s.StatExitMonitor, "/HM/CPU%d/Exit/Instr/Monitor", "Guest attempted to execute MONITOR.");
677 HM_REG_COUNTER(&pVCpu->hm.s.StatExitDRxWrite, "/HM/CPU%d/Exit/Instr/DR/Write", "Guest attempted to write a debug register.");
678 HM_REG_COUNTER(&pVCpu->hm.s.StatExitDRxRead, "/HM/CPU%d/Exit/Instr/DR/Read", "Guest attempted to read a debug register.");
679 HM_REG_COUNTER(&pVCpu->hm.s.StatExitClts, "/HM/CPU%d/Exit/Instr/CLTS", "Guest attempted to execute CLTS.");
680 HM_REG_COUNTER(&pVCpu->hm.s.StatExitLmsw, "/HM/CPU%d/Exit/Instr/LMSW", "Guest attempted to execute LMSW.");
681 HM_REG_COUNTER(&pVCpu->hm.s.StatExitCli, "/HM/CPU%d/Exit/Instr/Cli", "Guest attempted to execute CLI.");
682 HM_REG_COUNTER(&pVCpu->hm.s.StatExitSti, "/HM/CPU%d/Exit/Instr/Sti", "Guest attempted to execute STI.");
683 HM_REG_COUNTER(&pVCpu->hm.s.StatExitPushf, "/HM/CPU%d/Exit/Instr/Pushf", "Guest attempted to execute PUSHF.");
684 HM_REG_COUNTER(&pVCpu->hm.s.StatExitPopf, "/HM/CPU%d/Exit/Instr/Popf", "Guest attempted to execute POPF.");
685 HM_REG_COUNTER(&pVCpu->hm.s.StatExitIret, "/HM/CPU%d/Exit/Instr/Iret", "Guest attempted to execute IRET.");
686 HM_REG_COUNTER(&pVCpu->hm.s.StatExitInt, "/HM/CPU%d/Exit/Instr/Int", "Guest attempted to execute INT.");
687 HM_REG_COUNTER(&pVCpu->hm.s.StatExitHlt, "/HM/CPU%d/Exit/Instr/Hlt", "Guest attempted to execute HLT.");
688 HM_REG_COUNTER(&pVCpu->hm.s.StatExitXdtrAccess, "/HM/CPU%d/Exit/Instr/XdtrAccess", "Guest attempted to access descriptor table register (GDTR, IDTR, LDTR).");
689 HM_REG_COUNTER(&pVCpu->hm.s.StatExitIOWrite, "/HM/CPU%d/Exit/IO/Write", "I/O write.");
690 HM_REG_COUNTER(&pVCpu->hm.s.StatExitIORead, "/HM/CPU%d/Exit/IO/Read", "I/O read.");
691 HM_REG_COUNTER(&pVCpu->hm.s.StatExitIOStringWrite, "/HM/CPU%d/Exit/IO/WriteString", "String I/O write.");
692 HM_REG_COUNTER(&pVCpu->hm.s.StatExitIOStringRead, "/HM/CPU%d/Exit/IO/ReadString", "String I/O read.");
693 HM_REG_COUNTER(&pVCpu->hm.s.StatExitIntWindow, "/HM/CPU%d/Exit/IntWindow", "Interrupt-window exit. Guest is ready to receive interrupts again.");
694 HM_REG_COUNTER(&pVCpu->hm.s.StatExitMaxResume, "/HM/CPU%d/Exit/MaxResume", "Maximum VMRESUME inner-loop counter reached.");
695 HM_REG_COUNTER(&pVCpu->hm.s.StatExitExtInt, "/HM/CPU%d/Exit/ExtInt", "Host interrupt received.");
696#endif
697 HM_REG_COUNTER(&pVCpu->hm.s.StatExitHostNmiInGC, "/HM/CPU%d/Exit/HostNmiInGC", "Host NMI received while in guest context.");
698#ifdef VBOX_WITH_STATISTICS
699 HM_REG_COUNTER(&pVCpu->hm.s.StatExitPreemptTimer, "/HM/CPU%d/Exit/PreemptTimer", "VMX-preemption timer expired.");
700 HM_REG_COUNTER(&pVCpu->hm.s.StatExitTprBelowThreshold, "/HM/CPU%d/Exit/TprBelowThreshold", "TPR lowered below threshold by the guest.");
701 HM_REG_COUNTER(&pVCpu->hm.s.StatExitTaskSwitch, "/HM/CPU%d/Exit/TaskSwitch", "Guest attempted a task switch.");
702 HM_REG_COUNTER(&pVCpu->hm.s.StatExitMtf, "/HM/CPU%d/Exit/MonitorTrapFlag", "Monitor Trap Flag.");
703 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.");
704
705 HM_REG_COUNTER(&pVCpu->hm.s.StatSwitchGuestIrq, "/HM/CPU%d/Switch/IrqPending", "PDMGetInterrupt() cleared behind our back!?!.");
706 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.");
707 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.");
708 HM_REG_COUNTER(&pVCpu->hm.s.StatSwitchExitToR3, "/HM/CPU%d/Switch/ExitToR3", "Exit to ring-3 (total).");
709 HM_REG_COUNTER(&pVCpu->hm.s.StatSwitchLongJmpToR3, "/HM/CPU%d/Switch/LongJmpToR3", "Longjump to ring-3.");
710
711 HM_REG_COUNTER(&pVCpu->hm.s.StatInjectInterrupt, "/HM/CPU%d/EventInject/Interrupt", "Injected an external interrupt into the guest.");
712 HM_REG_COUNTER(&pVCpu->hm.s.StatInjectXcpt, "/HM/CPU%d/EventInject/Trap", "Injected an exception into the guest.");
713 HM_REG_COUNTER(&pVCpu->hm.s.StatInjectPendingReflect, "/HM/CPU%d/EventInject/PendingReflect", "Reflecting an exception back to the guest.");
714
715 HM_REG_COUNTER(&pVCpu->hm.s.StatPreemptPreempting, "/HM/CPU%d/Preempt/Preempting", "EMT has been preempted while in HM context.");
716 HM_REG_COUNTER(&pVCpu->hm.s.StatPreemptSaveHostState, "/HM/CPU%d/Preempt/SaveHostState", "Preemption caused us to resave host state.");
717
718 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushPage, "/HM/CPU%d/Flush/Page", "Invalidating a guest page on all guest CPUs.");
719 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushPageManual, "/HM/CPU%d/Flush/Page/Virt", "Invalidating a guest page using guest-virtual address.");
720 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushPhysPageManual, "/HM/CPU%d/Flush/Page/Phys", "Invalidating a guest page using guest-physical address.");
721 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushTlb, "/HM/CPU%d/Flush/TLB", "Forcing a full guest-TLB flush (ring-0).");
722 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushTlbManual, "/HM/CPU%d/Flush/TLB/Manual", "Request a full guest-TLB flush.");
723 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.");
724 HM_REG_COUNTER(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch, "/HM/CPU%d/Flush/TLB/Skipped", "No TLB flushing required.");
725 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushEntire, "/HM/CPU%d/Flush/TLB/Entire", "Flush the entire TLB (host + guest).");
726 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushAsid, "/HM/CPU%d/Flush/TLB/ASID", "Flushed guest-TLB entries for the current VPID.");
727 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushNestedPaging, "/HM/CPU%d/Flush/TLB/NestedPaging", "Flushed guest-TLB entries for the current EPT.");
728 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushTlbInvlpgVirt, "/HM/CPU%d/Flush/TLB/InvlpgVirt", "Invalidated a guest-TLB entry for a guest-virtual address.");
729 HM_REG_COUNTER(&pVCpu->hm.s.StatFlushTlbInvlpgPhys, "/HM/CPU%d/Flush/TLB/InvlpgPhys", "Currently not possible, flushes entire guest-TLB.");
730 HM_REG_COUNTER(&pVCpu->hm.s.StatTlbShootdown, "/HM/CPU%d/Flush/Shootdown/Page", "Inter-VCPU request to flush queued guest page.");
731 HM_REG_COUNTER(&pVCpu->hm.s.StatTlbShootdownFlush, "/HM/CPU%d/Flush/Shootdown/TLB", "Inter-VCPU request to flush entire guest-TLB.");
732
733 HM_REG_COUNTER(&pVCpu->hm.s.StatTscOffset, "/HM/CPU%d/TSC/Offset", "TSC offsetting is in effect.");
734 HM_REG_COUNTER(&pVCpu->hm.s.StatTscIntercept, "/HM/CPU%d/TSC/Intercept", "Guest is in catchup mode, intercept TSC accesses.");
735 HM_REG_COUNTER(&pVCpu->hm.s.StatTscInterceptOverFlow, "/HM/CPU%d/TSC/InterceptOverflow", "TSC offset overflow, fallback to intercept TSC accesses.");
736
737 HM_REG_COUNTER(&pVCpu->hm.s.StatDRxArmed, "/HM/CPU%d/Debug/Armed", "Loaded guest-debug state while loading guest-state.");
738 HM_REG_COUNTER(&pVCpu->hm.s.StatDRxContextSwitch, "/HM/CPU%d/Debug/ContextSwitch", "Loaded guest-debug state on MOV DRx.");
739 HM_REG_COUNTER(&pVCpu->hm.s.StatDRxIoCheck, "/HM/CPU%d/Debug/IOCheck", "Checking for I/O breakpoint.");
740
741 HM_REG_COUNTER(&pVCpu->hm.s.StatLoadMinimal, "/HM/CPU%d/Load/Minimal", "VM-entry loading minimal guest-state.");
742 HM_REG_COUNTER(&pVCpu->hm.s.StatLoadFull, "/HM/CPU%d/Load/Full", "VM-entry loading the full guest-state.");
743
744 HM_REG_COUNTER(&pVCpu->hm.s.StatVmxCheckBadRmSelBase, "/HM/CPU%d/VMXCheck/RMSelBase", "Could not use VMX due to unsuitable real-mode selector base.");
745 HM_REG_COUNTER(&pVCpu->hm.s.StatVmxCheckBadRmSelLimit, "/HM/CPU%d/VMXCheck/RMSelLimit", "Could not use VMX due to unsuitable real-mode selector limit.");
746 HM_REG_COUNTER(&pVCpu->hm.s.StatVmxCheckRmOk, "/HM/CPU%d/VMXCheck/VMX_RM", "VMX execution in real (V86) mode OK.");
747 HM_REG_COUNTER(&pVCpu->hm.s.StatVmxCheckBadSel, "/HM/CPU%d/VMXCheck/Selector", "Could not use VMX due to unsuitable selector.");
748 HM_REG_COUNTER(&pVCpu->hm.s.StatVmxCheckBadRpl, "/HM/CPU%d/VMXCheck/RPL", "Could not use VMX due to unsuitable RPL.");
749 HM_REG_COUNTER(&pVCpu->hm.s.StatVmxCheckBadLdt, "/HM/CPU%d/VMXCheck/LDT", "Could not use VMX due to unsuitable LDT.");
750 HM_REG_COUNTER(&pVCpu->hm.s.StatVmxCheckBadTr, "/HM/CPU%d/VMXCheck/TR", "Could not use VMX due to unsuitable TR.");
751 HM_REG_COUNTER(&pVCpu->hm.s.StatVmxCheckPmOk, "/HM/CPU%d/VMXCheck/VMX_PM", "VMX execution in protected mode OK.");
752
753#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS) && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)
754 HM_REG_COUNTER(&pVCpu->hm.s.StatFpu64SwitchBack, "/HM/CPU%d/Switch64/Fpu", "Saving guest FPU/XMM state.");
755 HM_REG_COUNTER(&pVCpu->hm.s.StatDebug64SwitchBack, "/HM/CPU%d/Switch64/Debug", "Saving guest debug state.");
756#endif
757
758 for (unsigned j = 0; j < RT_ELEMENTS(pVCpu->hm.s.StatExitCRxWrite); j++)
759 {
760 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatExitCRxWrite[j], STAMTYPE_COUNTER, STAMVISIBILITY_USED,
761 STAMUNIT_OCCURENCES, "Profiling of CRx writes",
762 "/HM/CPU%d/Exit/Instr/CR/Write/%x", i, j);
763 AssertRC(rc);
764 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatExitCRxRead[j], STAMTYPE_COUNTER, STAMVISIBILITY_USED,
765 STAMUNIT_OCCURENCES, "Profiling of CRx reads",
766 "/HM/CPU%d/Exit/Instr/CR/Read/%x", i, j);
767 AssertRC(rc);
768 }
769
770#undef HM_REG_COUNTER
771
772 pVCpu->hm.s.paStatExitReason = NULL;
773
774 rc = MMHyperAlloc(pVM, MAX_EXITREASON_STAT*sizeof(*pVCpu->hm.s.paStatExitReason), 0, MM_TAG_HM,
775 (void **)&pVCpu->hm.s.paStatExitReason);
776 AssertRC(rc);
777 if (RT_SUCCESS(rc))
778 {
779 const char * const *papszDesc = ASMIsIntelCpu() ? &g_apszVTxExitReasons[0] : &g_apszAmdVExitReasons[0];
780 for (int j = 0; j < MAX_EXITREASON_STAT; j++)
781 {
782 if (papszDesc[j])
783 {
784 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.paStatExitReason[j], STAMTYPE_COUNTER, STAMVISIBILITY_USED,
785 STAMUNIT_OCCURENCES, papszDesc[j], "/HM/CPU%d/Exit/Reason/%02x", i, j);
786 AssertRC(rc);
787 }
788 }
789 rc = STAMR3RegisterF(pVM, &pVCpu->hm.s.StatExitReasonNpf, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
790 "Nested page fault", "/HM/CPU%d/Exit/Reason/#NPF", i);
791 AssertRC(rc);
792 }
793 pVCpu->hm.s.paStatExitReasonR0 = MMHyperR3ToR0(pVM, pVCpu->hm.s.paStatExitReason);
794# ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
795 Assert(pVCpu->hm.s.paStatExitReasonR0 != NIL_RTR0PTR || !HMIsEnabled(pVM));
796# else
797 Assert(pVCpu->hm.s.paStatExitReasonR0 != NIL_RTR0PTR);
798# endif
799
800 rc = MMHyperAlloc(pVM, sizeof(STAMCOUNTER) * 256, 8, MM_TAG_HM, (void **)&pVCpu->hm.s.paStatInjectedIrqs);
801 AssertRCReturn(rc, rc);
802 pVCpu->hm.s.paStatInjectedIrqsR0 = MMHyperR3ToR0(pVM, pVCpu->hm.s.paStatInjectedIrqs);
803# ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
804 Assert(pVCpu->hm.s.paStatInjectedIrqsR0 != NIL_RTR0PTR || !HMIsEnabled(pVM));
805# else
806 Assert(pVCpu->hm.s.paStatInjectedIrqsR0 != NIL_RTR0PTR);
807# endif
808 for (unsigned j = 0; j < 255; j++)
809 {
810 STAMR3RegisterF(pVM, &pVCpu->hm.s.paStatInjectedIrqs[j], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
811 "Injected event.",
812 (j < 0x20) ? "/HM/CPU%d/EventInject/Event/Trap/%02X" : "/HM/CPU%d/EventInject/Event/IRQ/%02X", i, j);
813 }
814
815#endif /* VBOX_WITH_STATISTICS */
816 }
817
818#ifdef VBOX_WITH_CRASHDUMP_MAGIC
819 /*
820 * Magic marker for searching in crash dumps.
821 */
822 for (VMCPUID i = 0; i < pVM->cCpus; i++)
823 {
824 PVMCPU pVCpu = &pVM->aCpus[i];
825
826 PVMCSCACHE pCache = &pVCpu->hm.s.vmx.VMCSCache;
827 strcpy((char *)pCache->aMagic, "VMCSCACHE Magic");
828 pCache->uMagic = UINT64_C(0xDEADBEEFDEADBEEF);
829 }
830#endif
831
832 return VINF_SUCCESS;
833}
834
835
836/**
837 * Called when a init phase has completed.
838 *
839 * @returns VBox status code.
840 * @param pVM The VM.
841 * @param enmWhat The phase that completed.
842 */
843VMMR3_INT_DECL(int) HMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat)
844{
845 switch (enmWhat)
846 {
847 case VMINITCOMPLETED_RING3:
848 return hmR3InitCPU(pVM);
849 case VMINITCOMPLETED_RING0:
850 return hmR3InitFinalizeR0(pVM);
851 default:
852 return VINF_SUCCESS;
853 }
854}
855
856
857/**
858 * Turns off normal raw mode features.
859 *
860 * @param pVM Pointer to the VM.
861 */
862static void hmR3DisableRawMode(PVM pVM)
863{
864 /* Reinit the paging mode to force the new shadow mode. */
865 for (VMCPUID i = 0; i < pVM->cCpus; i++)
866 {
867 PVMCPU pVCpu = &pVM->aCpus[i];
868
869 PGMR3ChangeMode(pVM, pVCpu, PGMMODE_REAL);
870 }
871}
872
873
874/**
875 * Initialize VT-x or AMD-V.
876 *
877 * @returns VBox status code.
878 * @param pVM Pointer to the VM.
879 */
880static int hmR3InitFinalizeR0(PVM pVM)
881{
882 int rc;
883
884 if (!HMIsEnabled(pVM))
885 return VINF_SUCCESS;
886
887 /*
888 * Hack to allow users to work around broken BIOSes that incorrectly set
889 * EFER.SVME, which makes us believe somebody else is already using AMD-V.
890 */
891 if ( !pVM->hm.s.vmx.fSupported
892 && !pVM->hm.s.svm.fSupported
893 && pVM->hm.s.lLastError == VERR_SVM_IN_USE /* implies functional AMD-V */
894 && RTEnvExist("VBOX_HWVIRTEX_IGNORE_SVM_IN_USE"))
895 {
896 LogRel(("HM: VBOX_HWVIRTEX_IGNORE_SVM_IN_USE active!\n"));
897 pVM->hm.s.svm.fSupported = true;
898 pVM->hm.s.svm.fIgnoreInUseError = true;
899 pVM->hm.s.lLastError = VINF_SUCCESS;
900 }
901
902 /*
903 * Report ring-0 init errors.
904 */
905 if ( !pVM->hm.s.vmx.fSupported
906 && !pVM->hm.s.svm.fSupported)
907 {
908 LogRel(("HM: Failed to initialize VT-x / AMD-V: %Rrc\n", pVM->hm.s.lLastError));
909 LogRel(("HM: VMX MSR_IA32_FEATURE_CONTROL=%RX64\n", pVM->hm.s.vmx.Msrs.u64FeatureCtrl));
910 switch (pVM->hm.s.lLastError)
911 {
912 case VERR_VMX_IN_VMX_ROOT_MODE:
913 return VM_SET_ERROR(pVM, VERR_VMX_IN_VMX_ROOT_MODE, "VT-x is being used by another hypervisor.");
914 case VERR_VMX_NO_VMX:
915 return VM_SET_ERROR(pVM, VERR_VMX_NO_VMX, "VT-x is not available.");
916 case VERR_VMX_MSR_VMXON_DISABLED:
917 return VM_SET_ERROR(pVM, VERR_VMX_NO_VMX, "VT-x is disabled in the BIOS.");
918 case VERR_VMX_MSR_SMX_VMXON_DISABLED:
919 return VM_SET_ERROR(pVM, VERR_VMX_NO_VMX, "VT-x is disabled in the BIOS for Safer-Mode/Trusted Extensions.");
920 case VERR_VMX_MSR_LOCKING_FAILED:
921 return VM_SET_ERROR(pVM, VERR_VMX_NO_VMX, "Failed to enable and lock VT-x features.");
922
923 case VERR_SVM_IN_USE:
924 return VM_SET_ERROR(pVM, VERR_SVM_IN_USE, "AMD-V is being used by another hypervisor.");
925 case VERR_SVM_NO_SVM:
926 return VM_SET_ERROR(pVM, VERR_SVM_NO_SVM, "AMD-V is not available.");
927 case VERR_SVM_DISABLED:
928 return VM_SET_ERROR(pVM, VERR_SVM_DISABLED, "AMD-V is disabled in the BIOS.");
929 }
930 return VMSetError(pVM, pVM->hm.s.lLastError, RT_SRC_POS, "HM ring-0 init failed: %Rrc", pVM->hm.s.lLastError);
931 }
932
933 /*
934 * Enable VT-x or AMD-V on all host CPUs.
935 */
936 rc = SUPR3CallVMMR0Ex(pVM->pVMR0, 0 /*idCpu*/, VMMR0_DO_HM_ENABLE, 0, NULL);
937 if (RT_FAILURE(rc))
938 {
939 LogRel(("HMR3InitFinalize: SUPR3CallVMMR0Ex VMMR0_DO_HM_ENABLE failed with %Rrc\n", rc));
940 return rc;
941 }
942
943 /*
944 * No TPR patching is required when the IO-APIC is not enabled for this VM.
945 * (Main should have taken care of this already)
946 */
947 pVM->hm.s.fHasIoApic = PDMHasIoApic(pVM);
948 if (!pVM->hm.s.fHasIoApic)
949 {
950 Assert(!pVM->hm.s.fTRPPatchingAllowed); /* paranoia */
951 pVM->hm.s.fTRPPatchingAllowed = false;
952 }
953
954 /*
955 * Do the vendor specific initalization .
956 * .
957 * Note! We disable release log buffering here since we're doing relatively .
958 * lot of logging and doesn't want to hit the disk with each LogRel .
959 * statement.
960 */
961 AssertLogRelReturn(!pVM->hm.s.fInitialized, VERR_HM_IPE_5);
962 bool fOldBuffered = RTLogRelSetBuffering(true /*fBuffered*/);
963 if (pVM->hm.s.vmx.fSupported)
964 rc = hmR3InitFinalizeR0Intel(pVM);
965 else
966 rc = hmR3InitFinalizeR0Amd(pVM);
967 LogRel(("HM: VT-x/AMD-V init method: %s\n", (pVM->hm.s.fGlobalInit) ? "GLOBAL" : "LOCAL"));
968 RTLogRelSetBuffering(fOldBuffered);
969 pVM->hm.s.fInitialized = true;
970
971 return rc;
972}
973
974
975/**
976 * Finish VT-x initialization (after ring-0 init).
977 *
978 * @returns VBox status code.
979 * @param pVM The cross context VM structure.
980 */
981static int hmR3InitFinalizeR0Intel(PVM pVM)
982{
983 int rc;
984
985 Log(("pVM->hm.s.vmx.fSupported = %d\n", pVM->hm.s.vmx.fSupported));
986 AssertLogRelReturn(pVM->hm.s.vmx.Msrs.u64FeatureCtrl != 0, VERR_HM_IPE_4);
987
988 uint64_t val;
989 uint64_t zap;
990 RTGCPHYS GCPhys = 0;
991
992 LogRel(("HM: Using VT-x implementation 2.0!\n"));
993 LogRel(("HM: Host CR4 = %#RX64\n", pVM->hm.s.vmx.u64HostCr4));
994 LogRel(("HM: MSR_IA32_FEATURE_CONTROL = %#RX64\n", pVM->hm.s.vmx.Msrs.u64FeatureCtrl));
995 LogRel(("HM: MSR_IA32_VMX_BASIC_INFO = %#RX64\n", pVM->hm.s.vmx.Msrs.u64BasicInfo));
996 LogRel(("HM: VMCS id = %#x\n", MSR_IA32_VMX_BASIC_INFO_VMCS_ID(pVM->hm.s.vmx.Msrs.u64BasicInfo)));
997 LogRel(("HM: VMCS size = %u\n", MSR_IA32_VMX_BASIC_INFO_VMCS_SIZE(pVM->hm.s.vmx.Msrs.u64BasicInfo)));
998 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"));
999 LogRel(("HM: VMCS memory type = %#x\n", MSR_IA32_VMX_BASIC_INFO_VMCS_MEM_TYPE(pVM->hm.s.vmx.Msrs.u64BasicInfo)));
1000 LogRel(("HM: Dual-monitor treatment support = %RTbool\n", !!MSR_IA32_VMX_BASIC_INFO_VMCS_DUAL_MON(pVM->hm.s.vmx.Msrs.u64BasicInfo)));
1001 LogRel(("HM: OUTS & INS instruction-info = %RTbool\n", !!MSR_IA32_VMX_BASIC_INFO_VMCS_INS_OUTS(pVM->hm.s.vmx.Msrs.u64BasicInfo)));
1002 LogRel(("HM: Max resume loops = %u\n", pVM->hm.s.cMaxResumeLoops));
1003
1004 LogRel(("HM: MSR_IA32_VMX_PINBASED_CTLS = %#RX64\n", pVM->hm.s.vmx.Msrs.VmxPinCtls.u));
1005 val = pVM->hm.s.vmx.Msrs.VmxPinCtls.n.allowed1;
1006 zap = pVM->hm.s.vmx.Msrs.VmxPinCtls.n.disallowed0;
1007 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PIN_EXEC_EXT_INT_EXIT);
1008 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PIN_EXEC_NMI_EXIT);
1009 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PIN_EXEC_VIRTUAL_NMI);
1010 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PIN_EXEC_PREEMPT_TIMER);
1011
1012 LogRel(("HM: MSR_IA32_VMX_PROCBASED_CTLS = %#RX64\n", pVM->hm.s.vmx.Msrs.VmxProcCtls.u));
1013 val = pVM->hm.s.vmx.Msrs.VmxProcCtls.n.allowed1;
1014 zap = pVM->hm.s.vmx.Msrs.VmxProcCtls.n.disallowed0;
1015 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_INT_WINDOW_EXIT);
1016 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_USE_TSC_OFFSETTING);
1017 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_HLT_EXIT);
1018 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_INVLPG_EXIT);
1019 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_MWAIT_EXIT);
1020 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_RDPMC_EXIT);
1021 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_RDTSC_EXIT);
1022 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_CR3_LOAD_EXIT);
1023 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_CR3_STORE_EXIT);
1024 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_CR8_LOAD_EXIT);
1025 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_CR8_STORE_EXIT);
1026 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_USE_TPR_SHADOW);
1027 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_NMI_WINDOW_EXIT);
1028 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_MOV_DR_EXIT);
1029 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_UNCOND_IO_EXIT);
1030 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_USE_IO_BITMAPS);
1031 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_MONITOR_TRAP_FLAG);
1032 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_USE_MSR_BITMAPS);
1033 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_MONITOR_EXIT);
1034 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_PAUSE_EXIT);
1035 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL);
1036 if (pVM->hm.s.vmx.Msrs.VmxProcCtls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL)
1037 {
1038 LogRel(("HM: MSR_IA32_VMX_PROCBASED_CTLS2 = %#RX64\n", pVM->hm.s.vmx.Msrs.VmxProcCtls2.u));
1039 val = pVM->hm.s.vmx.Msrs.VmxProcCtls2.n.allowed1;
1040 zap = pVM->hm.s.vmx.Msrs.VmxProcCtls2.n.disallowed0;
1041 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC2_VIRT_APIC);
1042 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC2_EPT);
1043 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC2_DESCRIPTOR_TABLE_EXIT);
1044 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC2_RDTSCP);
1045 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC2_VIRT_X2APIC);
1046 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC2_VPID);
1047 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC2_WBINVD_EXIT);
1048 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC2_UNRESTRICTED_GUEST);
1049 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC2_PAUSE_LOOP_EXIT);
1050 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC2_RDRAND_EXIT);
1051 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC2_INVPCID);
1052 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_PROC_EXEC2_VMFUNC);
1053 }
1054
1055 LogRel(("HM: MSR_IA32_VMX_ENTRY_CTLS = %#RX64\n", pVM->hm.s.vmx.Msrs.VmxEntry.u));
1056 val = pVM->hm.s.vmx.Msrs.VmxEntry.n.allowed1;
1057 zap = pVM->hm.s.vmx.Msrs.VmxEntry.n.disallowed0;
1058 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_ENTRY_LOAD_DEBUG);
1059 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_ENTRY_IA32E_MODE_GUEST);
1060 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_ENTRY_ENTRY_SMM);
1061 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_ENTRY_DEACTIVATE_DUALMON);
1062 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_ENTRY_LOAD_GUEST_PERF_MSR);
1063 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_ENTRY_LOAD_GUEST_PAT_MSR);
1064 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_ENTRY_LOAD_GUEST_EFER_MSR);
1065
1066 LogRel(("HM: MSR_IA32_VMX_EXIT_CTLS = %#RX64\n", pVM->hm.s.vmx.Msrs.VmxExit.u));
1067 val = pVM->hm.s.vmx.Msrs.VmxExit.n.allowed1;
1068 zap = pVM->hm.s.vmx.Msrs.VmxExit.n.disallowed0;
1069 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_EXIT_SAVE_DEBUG);
1070 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_EXIT_HOST_ADDR_SPACE_SIZE);
1071 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_EXIT_LOAD_PERF_MSR);
1072 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_EXIT_ACK_EXT_INT);
1073 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_EXIT_SAVE_GUEST_PAT_MSR);
1074 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_EXIT_LOAD_HOST_PAT_MSR);
1075 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_EXIT_SAVE_GUEST_EFER_MSR);
1076 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_EXIT_LOAD_HOST_EFER_MSR);
1077 HMVMX_REPORT_FEATURE(val, zap, VMX_VMCS_CTRL_EXIT_SAVE_VMX_PREEMPT_TIMER);
1078
1079 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps)
1080 {
1081 val = pVM->hm.s.vmx.Msrs.u64EptVpidCaps;
1082 LogRel(("HM: MSR_IA32_VMX_EPT_VPID_CAP = %#RX64\n", val));
1083 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_RWX_X_ONLY);
1084 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_RWX_W_ONLY);
1085 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_RWX_WX_ONLY);
1086 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_GAW_21_BITS);
1087 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_GAW_30_BITS);
1088 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_GAW_39_BITS);
1089 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_GAW_48_BITS);
1090 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_GAW_57_BITS);
1091 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_EMT_UC);
1092 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_EMT_WC);
1093 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_EMT_WT);
1094 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_EMT_WP);
1095 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB);
1096 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_SP_21_BITS);
1097 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_SP_30_BITS);
1098 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_SP_39_BITS);
1099 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_SP_48_BITS);
1100 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_INVEPT);
1101 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT);
1102 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS);
1103 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_INVVPID);
1104 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
1105 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT);
1106 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS);
1107 HMVMX_REPORT_CAPABILITY(val, MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS);
1108 }
1109
1110 val = pVM->hm.s.vmx.Msrs.u64Misc;
1111 LogRel(("HM: MSR_IA32_VMX_MISC = %#RX64\n", val));
1112 if (MSR_IA32_VMX_MISC_PREEMPT_TSC_BIT(val) == pVM->hm.s.vmx.cPreemptTimerShift)
1113 LogRel(("HM: MSR_IA32_VMX_MISC_PREEMPT_TSC_BIT = %#x\n", MSR_IA32_VMX_MISC_PREEMPT_TSC_BIT(val)));
1114 else
1115 {
1116 LogRel(("HM: MSR_IA32_VMX_MISC_PREEMPT_TSC_BIT = %#x - erratum detected, using %#x instead\n",
1117 MSR_IA32_VMX_MISC_PREEMPT_TSC_BIT(val), pVM->hm.s.vmx.cPreemptTimerShift));
1118 }
1119
1120 LogRel(("HM: MSR_IA32_VMX_MISC_STORE_EFERLMA_VMEXIT = %RTbool\n", !!MSR_IA32_VMX_MISC_STORE_EFERLMA_VMEXIT(val)));
1121 LogRel(("HM: MSR_IA32_VMX_MISC_ACTIVITY_STATES = %#x\n", MSR_IA32_VMX_MISC_ACTIVITY_STATES(val)));
1122 LogRel(("HM: MSR_IA32_VMX_MISC_CR3_TARGET = %#x\n", MSR_IA32_VMX_MISC_CR3_TARGET(val)));
1123 LogRel(("HM: MSR_IA32_VMX_MISC_MAX_MSR = %u\n", MSR_IA32_VMX_MISC_MAX_MSR(val)));
1124 LogRel(("HM: MSR_IA32_VMX_MISC_RDMSR_SMBASE_MSR_SMM = %RTbool\n", !!MSR_IA32_VMX_MISC_RDMSR_SMBASE_MSR_SMM(val)));
1125 LogRel(("HM: MSR_IA32_VMX_MISC_SMM_MONITOR_CTL_B2 = %RTbool\n", !!MSR_IA32_VMX_MISC_SMM_MONITOR_CTL_B2(val)));
1126 LogRel(("HM: MSR_IA32_VMX_MISC_VMWRITE_VMEXIT_INFO = %RTbool\n", !!MSR_IA32_VMX_MISC_VMWRITE_VMEXIT_INFO(val)));
1127 LogRel(("HM: MSR_IA32_VMX_MISC_MSEG_ID = %#x\n", MSR_IA32_VMX_MISC_MSEG_ID(val)));
1128
1129 /* Paranoia */
1130 AssertRelease(MSR_IA32_VMX_MISC_MAX_MSR(pVM->hm.s.vmx.Msrs.u64Misc) >= 512);
1131
1132 LogRel(("HM: MSR_IA32_VMX_CR0_FIXED0 = %#RX64\n", pVM->hm.s.vmx.Msrs.u64Cr0Fixed0));
1133 LogRel(("HM: MSR_IA32_VMX_CR0_FIXED1 = %#RX64\n", pVM->hm.s.vmx.Msrs.u64Cr0Fixed1));
1134 LogRel(("HM: MSR_IA32_VMX_CR4_FIXED0 = %#RX64\n", pVM->hm.s.vmx.Msrs.u64Cr4Fixed0));
1135 LogRel(("HM: MSR_IA32_VMX_CR4_FIXED1 = %#RX64\n", pVM->hm.s.vmx.Msrs.u64Cr4Fixed1));
1136
1137 val = pVM->hm.s.vmx.Msrs.u64VmcsEnum;
1138 LogRel(("HM: MSR_IA32_VMX_VMCS_ENUM = %#RX64\n", val));
1139 LogRel(("HM: MSR_IA32_VMX_VMCS_ENUM_HIGHEST_INDEX = %#x\n", MSR_IA32_VMX_VMCS_ENUM_HIGHEST_INDEX(val)));
1140
1141 val = pVM->hm.s.vmx.Msrs.u64Vmfunc;
1142 if (val)
1143 {
1144 LogRel(("HM: MSR_A32_VMX_VMFUNC = %#RX64\n", val));
1145 HMVMX_REPORT_ALLOWED_FEATURE(val, VMX_VMCS_CTRL_VMFUNC_EPTP_SWITCHING);
1146 }
1147
1148 LogRel(("HM: APIC-access page physaddr = %#RHp\n", pVM->hm.s.vmx.HCPhysApicAccess));
1149
1150 for (VMCPUID i = 0; i < pVM->cCpus; i++)
1151 {
1152 LogRel(("HM: VCPU%3d: MSR bitmap physaddr = %#RHp\n", i, pVM->aCpus[i].hm.s.vmx.HCPhysMsrBitmap));
1153 LogRel(("HM: VCPU%3d: VMCS physaddr = %#RHp\n", i, pVM->aCpus[i].hm.s.vmx.HCPhysVmcs));
1154 }
1155
1156 if (pVM->hm.s.vmx.Msrs.VmxProcCtls2.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC2_EPT)
1157 pVM->hm.s.fNestedPaging = pVM->hm.s.fAllowNestedPaging;
1158
1159 if (pVM->hm.s.vmx.Msrs.VmxProcCtls2.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC2_VPID)
1160 pVM->hm.s.vmx.fVpid = pVM->hm.s.vmx.fAllowVpid;
1161
1162 /*
1163 * Disallow RDTSCP in the guest if there is no secondary process-based VM execution controls as otherwise
1164 * RDTSCP would cause a #UD. There might be no CPUs out there where this happens, as RDTSCP was introduced
1165 * in Nehalems and secondary VM exec. controls should be supported in all of them, but nonetheless it's Intel...
1166 */
1167 if ( !(pVM->hm.s.vmx.Msrs.VmxProcCtls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL)
1168 && CPUMGetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_RDTSCP))
1169 {
1170 CPUMClearGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_RDTSCP);
1171 LogRel(("HM: RDTSCP disabled.\n"));
1172 }
1173
1174 /* Unrestricted guest execution also requires EPT. */
1175 if ( pVM->hm.s.vmx.fAllowUnrestricted
1176 && pVM->hm.s.fNestedPaging
1177 && (pVM->hm.s.vmx.Msrs.VmxProcCtls2.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC2_UNRESTRICTED_GUEST))
1178 {
1179 pVM->hm.s.vmx.fUnrestrictedGuest = true;
1180 }
1181
1182 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
1183 {
1184 /* Allocate three pages for the TSS we need for real mode emulation. (2 pages for the IO bitmap) */
1185 rc = PDMR3VmmDevHeapAlloc(pVM, HM_VTX_TOTAL_DEVHEAP_MEM, (RTR3PTR *)&pVM->hm.s.vmx.pRealModeTSS);
1186 if (RT_SUCCESS(rc))
1187 {
1188 /* The IO bitmap starts right after the virtual interrupt redirection bitmap.
1189 Refer Intel spec. 20.3.3 "Software Interrupt Handling in Virtual-8086 mode"
1190 esp. Figure 20-5.*/
1191 ASMMemZero32(pVM->hm.s.vmx.pRealModeTSS, sizeof(*pVM->hm.s.vmx.pRealModeTSS));
1192 pVM->hm.s.vmx.pRealModeTSS->offIoBitmap = sizeof(*pVM->hm.s.vmx.pRealModeTSS);
1193
1194 /* Bit set to 0 means software interrupts are redirected to the
1195 8086 program interrupt handler rather than switching to
1196 protected-mode handler. */
1197 memset(pVM->hm.s.vmx.pRealModeTSS->IntRedirBitmap, 0, sizeof(pVM->hm.s.vmx.pRealModeTSS->IntRedirBitmap));
1198
1199 /* Allow all port IO, so that port IO instructions do not cause
1200 exceptions and would instead cause a VM-exit (based on VT-x's
1201 IO bitmap which we currently configure to always cause an exit). */
1202 memset(pVM->hm.s.vmx.pRealModeTSS + 1, 0, PAGE_SIZE * 2);
1203 *((unsigned char *)pVM->hm.s.vmx.pRealModeTSS + HM_VTX_TSS_SIZE - 2) = 0xff;
1204
1205 /*
1206 * Construct a 1024 element page directory with 4 MB pages for
1207 * the identity mapped page table used in real and protected mode
1208 * without paging with EPT.
1209 */
1210 pVM->hm.s.vmx.pNonPagingModeEPTPageTable = (PX86PD)((char *)pVM->hm.s.vmx.pRealModeTSS + PAGE_SIZE * 3);
1211 for (uint32_t i = 0; i < X86_PG_ENTRIES; i++)
1212 {
1213 pVM->hm.s.vmx.pNonPagingModeEPTPageTable->a[i].u = _4M * i;
1214 pVM->hm.s.vmx.pNonPagingModeEPTPageTable->a[i].u |= X86_PDE4M_P | X86_PDE4M_RW | X86_PDE4M_US
1215 | X86_PDE4M_A | X86_PDE4M_D | X86_PDE4M_PS
1216 | X86_PDE4M_G;
1217 }
1218
1219 /* We convert it here every time as pci regions could be reconfigured. */
1220 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
1221 AssertRCReturn(rc, rc);
1222 LogRel(("HM: Real Mode TSS guest physaddr = %#RGp\n", GCPhys));
1223
1224 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
1225 AssertRCReturn(rc, rc);
1226 LogRel(("HM: Non-Paging Mode EPT CR3 = %#RGp\n", GCPhys));
1227 }
1228 else
1229 {
1230 /** @todo This cannot possibly work, there are other places which assumes
1231 * this allocation cannot fail (see HMR3CanExecuteGuest()). Make this
1232 * a failure case. */
1233 LogRel(("HM: No real mode VT-x support (PDMR3VMMDevHeapAlloc returned %Rrc)\n", rc));
1234 pVM->hm.s.vmx.pRealModeTSS = NULL;
1235 pVM->hm.s.vmx.pNonPagingModeEPTPageTable = NULL;
1236 }
1237 }
1238
1239 /*
1240 * Call ring-0 to set up the VM.
1241 */
1242 rc = SUPR3CallVMMR0Ex(pVM->pVMR0, 0 /*idCpu*/, VMMR0_DO_HM_SETUP_VM, 0, NULL);
1243 if (rc != VINF_SUCCESS)
1244 {
1245 AssertMsgFailed(("%Rrc\n", rc));
1246 LogRel(("HM: VMX setup failed with rc=%Rrc!\n", rc));
1247 for (VMCPUID i = 0; i < pVM->cCpus; i++)
1248 {
1249 PVMCPU pVCpu = &pVM->aCpus[i];
1250 LogRel(("HM: CPU[%u] Last instruction error %#x\n", i, pVCpu->hm.s.vmx.LastError.u32InstrError));
1251 LogRel(("HM: CPU[%u] HM error %#x (%u)\n", i, pVCpu->hm.s.u32HMError, pVCpu->hm.s.u32HMError));
1252 }
1253 return VMSetError(pVM, rc, RT_SRC_POS, "VT-x setup failed: %Rrc", rc);
1254 }
1255
1256 LogRel(("HM: VMX enabled!\n"));
1257 pVM->hm.s.vmx.fEnabled = true;
1258
1259 hmR3DisableRawMode(pVM); /** @todo make this go away! */
1260
1261 /*
1262 * Change the CPU features.
1263 */
1264 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_SEP);
1265 if (pVM->hm.s.fAllow64BitGuests)
1266 {
1267 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_PAE);
1268 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_LONG_MODE);
1269 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_SYSCALL); /* 64 bits only on Intel CPUs */
1270 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_LAHF);
1271 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_NX);
1272#if 0 /** @todo r=bird: This ain't making any sense whatsoever. */
1273#if RT_ARCH_X86
1274 if ( !CPUMGetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_PAE)
1275 || !(pVM->hm.s.vmx.u64HostEfer & MSR_K6_EFER_NXE))
1276 LogRel(("NX is only supported for 64-bit guests!\n"));
1277#endif
1278#endif
1279 }
1280 /* Turn on NXE if PAE has been enabled *and* the host has turned on NXE
1281 (we reuse the host EFER in the switcher). */
1282 /** @todo this needs to be fixed properly!! */
1283 else if ( CPUMGetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_PAE)
1284 && (pVM->hm.s.vmx.u64HostEfer & MSR_K6_EFER_NXE))
1285 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_NX);
1286 else
1287 LogRel(("HM: NX not supported by the host.\n"));
1288
1289 /*
1290 * Log configuration details.
1291 */
1292 LogRel((pVM->hm.s.fAllow64BitGuests
1293 ? "HM: Guest support: 32-bit and 64-bit.\n"
1294 : "HM: Guest support: 32-bit only.\n"));
1295 if (pVM->hm.s.fNestedPaging)
1296 {
1297 LogRel(("HM: Nested paging enabled!\n"));
1298 if (pVM->hm.s.vmx.enmFlushEpt == VMX_FLUSH_EPT_SINGLE_CONTEXT)
1299 LogRel(("HM: EPT flush type = VMX_FLUSH_EPT_SINGLE_CONTEXT\n"));
1300 else if (pVM->hm.s.vmx.enmFlushEpt == VMX_FLUSH_EPT_ALL_CONTEXTS)
1301 LogRel(("HM: EPT flush type = VMX_FLUSH_EPT_ALL_CONTEXTS\n"));
1302 else if (pVM->hm.s.vmx.enmFlushEpt == VMX_FLUSH_EPT_NOT_SUPPORTED)
1303 LogRel(("HM: EPT flush type = VMX_FLUSH_EPT_NOT_SUPPORTED\n"));
1304 else
1305 LogRel(("HM: EPT flush type = %d\n", pVM->hm.s.vmx.enmFlushEpt));
1306
1307 if (pVM->hm.s.vmx.fUnrestrictedGuest)
1308 LogRel(("HM: Unrestricted guest execution enabled!\n"));
1309
1310#if HC_ARCH_BITS == 64
1311 if (pVM->hm.s.fLargePages)
1312 {
1313 /* Use large (2 MB) pages for our EPT PDEs where possible. */
1314 PGMSetLargePageUsage(pVM, true);
1315 LogRel(("HM: Large page support enabled!\n"));
1316 }
1317#endif
1318 }
1319 else
1320 Assert(!pVM->hm.s.vmx.fUnrestrictedGuest);
1321
1322 if (pVM->hm.s.vmx.fVpid)
1323 {
1324 LogRel(("HM: VPID enabled!\n"));
1325 if (pVM->hm.s.vmx.enmFlushVpid == VMX_FLUSH_VPID_INDIV_ADDR)
1326 LogRel(("HM: VPID flush type = VMX_FLUSH_VPID_INDIV_ADDR\n"));
1327 else if (pVM->hm.s.vmx.enmFlushVpid == VMX_FLUSH_VPID_SINGLE_CONTEXT)
1328 LogRel(("HM: VPID flush type = VMX_FLUSH_VPID_SINGLE_CONTEXT\n"));
1329 else if (pVM->hm.s.vmx.enmFlushVpid == VMX_FLUSH_VPID_ALL_CONTEXTS)
1330 LogRel(("HM: VPID flush type = VMX_FLUSH_VPID_ALL_CONTEXTS\n"));
1331 else if (pVM->hm.s.vmx.enmFlushVpid == VMX_FLUSH_VPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
1332 LogRel(("HM: VPID flush type = VMX_FLUSH_VPID_SINGLE_CONTEXT_RETAIN_GLOBALS\n"));
1333 else
1334 LogRel(("HM: VPID flush type = %d\n", pVM->hm.s.vmx.enmFlushVpid));
1335 }
1336 else if (pVM->hm.s.vmx.enmFlushVpid == VMX_FLUSH_VPID_NOT_SUPPORTED)
1337 LogRel(("HM: Ignoring VPID capabilities of CPU.\n"));
1338
1339 /*
1340 * Check for preemption timer config override and log the state of it.
1341 */
1342 if (pVM->hm.s.vmx.fUsePreemptTimer)
1343 {
1344 PCFGMNODE pCfgHm = CFGMR3GetChild(CFGMR3GetRoot(pVM), "HM");
1345 rc = CFGMR3QueryBoolDef(pCfgHm, "UsePreemptTimer", &pVM->hm.s.vmx.fUsePreemptTimer, true);
1346 AssertLogRelRCReturn(rc, rc);
1347 }
1348 if (pVM->hm.s.vmx.fUsePreemptTimer)
1349 LogRel(("HM: VMX-preemption timer enabled (cPreemptTimerShift=%u).\n", pVM->hm.s.vmx.cPreemptTimerShift));
1350 else
1351 LogRel(("HM: VMX-preemption timer disabled.\n"));
1352
1353 return VINF_SUCCESS;
1354}
1355
1356
1357/**
1358 * Finish AMD-V initialization (after ring-0 init).
1359 *
1360 * @returns VBox status code.
1361 * @param pVM The cross context VM structure.
1362 */
1363static int hmR3InitFinalizeR0Amd(PVM pVM)
1364{
1365 Log(("pVM->hm.s.svm.fSupported = %d\n", pVM->hm.s.svm.fSupported));
1366
1367 LogRel(("HM: Using AMD-V implementation 2.0!\n"));
1368
1369 uint32_t u32Family;
1370 uint32_t u32Model;
1371 uint32_t u32Stepping;
1372 if (HMAmdIsSubjectToErratum170(&u32Family, &u32Model, &u32Stepping))
1373 LogRel(("HM: AMD Cpu with erratum 170 family %#x model %#x stepping %#x\n", u32Family, u32Model, u32Stepping));
1374 LogRel(("HM: CPUID 0x80000001.u32AMDFeatureECX = %#RX32\n", pVM->hm.s.cpuid.u32AMDFeatureECX));
1375 LogRel(("HM: CPUID 0x80000001.u32AMDFeatureEDX = %#RX32\n", pVM->hm.s.cpuid.u32AMDFeatureEDX));
1376 LogRel(("HM: AMD HWCR MSR = %#RX64\n", pVM->hm.s.svm.u64MsrHwcr));
1377 LogRel(("HM: AMD-V revision = %#x\n", pVM->hm.s.svm.u32Rev));
1378 LogRel(("HM: AMD-V max ASID = %RU32\n", pVM->hm.s.uMaxAsid));
1379 LogRel(("HM: AMD-V features = %#x\n", pVM->hm.s.svm.u32Features));
1380
1381 /*
1382 * Enumerate AMD-V features.
1383 */
1384 static const struct { uint32_t fFlag; const char *pszName; } s_aSvmFeatures[] =
1385 {
1386#define HMSVM_REPORT_FEATURE(a_Define) { a_Define, #a_Define }
1387 HMSVM_REPORT_FEATURE(AMD_CPUID_SVM_FEATURE_EDX_NESTED_PAGING),
1388 HMSVM_REPORT_FEATURE(AMD_CPUID_SVM_FEATURE_EDX_LBR_VIRT),
1389 HMSVM_REPORT_FEATURE(AMD_CPUID_SVM_FEATURE_EDX_SVM_LOCK),
1390 HMSVM_REPORT_FEATURE(AMD_CPUID_SVM_FEATURE_EDX_NRIP_SAVE),
1391 HMSVM_REPORT_FEATURE(AMD_CPUID_SVM_FEATURE_EDX_TSC_RATE_MSR),
1392 HMSVM_REPORT_FEATURE(AMD_CPUID_SVM_FEATURE_EDX_VMCB_CLEAN),
1393 HMSVM_REPORT_FEATURE(AMD_CPUID_SVM_FEATURE_EDX_FLUSH_BY_ASID),
1394 HMSVM_REPORT_FEATURE(AMD_CPUID_SVM_FEATURE_EDX_DECODE_ASSIST),
1395 HMSVM_REPORT_FEATURE(AMD_CPUID_SVM_FEATURE_EDX_PAUSE_FILTER),
1396 HMSVM_REPORT_FEATURE(AMD_CPUID_SVM_FEATURE_EDX_PAUSE_FILTER_THRESHOLD),
1397 HMSVM_REPORT_FEATURE(AMD_CPUID_SVM_FEATURE_EDX_AVIC),
1398#undef HMSVM_REPORT_FEATURE
1399 };
1400
1401 uint32_t fSvmFeatures = pVM->hm.s.svm.u32Features;
1402 for (unsigned i = 0; i < RT_ELEMENTS(s_aSvmFeatures); i++)
1403 if (fSvmFeatures & s_aSvmFeatures[i].fFlag)
1404 {
1405 LogRel(("HM: %s\n", s_aSvmFeatures[i].pszName));
1406 fSvmFeatures &= ~s_aSvmFeatures[i].fFlag;
1407 }
1408 if (fSvmFeatures)
1409 for (unsigned iBit = 0; iBit < 32; iBit++)
1410 if (RT_BIT_32(iBit) & fSvmFeatures)
1411 LogRel(("HM: Reserved bit %u\n", iBit));
1412
1413 /*
1414 * Adjust feature(s).
1415 */
1416 if (pVM->hm.s.svm.u32Features & AMD_CPUID_SVM_FEATURE_EDX_NESTED_PAGING)
1417 pVM->hm.s.fNestedPaging = pVM->hm.s.fAllowNestedPaging;
1418
1419 /*
1420 * Call ring-0 to set up the VM.
1421 */
1422 int rc = SUPR3CallVMMR0Ex(pVM->pVMR0, 0 /*idCpu*/, VMMR0_DO_HM_SETUP_VM, 0, NULL);
1423 if (rc != VINF_SUCCESS)
1424 {
1425 AssertMsgFailed(("%Rrc\n", rc));
1426 LogRel(("HM: AMD-V setup failed with rc=%Rrc!\n", rc));
1427 return VMSetError(pVM, rc, RT_SRC_POS, "AMD-V setup failed: %Rrc", rc);
1428 }
1429
1430 LogRel(("HM: AMD-V enabled!\n"));
1431 pVM->hm.s.svm.fEnabled = true;
1432
1433 if (pVM->hm.s.fNestedPaging)
1434 {
1435 LogRel(("HM: Nested paging enabled!\n"));
1436
1437 /*
1438 * Enable large pages (2 MB) if applicable.
1439 */
1440#if HC_ARCH_BITS == 64
1441 if (pVM->hm.s.fLargePages)
1442 {
1443 PGMSetLargePageUsage(pVM, true);
1444 LogRel(("HM: Large page support enabled!\n"));
1445 }
1446#endif
1447 }
1448
1449 hmR3DisableRawMode(pVM);
1450
1451 /*
1452 * Change the CPU features.
1453 */
1454 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_SEP);
1455 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_SYSCALL);
1456 if (pVM->hm.s.fAllow64BitGuests)
1457 {
1458 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_PAE);
1459 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_LONG_MODE);
1460 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_NX);
1461 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_LAHF);
1462 }
1463 /* Turn on NXE if PAE has been enabled. */
1464 else if (CPUMGetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_PAE))
1465 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_NX);
1466
1467 LogRel(("HM: TPR Patching %s.\n", (pVM->hm.s.fTRPPatchingAllowed) ? "enabled" : "disabled"));
1468
1469 LogRel((pVM->hm.s.fAllow64BitGuests
1470 ? "HM: Guest support: 32-bit and 64-bit.\n"
1471 : "HM: Guest support: 32-bit only.\n"));
1472
1473 return VINF_SUCCESS;
1474}
1475
1476
1477/**
1478 * Applies relocations to data and code managed by this
1479 * component. This function will be called at init and
1480 * whenever the VMM need to relocate it self inside the GC.
1481 *
1482 * @param pVM The VM.
1483 */
1484VMMR3_INT_DECL(void) HMR3Relocate(PVM pVM)
1485{
1486 Log(("HMR3Relocate to %RGv\n", MMHyperGetArea(pVM, 0)));
1487
1488 /* Fetch the current paging mode during the relocate callback during state loading. */
1489 if (VMR3GetState(pVM) == VMSTATE_LOADING)
1490 {
1491 for (VMCPUID i = 0; i < pVM->cCpus; i++)
1492 {
1493 PVMCPU pVCpu = &pVM->aCpus[i];
1494 pVCpu->hm.s.enmShadowMode = PGMGetShadowMode(pVCpu);
1495 }
1496 }
1497#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS) && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)
1498 if (HMIsEnabled(pVM))
1499 {
1500 switch (PGMGetHostMode(pVM))
1501 {
1502 case PGMMODE_32_BIT:
1503 pVM->hm.s.pfnHost32ToGuest64R0 = VMMR3GetHostToGuestSwitcher(pVM, VMMSWITCHER_32_TO_AMD64);
1504 break;
1505
1506 case PGMMODE_PAE:
1507 case PGMMODE_PAE_NX:
1508 pVM->hm.s.pfnHost32ToGuest64R0 = VMMR3GetHostToGuestSwitcher(pVM, VMMSWITCHER_PAE_TO_AMD64);
1509 break;
1510
1511 default:
1512 AssertFailed();
1513 break;
1514 }
1515 }
1516#endif
1517 return;
1518}
1519
1520
1521/**
1522 * Notification callback which is called whenever there is a chance that a CR3
1523 * value might have changed.
1524 *
1525 * This is called by PGM.
1526 *
1527 * @param pVM Pointer to the VM.
1528 * @param pVCpu Pointer to the VMCPU.
1529 * @param enmShadowMode New shadow paging mode.
1530 * @param enmGuestMode New guest paging mode.
1531 */
1532VMMR3_INT_DECL(void) HMR3PagingModeChanged(PVM pVM, PVMCPU pVCpu, PGMMODE enmShadowMode, PGMMODE enmGuestMode)
1533{
1534 /* Ignore page mode changes during state loading. */
1535 if (VMR3GetState(pVCpu->pVMR3) == VMSTATE_LOADING)
1536 return;
1537
1538 pVCpu->hm.s.enmShadowMode = enmShadowMode;
1539
1540 /*
1541 * If the guest left protected mode VMX execution, we'll have to be
1542 * extra careful if/when the guest switches back to protected mode.
1543 */
1544 if (enmGuestMode == PGMMODE_REAL)
1545 {
1546 Log(("HMR3PagingModeChanged indicates real mode execution\n"));
1547 pVCpu->hm.s.vmx.fWasInRealMode = true;
1548 }
1549
1550 /** @todo r=ramshankar: Disabling for now. If nothing breaks remove it
1551 * eventually. (Test platforms that use the cache ofc). */
1552#if 0
1553#ifdef VMX_USE_CACHED_VMCS_ACCESSES
1554 /* Reset the contents of the read cache. */
1555 PVMCSCACHE pCache = &pVCpu->hm.s.vmx.VMCSCache;
1556 for (unsigned j = 0; j < pCache->Read.cValidEntries; j++)
1557 pCache->Read.aFieldVal[j] = 0;
1558#endif
1559#endif
1560}
1561
1562
1563/**
1564 * Terminates the HM.
1565 *
1566 * Termination means cleaning up and freeing all resources,
1567 * the VM itself is, at this point, powered off or suspended.
1568 *
1569 * @returns VBox status code.
1570 * @param pVM Pointer to the VM.
1571 */
1572VMMR3_INT_DECL(int) HMR3Term(PVM pVM)
1573{
1574 if (pVM->hm.s.vmx.pRealModeTSS)
1575 {
1576 PDMR3VmmDevHeapFree(pVM, pVM->hm.s.vmx.pRealModeTSS);
1577 pVM->hm.s.vmx.pRealModeTSS = 0;
1578 }
1579 hmR3TermCPU(pVM);
1580 return 0;
1581}
1582
1583
1584/**
1585 * Terminates the per-VCPU HM.
1586 *
1587 * @returns VBox status code.
1588 * @param pVM Pointer to the VM.
1589 */
1590static int hmR3TermCPU(PVM pVM)
1591{
1592 for (VMCPUID i = 0; i < pVM->cCpus; i++)
1593 {
1594 PVMCPU pVCpu = &pVM->aCpus[i]; NOREF(pVCpu);
1595
1596#ifdef VBOX_WITH_STATISTICS
1597 if (pVCpu->hm.s.paStatExitReason)
1598 {
1599 MMHyperFree(pVM, pVCpu->hm.s.paStatExitReason);
1600 pVCpu->hm.s.paStatExitReason = NULL;
1601 pVCpu->hm.s.paStatExitReasonR0 = NIL_RTR0PTR;
1602 }
1603 if (pVCpu->hm.s.paStatInjectedIrqs)
1604 {
1605 MMHyperFree(pVM, pVCpu->hm.s.paStatInjectedIrqs);
1606 pVCpu->hm.s.paStatInjectedIrqs = NULL;
1607 pVCpu->hm.s.paStatInjectedIrqsR0 = NIL_RTR0PTR;
1608 }
1609#endif
1610
1611#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1612 memset(pVCpu->hm.s.vmx.VMCSCache.aMagic, 0, sizeof(pVCpu->hm.s.vmx.VMCSCache.aMagic));
1613 pVCpu->hm.s.vmx.VMCSCache.uMagic = 0;
1614 pVCpu->hm.s.vmx.VMCSCache.uPos = 0xffffffff;
1615#endif
1616 }
1617 return 0;
1618}
1619
1620
1621/**
1622 * Resets a virtual CPU.
1623 *
1624 * Used by HMR3Reset and CPU hot plugging.
1625 *
1626 * @param pVCpu The CPU to reset.
1627 */
1628VMMR3_INT_DECL(void) HMR3ResetCpu(PVMCPU pVCpu)
1629{
1630 /* On first entry we'll sync everything. */
1631 pVCpu->hm.s.fContextUseFlags = (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_ALL_GUEST);
1632
1633 pVCpu->hm.s.vmx.u32CR0Mask = 0;
1634 pVCpu->hm.s.vmx.u32CR4Mask = 0;
1635 pVCpu->hm.s.fActive = false;
1636 pVCpu->hm.s.Event.fPending = false;
1637 pVCpu->hm.s.vmx.fWasInRealMode = true;
1638
1639 /* Reset the contents of the read cache. */
1640 PVMCSCACHE pCache = &pVCpu->hm.s.vmx.VMCSCache;
1641 for (unsigned j = 0; j < pCache->Read.cValidEntries; j++)
1642 pCache->Read.aFieldVal[j] = 0;
1643
1644#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1645 /* Magic marker for searching in crash dumps. */
1646 strcpy((char *)pCache->aMagic, "VMCSCACHE Magic");
1647 pCache->uMagic = UINT64_C(0xDEADBEEFDEADBEEF);
1648#endif
1649}
1650
1651
1652/**
1653 * The VM is being reset.
1654 *
1655 * For the HM component this means that any GDT/LDT/TSS monitors
1656 * needs to be removed.
1657 *
1658 * @param pVM Pointer to the VM.
1659 */
1660VMMR3_INT_DECL(void) HMR3Reset(PVM pVM)
1661{
1662 LogFlow(("HMR3Reset:\n"));
1663
1664 if (HMIsEnabled(pVM))
1665 hmR3DisableRawMode(pVM);
1666
1667 for (VMCPUID i = 0; i < pVM->cCpus; i++)
1668 {
1669 PVMCPU pVCpu = &pVM->aCpus[i];
1670
1671 HMR3ResetCpu(pVCpu);
1672 }
1673
1674 /* Clear all patch information. */
1675 pVM->hm.s.pGuestPatchMem = 0;
1676 pVM->hm.s.pFreeGuestPatchMem = 0;
1677 pVM->hm.s.cbGuestPatchMem = 0;
1678 pVM->hm.s.cPatches = 0;
1679 pVM->hm.s.PatchTree = 0;
1680 pVM->hm.s.fTPRPatchingActive = false;
1681 ASMMemZero32(pVM->hm.s.aPatches, sizeof(pVM->hm.s.aPatches));
1682}
1683
1684
1685/**
1686 * Callback to patch a TPR instruction (vmmcall or mov cr8).
1687 *
1688 * @returns VBox strict status code.
1689 * @param pVM Pointer to the VM.
1690 * @param pVCpu The VMCPU for the EMT we're being called on.
1691 * @param pvUser Unused.
1692 */
1693DECLCALLBACK(VBOXSTRICTRC) hmR3RemovePatches(PVM pVM, PVMCPU pVCpu, void *pvUser)
1694{
1695 VMCPUID idCpu = (VMCPUID)(uintptr_t)pvUser;
1696
1697 /* Only execute the handler on the VCPU the original patch request was issued. */
1698 if (pVCpu->idCpu != idCpu)
1699 return VINF_SUCCESS;
1700
1701 Log(("hmR3RemovePatches\n"));
1702 for (unsigned i = 0; i < pVM->hm.s.cPatches; i++)
1703 {
1704 uint8_t abInstr[15];
1705 PHMTPRPATCH pPatch = &pVM->hm.s.aPatches[i];
1706 RTGCPTR pInstrGC = (RTGCPTR)pPatch->Core.Key;
1707 int rc;
1708
1709#ifdef LOG_ENABLED
1710 char szOutput[256];
1711
1712 rc = DBGFR3DisasInstrEx(pVM->pUVM, pVCpu->idCpu, CPUMGetGuestCS(pVCpu), pInstrGC, DBGF_DISAS_FLAGS_DEFAULT_MODE,
1713 szOutput, sizeof(szOutput), NULL);
1714 if (RT_SUCCESS(rc))
1715 Log(("Patched instr: %s\n", szOutput));
1716#endif
1717
1718 /* Check if the instruction is still the same. */
1719 rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pInstrGC, pPatch->cbNewOp);
1720 if (rc != VINF_SUCCESS)
1721 {
1722 Log(("Patched code removed? (rc=%Rrc0\n", rc));
1723 continue; /* swapped out or otherwise removed; skip it. */
1724 }
1725
1726 if (memcmp(abInstr, pPatch->aNewOpcode, pPatch->cbNewOp))
1727 {
1728 Log(("Patched instruction was changed! (rc=%Rrc0\n", rc));
1729 continue; /* skip it. */
1730 }
1731
1732 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pInstrGC, pPatch->aOpcode, pPatch->cbOp);
1733 AssertRC(rc);
1734
1735#ifdef LOG_ENABLED
1736 rc = DBGFR3DisasInstrEx(pVM->pUVM, pVCpu->idCpu, CPUMGetGuestCS(pVCpu), pInstrGC, DBGF_DISAS_FLAGS_DEFAULT_MODE,
1737 szOutput, sizeof(szOutput), NULL);
1738 if (RT_SUCCESS(rc))
1739 Log(("Original instr: %s\n", szOutput));
1740#endif
1741 }
1742 pVM->hm.s.cPatches = 0;
1743 pVM->hm.s.PatchTree = 0;
1744 pVM->hm.s.pFreeGuestPatchMem = pVM->hm.s.pGuestPatchMem;
1745 pVM->hm.s.fTPRPatchingActive = false;
1746 return VINF_SUCCESS;
1747}
1748
1749
1750/**
1751 * Worker for enabling patching in a VT-x/AMD-V guest.
1752 *
1753 * @returns VBox status code.
1754 * @param pVM Pointer to the VM.
1755 * @param idCpu VCPU to execute hmR3RemovePatches on.
1756 * @param pPatchMem Patch memory range.
1757 * @param cbPatchMem Size of the memory range.
1758 */
1759static int hmR3EnablePatching(PVM pVM, VMCPUID idCpu, RTRCPTR pPatchMem, unsigned cbPatchMem)
1760{
1761 int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONE_BY_ONE, hmR3RemovePatches, (void *)(uintptr_t)idCpu);
1762 AssertRC(rc);
1763
1764 pVM->hm.s.pGuestPatchMem = pPatchMem;
1765 pVM->hm.s.pFreeGuestPatchMem = pPatchMem;
1766 pVM->hm.s.cbGuestPatchMem = cbPatchMem;
1767 return VINF_SUCCESS;
1768}
1769
1770
1771/**
1772 * Enable patching in a VT-x/AMD-V guest
1773 *
1774 * @returns VBox status code.
1775 * @param pVM Pointer to the VM.
1776 * @param pPatchMem Patch memory range.
1777 * @param cbPatchMem Size of the memory range.
1778 */
1779VMMR3_INT_DECL(int) HMR3EnablePatching(PVM pVM, RTGCPTR pPatchMem, unsigned cbPatchMem)
1780{
1781 VM_ASSERT_EMT(pVM);
1782 Log(("HMR3EnablePatching %RGv size %x\n", pPatchMem, cbPatchMem));
1783 if (pVM->cCpus > 1)
1784 {
1785 /* We own the IOM lock here and could cause a deadlock by waiting for a VCPU that is blocking on the IOM lock. */
1786 int rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE,
1787 (PFNRT)hmR3EnablePatching, 4, pVM, VMMGetCpuId(pVM), (RTRCPTR)pPatchMem, cbPatchMem);
1788 AssertRC(rc);
1789 return rc;
1790 }
1791 return hmR3EnablePatching(pVM, VMMGetCpuId(pVM), (RTRCPTR)pPatchMem, cbPatchMem);
1792}
1793
1794
1795/**
1796 * Disable patching in a VT-x/AMD-V guest.
1797 *
1798 * @returns VBox status code.
1799 * @param pVM Pointer to the VM.
1800 * @param pPatchMem Patch memory range.
1801 * @param cbPatchMem Size of the memory range.
1802 */
1803VMMR3_INT_DECL(int) HMR3DisablePatching(PVM pVM, RTGCPTR pPatchMem, unsigned cbPatchMem)
1804{
1805 Log(("HMR3DisablePatching %RGv size %x\n", pPatchMem, cbPatchMem));
1806
1807 Assert(pVM->hm.s.pGuestPatchMem == pPatchMem);
1808 Assert(pVM->hm.s.cbGuestPatchMem == cbPatchMem);
1809
1810 /* @todo Potential deadlock when other VCPUs are waiting on the IOM lock (we own it)!! */
1811 int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONE_BY_ONE, hmR3RemovePatches,
1812 (void *)(uintptr_t)VMMGetCpuId(pVM));
1813 AssertRC(rc);
1814
1815 pVM->hm.s.pGuestPatchMem = 0;
1816 pVM->hm.s.pFreeGuestPatchMem = 0;
1817 pVM->hm.s.cbGuestPatchMem = 0;
1818 pVM->hm.s.fTPRPatchingActive = false;
1819 return VINF_SUCCESS;
1820}
1821
1822
1823/**
1824 * Callback to patch a TPR instruction (vmmcall or mov cr8).
1825 *
1826 * @returns VBox strict status code.
1827 * @param pVM Pointer to the VM.
1828 * @param pVCpu The VMCPU for the EMT we're being called on.
1829 * @param pvUser User specified CPU context.
1830 *
1831 */
1832DECLCALLBACK(VBOXSTRICTRC) hmR3ReplaceTprInstr(PVM pVM, PVMCPU pVCpu, void *pvUser)
1833{
1834 /*
1835 * Only execute the handler on the VCPU the original patch request was
1836 * issued. (The other CPU(s) might not yet have switched to protected
1837 * mode, nor have the correct memory context.)
1838 */
1839 VMCPUID idCpu = (VMCPUID)(uintptr_t)pvUser;
1840 if (pVCpu->idCpu != idCpu)
1841 return VINF_SUCCESS;
1842
1843 /*
1844 * We're racing other VCPUs here, so don't try patch the instruction twice
1845 * and make sure there is still room for our patch record.
1846 */
1847 PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
1848 PHMTPRPATCH pPatch = (PHMTPRPATCH)RTAvloU32Get(&pVM->hm.s.PatchTree, (AVLOU32KEY)pCtx->eip);
1849 if (pPatch)
1850 {
1851 Log(("hmR3ReplaceTprInstr: already patched %RGv\n", pCtx->rip));
1852 return VINF_SUCCESS;
1853 }
1854 uint32_t const idx = pVM->hm.s.cPatches;
1855 if (idx >= RT_ELEMENTS(pVM->hm.s.aPatches))
1856 {
1857 Log(("hmR3ReplaceTprInstr: no available patch slots (%RGv)\n", pCtx->rip));
1858 return VINF_SUCCESS;
1859 }
1860 pPatch = &pVM->hm.s.aPatches[idx];
1861
1862 Log(("hmR3ReplaceTprInstr: rip=%RGv idxPatch=%u\n", pCtx->rip, idx));
1863
1864 /*
1865 * Disassembler the instruction and get cracking.
1866 */
1867 DBGFR3_DISAS_INSTR_CUR_LOG(pVCpu, "hmR3ReplaceTprInstr");
1868 PDISCPUSTATE pDis = &pVCpu->hm.s.DisState;
1869 uint32_t cbOp;
1870 int rc = EMInterpretDisasCurrent(pVM, pVCpu, pDis, &cbOp);
1871 AssertRC(rc);
1872 if ( rc == VINF_SUCCESS
1873 && pDis->pCurInstr->uOpcode == OP_MOV
1874 && cbOp >= 3)
1875 {
1876 static uint8_t const s_abVMMCall[3] = { 0x0f, 0x01, 0xd9 };
1877
1878 rc = PGMPhysSimpleReadGCPtr(pVCpu, pPatch->aOpcode, pCtx->rip, cbOp);
1879 AssertRC(rc);
1880
1881 pPatch->cbOp = cbOp;
1882
1883 if (pDis->Param1.fUse == DISUSE_DISPLACEMENT32)
1884 {
1885 /* write. */
1886 if (pDis->Param2.fUse == DISUSE_REG_GEN32)
1887 {
1888 pPatch->enmType = HMTPRINSTR_WRITE_REG;
1889 pPatch->uSrcOperand = pDis->Param2.Base.idxGenReg;
1890 Log(("hmR3ReplaceTprInstr: HMTPRINSTR_WRITE_REG %u\n", pDis->Param2.Base.idxGenReg));
1891 }
1892 else
1893 {
1894 Assert(pDis->Param2.fUse == DISUSE_IMMEDIATE32);
1895 pPatch->enmType = HMTPRINSTR_WRITE_IMM;
1896 pPatch->uSrcOperand = pDis->Param2.uValue;
1897 Log(("hmR3ReplaceTprInstr: HMTPRINSTR_WRITE_IMM %#llx\n", pDis->Param2.uValue));
1898 }
1899 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, s_abVMMCall, sizeof(s_abVMMCall));
1900 AssertRC(rc);
1901
1902 memcpy(pPatch->aNewOpcode, s_abVMMCall, sizeof(s_abVMMCall));
1903 pPatch->cbNewOp = sizeof(s_abVMMCall);
1904 }
1905 else
1906 {
1907 /*
1908 * TPR Read.
1909 *
1910 * Found:
1911 * mov eax, dword [fffe0080] (5 bytes)
1912 * Check if next instruction is:
1913 * shr eax, 4
1914 */
1915 Assert(pDis->Param1.fUse == DISUSE_REG_GEN32);
1916
1917 uint8_t const idxMmioReg = pDis->Param1.Base.idxGenReg;
1918 uint8_t const cbOpMmio = cbOp;
1919 uint64_t const uSavedRip = pCtx->rip;
1920
1921 pCtx->rip += cbOp;
1922 rc = EMInterpretDisasCurrent(pVM, pVCpu, pDis, &cbOp);
1923 DBGFR3_DISAS_INSTR_CUR_LOG(pVCpu, "Following read");
1924 pCtx->rip = uSavedRip;
1925
1926 if ( rc == VINF_SUCCESS
1927 && pDis->pCurInstr->uOpcode == OP_SHR
1928 && pDis->Param1.fUse == DISUSE_REG_GEN32
1929 && pDis->Param1.Base.idxGenReg == idxMmioReg
1930 && pDis->Param2.fUse == DISUSE_IMMEDIATE8
1931 && pDis->Param2.uValue == 4
1932 && cbOpMmio + cbOp < sizeof(pVM->hm.s.aPatches[idx].aOpcode))
1933 {
1934 uint8_t abInstr[15];
1935
1936 /* Replacing the two instructions above with an AMD-V specific lock-prefixed 32-bit MOV CR8 instruction so as to
1937 access CR8 in 32-bit mode and not cause a #VMEXIT. */
1938 rc = PGMPhysSimpleReadGCPtr(pVCpu, &pPatch->aOpcode, pCtx->rip, cbOpMmio + cbOp);
1939 AssertRC(rc);
1940
1941 pPatch->cbOp = cbOpMmio + cbOp;
1942
1943 /* 0xF0, 0x0F, 0x20, 0xC0 = mov eax, cr8 */
1944 abInstr[0] = 0xF0;
1945 abInstr[1] = 0x0F;
1946 abInstr[2] = 0x20;
1947 abInstr[3] = 0xC0 | pDis->Param1.Base.idxGenReg;
1948 for (unsigned i = 4; i < pPatch->cbOp; i++)
1949 abInstr[i] = 0x90; /* nop */
1950
1951 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, abInstr, pPatch->cbOp);
1952 AssertRC(rc);
1953
1954 memcpy(pPatch->aNewOpcode, abInstr, pPatch->cbOp);
1955 pPatch->cbNewOp = pPatch->cbOp;
1956
1957 Log(("Acceptable read/shr candidate!\n"));
1958 pPatch->enmType = HMTPRINSTR_READ_SHR4;
1959 }
1960 else
1961 {
1962 pPatch->enmType = HMTPRINSTR_READ;
1963 pPatch->uDstOperand = idxMmioReg;
1964
1965 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, s_abVMMCall, sizeof(s_abVMMCall));
1966 AssertRC(rc);
1967
1968 memcpy(pPatch->aNewOpcode, s_abVMMCall, sizeof(s_abVMMCall));
1969 pPatch->cbNewOp = sizeof(s_abVMMCall);
1970 Log(("hmR3ReplaceTprInstr: HMTPRINSTR_READ %u\n", pPatch->uDstOperand));
1971 }
1972 }
1973
1974 pPatch->Core.Key = pCtx->eip;
1975 rc = RTAvloU32Insert(&pVM->hm.s.PatchTree, &pPatch->Core);
1976 AssertRC(rc);
1977
1978 pVM->hm.s.cPatches++;
1979 STAM_COUNTER_INC(&pVM->hm.s.StatTprReplaceSuccess);
1980 return VINF_SUCCESS;
1981 }
1982
1983 /*
1984 * Save invalid patch, so we will not try again.
1985 */
1986 Log(("hmR3ReplaceTprInstr: Failed to patch instr!\n"));
1987 pPatch->Core.Key = pCtx->eip;
1988 pPatch->enmType = HMTPRINSTR_INVALID;
1989 rc = RTAvloU32Insert(&pVM->hm.s.PatchTree, &pPatch->Core);
1990 AssertRC(rc);
1991 pVM->hm.s.cPatches++;
1992 STAM_COUNTER_INC(&pVM->hm.s.StatTprReplaceFailure);
1993 return VINF_SUCCESS;
1994}
1995
1996
1997/**
1998 * Callback to patch a TPR instruction (jump to generated code).
1999 *
2000 * @returns VBox strict status code.
2001 * @param pVM Pointer to the VM.
2002 * @param pVCpu The VMCPU for the EMT we're being called on.
2003 * @param pvUser User specified CPU context.
2004 *
2005 */
2006DECLCALLBACK(VBOXSTRICTRC) hmR3PatchTprInstr(PVM pVM, PVMCPU pVCpu, void *pvUser)
2007{
2008 /*
2009 * Only execute the handler on the VCPU the original patch request was
2010 * issued. (The other CPU(s) might not yet have switched to protected
2011 * mode, nor have the correct memory context.)
2012 */
2013 VMCPUID idCpu = (VMCPUID)(uintptr_t)pvUser;
2014 if (pVCpu->idCpu != idCpu)
2015 return VINF_SUCCESS;
2016
2017 /*
2018 * We're racing other VCPUs here, so don't try patch the instruction twice
2019 * and make sure there is still room for our patch record.
2020 */
2021 PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
2022 PHMTPRPATCH pPatch = (PHMTPRPATCH)RTAvloU32Get(&pVM->hm.s.PatchTree, (AVLOU32KEY)pCtx->eip);
2023 if (pPatch)
2024 {
2025 Log(("hmR3PatchTprInstr: already patched %RGv\n", pCtx->rip));
2026 return VINF_SUCCESS;
2027 }
2028 uint32_t const idx = pVM->hm.s.cPatches;
2029 if (idx >= RT_ELEMENTS(pVM->hm.s.aPatches))
2030 {
2031 Log(("hmR3PatchTprInstr: no available patch slots (%RGv)\n", pCtx->rip));
2032 return VINF_SUCCESS;
2033 }
2034 pPatch = &pVM->hm.s.aPatches[idx];
2035
2036 Log(("hmR3PatchTprInstr: rip=%RGv idxPatch=%u\n", pCtx->rip, idx));
2037 DBGFR3_DISAS_INSTR_CUR_LOG(pVCpu, "hmR3PatchTprInstr");
2038
2039 /*
2040 * Disassemble the instruction and get cracking.
2041 */
2042 PDISCPUSTATE pDis = &pVCpu->hm.s.DisState;
2043 uint32_t cbOp;
2044 int rc = EMInterpretDisasCurrent(pVM, pVCpu, pDis, &cbOp);
2045 AssertRC(rc);
2046 if ( rc == VINF_SUCCESS
2047 && pDis->pCurInstr->uOpcode == OP_MOV
2048 && cbOp >= 5)
2049 {
2050 uint8_t aPatch[64];
2051 uint32_t off = 0;
2052
2053 rc = PGMPhysSimpleReadGCPtr(pVCpu, pPatch->aOpcode, pCtx->rip, cbOp);
2054 AssertRC(rc);
2055
2056 pPatch->cbOp = cbOp;
2057 pPatch->enmType = HMTPRINSTR_JUMP_REPLACEMENT;
2058
2059 if (pDis->Param1.fUse == DISUSE_DISPLACEMENT32)
2060 {
2061 /*
2062 * TPR write:
2063 *
2064 * push ECX [51]
2065 * push EDX [52]
2066 * push EAX [50]
2067 * xor EDX,EDX [31 D2]
2068 * mov EAX,EAX [89 C0]
2069 * or
2070 * mov EAX,0000000CCh [B8 CC 00 00 00]
2071 * mov ECX,0C0000082h [B9 82 00 00 C0]
2072 * wrmsr [0F 30]
2073 * pop EAX [58]
2074 * pop EDX [5A]
2075 * pop ECX [59]
2076 * jmp return_address [E9 return_address]
2077 *
2078 */
2079 bool fUsesEax = (pDis->Param2.fUse == DISUSE_REG_GEN32 && pDis->Param2.Base.idxGenReg == DISGREG_EAX);
2080
2081 aPatch[off++] = 0x51; /* push ecx */
2082 aPatch[off++] = 0x52; /* push edx */
2083 if (!fUsesEax)
2084 aPatch[off++] = 0x50; /* push eax */
2085 aPatch[off++] = 0x31; /* xor edx, edx */
2086 aPatch[off++] = 0xD2;
2087 if (pDis->Param2.fUse == DISUSE_REG_GEN32)
2088 {
2089 if (!fUsesEax)
2090 {
2091 aPatch[off++] = 0x89; /* mov eax, src_reg */
2092 aPatch[off++] = MAKE_MODRM(3, pDis->Param2.Base.idxGenReg, DISGREG_EAX);
2093 }
2094 }
2095 else
2096 {
2097 Assert(pDis->Param2.fUse == DISUSE_IMMEDIATE32);
2098 aPatch[off++] = 0xB8; /* mov eax, immediate */
2099 *(uint32_t *)&aPatch[off] = pDis->Param2.uValue;
2100 off += sizeof(uint32_t);
2101 }
2102 aPatch[off++] = 0xB9; /* mov ecx, 0xc0000082 */
2103 *(uint32_t *)&aPatch[off] = MSR_K8_LSTAR;
2104 off += sizeof(uint32_t);
2105
2106 aPatch[off++] = 0x0F; /* wrmsr */
2107 aPatch[off++] = 0x30;
2108 if (!fUsesEax)
2109 aPatch[off++] = 0x58; /* pop eax */
2110 aPatch[off++] = 0x5A; /* pop edx */
2111 aPatch[off++] = 0x59; /* pop ecx */
2112 }
2113 else
2114 {
2115 /*
2116 * TPR read:
2117 *
2118 * push ECX [51]
2119 * push EDX [52]
2120 * push EAX [50]
2121 * mov ECX,0C0000082h [B9 82 00 00 C0]
2122 * rdmsr [0F 32]
2123 * mov EAX,EAX [89 C0]
2124 * pop EAX [58]
2125 * pop EDX [5A]
2126 * pop ECX [59]
2127 * jmp return_address [E9 return_address]
2128 *
2129 */
2130 Assert(pDis->Param1.fUse == DISUSE_REG_GEN32);
2131
2132 if (pDis->Param1.Base.idxGenReg != DISGREG_ECX)
2133 aPatch[off++] = 0x51; /* push ecx */
2134 if (pDis->Param1.Base.idxGenReg != DISGREG_EDX )
2135 aPatch[off++] = 0x52; /* push edx */
2136 if (pDis->Param1.Base.idxGenReg != DISGREG_EAX)
2137 aPatch[off++] = 0x50; /* push eax */
2138
2139 aPatch[off++] = 0x31; /* xor edx, edx */
2140 aPatch[off++] = 0xD2;
2141
2142 aPatch[off++] = 0xB9; /* mov ecx, 0xc0000082 */
2143 *(uint32_t *)&aPatch[off] = MSR_K8_LSTAR;
2144 off += sizeof(uint32_t);
2145
2146 aPatch[off++] = 0x0F; /* rdmsr */
2147 aPatch[off++] = 0x32;
2148
2149 if (pDis->Param1.Base.idxGenReg != DISGREG_EAX)
2150 {
2151 aPatch[off++] = 0x89; /* mov dst_reg, eax */
2152 aPatch[off++] = MAKE_MODRM(3, DISGREG_EAX, pDis->Param1.Base.idxGenReg);
2153 }
2154
2155 if (pDis->Param1.Base.idxGenReg != DISGREG_EAX)
2156 aPatch[off++] = 0x58; /* pop eax */
2157 if (pDis->Param1.Base.idxGenReg != DISGREG_EDX )
2158 aPatch[off++] = 0x5A; /* pop edx */
2159 if (pDis->Param1.Base.idxGenReg != DISGREG_ECX)
2160 aPatch[off++] = 0x59; /* pop ecx */
2161 }
2162 aPatch[off++] = 0xE9; /* jmp return_address */
2163 *(RTRCUINTPTR *)&aPatch[off] = ((RTRCUINTPTR)pCtx->eip + cbOp) - ((RTRCUINTPTR)pVM->hm.s.pFreeGuestPatchMem + off + 4);
2164 off += sizeof(RTRCUINTPTR);
2165
2166 if (pVM->hm.s.pFreeGuestPatchMem + off <= pVM->hm.s.pGuestPatchMem + pVM->hm.s.cbGuestPatchMem)
2167 {
2168 /* Write new code to the patch buffer. */
2169 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pVM->hm.s.pFreeGuestPatchMem, aPatch, off);
2170 AssertRC(rc);
2171
2172#ifdef LOG_ENABLED
2173 uint32_t cbCurInstr;
2174 for (RTGCPTR GCPtrInstr = pVM->hm.s.pFreeGuestPatchMem;
2175 GCPtrInstr < pVM->hm.s.pFreeGuestPatchMem + off;
2176 GCPtrInstr += RT_MAX(cbCurInstr, 1))
2177 {
2178 char szOutput[256];
2179 rc = DBGFR3DisasInstrEx(pVM->pUVM, pVCpu->idCpu, pCtx->cs.Sel, GCPtrInstr, DBGF_DISAS_FLAGS_DEFAULT_MODE,
2180 szOutput, sizeof(szOutput), &cbCurInstr);
2181 if (RT_SUCCESS(rc))
2182 Log(("Patch instr %s\n", szOutput));
2183 else
2184 Log(("%RGv: rc=%Rrc\n", GCPtrInstr, rc));
2185 }
2186#endif
2187
2188 pPatch->aNewOpcode[0] = 0xE9;
2189 *(RTRCUINTPTR *)&pPatch->aNewOpcode[1] = ((RTRCUINTPTR)pVM->hm.s.pFreeGuestPatchMem) - ((RTRCUINTPTR)pCtx->eip + 5);
2190
2191 /* Overwrite the TPR instruction with a jump. */
2192 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->eip, pPatch->aNewOpcode, 5);
2193 AssertRC(rc);
2194
2195 DBGFR3_DISAS_INSTR_CUR_LOG(pVCpu, "Jump");
2196
2197 pVM->hm.s.pFreeGuestPatchMem += off;
2198 pPatch->cbNewOp = 5;
2199
2200 pPatch->Core.Key = pCtx->eip;
2201 rc = RTAvloU32Insert(&pVM->hm.s.PatchTree, &pPatch->Core);
2202 AssertRC(rc);
2203
2204 pVM->hm.s.cPatches++;
2205 pVM->hm.s.fTPRPatchingActive = true;
2206 STAM_COUNTER_INC(&pVM->hm.s.StatTprPatchSuccess);
2207 return VINF_SUCCESS;
2208 }
2209
2210 Log(("Ran out of space in our patch buffer!\n"));
2211 }
2212 else
2213 Log(("hmR3PatchTprInstr: Failed to patch instr!\n"));
2214
2215
2216 /*
2217 * Save invalid patch, so we will not try again.
2218 */
2219 pPatch = &pVM->hm.s.aPatches[idx];
2220 pPatch->Core.Key = pCtx->eip;
2221 pPatch->enmType = HMTPRINSTR_INVALID;
2222 rc = RTAvloU32Insert(&pVM->hm.s.PatchTree, &pPatch->Core);
2223 AssertRC(rc);
2224 pVM->hm.s.cPatches++;
2225 STAM_COUNTER_INC(&pVM->hm.s.StatTprPatchFailure);
2226 return VINF_SUCCESS;
2227}
2228
2229
2230/**
2231 * Attempt to patch TPR mmio instructions.
2232 *
2233 * @returns VBox status code.
2234 * @param pVM Pointer to the VM.
2235 * @param pVCpu Pointer to the VMCPU.
2236 * @param pCtx Pointer to the guest CPU context.
2237 */
2238VMMR3_INT_DECL(int) HMR3PatchTprInstr(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
2239{
2240 NOREF(pCtx);
2241 int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONE_BY_ONE,
2242 pVM->hm.s.pGuestPatchMem ? hmR3PatchTprInstr : hmR3ReplaceTprInstr,
2243 (void *)(uintptr_t)pVCpu->idCpu);
2244 AssertRC(rc);
2245 return rc;
2246}
2247
2248
2249/**
2250 * Checks if a code selector (CS) is suitable for execution
2251 * within VMX when unrestricted execution isn't available.
2252 *
2253 * @returns true if selector is suitable for VMX, otherwise
2254 * false.
2255 * @param pSel Pointer to the selector to check (CS).
2256 * uStackDpl The CPL, aka the DPL of the stack segment.
2257 */
2258static bool hmR3IsCodeSelectorOkForVmx(PCPUMSELREG pSel, unsigned uStackDpl)
2259{
2260 /*
2261 * Segment must be an accessed code segment, it must be present and it must
2262 * be usable.
2263 * Note! These are all standard requirements and if CS holds anything else
2264 * we've got buggy code somewhere!
2265 */
2266 AssertCompile(X86DESCATTR_TYPE == 0xf);
2267 AssertMsgReturn( (pSel->Attr.u & (X86_SEL_TYPE_ACCESSED | X86_SEL_TYPE_CODE | X86DESCATTR_DT | X86DESCATTR_P | X86DESCATTR_UNUSABLE))
2268 == (X86_SEL_TYPE_ACCESSED | X86_SEL_TYPE_CODE | X86DESCATTR_DT | X86DESCATTR_P),
2269 ("%#x\n", pSel->Attr.u),
2270 false);
2271
2272 /* For conforming segments, CS.DPL must be <= SS.DPL, while CS.DPL
2273 must equal SS.DPL for non-confroming segments.
2274 Note! This is also a hard requirement like above. */
2275 AssertMsgReturn( pSel->Attr.n.u4Type & X86_SEL_TYPE_CONF
2276 ? pSel->Attr.n.u2Dpl <= uStackDpl
2277 : pSel->Attr.n.u2Dpl == uStackDpl,
2278 ("u4Type=%#x u2Dpl=%u uStackDpl=%u\n", pSel->Attr.n.u4Type, pSel->Attr.n.u2Dpl, uStackDpl),
2279 false);
2280
2281 /*
2282 * The following two requirements are VT-x specific:
2283 * - G bit must be set if any high limit bits are set.
2284 * - G bit must be clear if any low limit bits are clear.
2285 */
2286 if ( ((pSel->u32Limit & 0xfff00000) == 0x00000000 || pSel->Attr.n.u1Granularity)
2287 && ((pSel->u32Limit & 0x00000fff) == 0x00000fff || !pSel->Attr.n.u1Granularity) )
2288 return true;
2289 return false;
2290}
2291
2292
2293/**
2294 * Checks if a data selector (DS/ES/FS/GS) is suitable for
2295 * execution within VMX when unrestricted execution isn't
2296 * available.
2297 *
2298 * @returns true if selector is suitable for VMX, otherwise
2299 * false.
2300 * @param pSel Pointer to the selector to check
2301 * (DS/ES/FS/GS).
2302 */
2303static bool hmR3IsDataSelectorOkForVmx(PCPUMSELREG pSel)
2304{
2305 /*
2306 * Unusable segments are OK. These days they should be marked as such, as
2307 * but as an alternative we for old saved states and AMD<->VT-x migration
2308 * we also treat segments with all the attributes cleared as unusable.
2309 */
2310 if (pSel->Attr.n.u1Unusable || !pSel->Attr.u)
2311 return true;
2312
2313 /** @todo tighten these checks. Will require CPUM load adjusting. */
2314
2315 /* Segment must be accessed. */
2316 if (pSel->Attr.u & X86_SEL_TYPE_ACCESSED)
2317 {
2318 /* Code segments must also be readable. */
2319 if ( !(pSel->Attr.u & X86_SEL_TYPE_CODE)
2320 || (pSel->Attr.u & X86_SEL_TYPE_READ))
2321 {
2322 /* The S bit must be set. */
2323 if (pSel->Attr.n.u1DescType)
2324 {
2325 /* Except for conforming segments, DPL >= RPL. */
2326 if ( pSel->Attr.n.u2Dpl >= (pSel->Sel & X86_SEL_RPL)
2327 || pSel->Attr.n.u4Type >= X86_SEL_TYPE_ER_ACC)
2328 {
2329 /* Segment must be present. */
2330 if (pSel->Attr.n.u1Present)
2331 {
2332 /*
2333 * The following two requirements are VT-x specific:
2334 * - G bit must be set if any high limit bits are set.
2335 * - G bit must be clear if any low limit bits are clear.
2336 */
2337 if ( ((pSel->u32Limit & 0xfff00000) == 0x00000000 || pSel->Attr.n.u1Granularity)
2338 && ((pSel->u32Limit & 0x00000fff) == 0x00000fff || !pSel->Attr.n.u1Granularity) )
2339 return true;
2340 }
2341 }
2342 }
2343 }
2344 }
2345
2346 return false;
2347}
2348
2349
2350/**
2351 * Checks if the stack selector (SS) is suitable for execution
2352 * within VMX when unrestricted execution isn't available.
2353 *
2354 * @returns true if selector is suitable for VMX, otherwise
2355 * false.
2356 * @param pSel Pointer to the selector to check (SS).
2357 */
2358static bool hmR3IsStackSelectorOkForVmx(PCPUMSELREG pSel)
2359{
2360 /*
2361 * Unusable segments are OK. These days they should be marked as such, as
2362 * but as an alternative we for old saved states and AMD<->VT-x migration
2363 * we also treat segments with all the attributes cleared as unusable.
2364 */
2365 /** @todo r=bird: actually all zeros isn't gonna cut it... SS.DPL == CPL. */
2366 if (pSel->Attr.n.u1Unusable || !pSel->Attr.u)
2367 return true;
2368
2369 /*
2370 * Segment must be an accessed writable segment, it must be present.
2371 * Note! These are all standard requirements and if SS holds anything else
2372 * we've got buggy code somewhere!
2373 */
2374 AssertCompile(X86DESCATTR_TYPE == 0xf);
2375 AssertMsgReturn( (pSel->Attr.u & (X86_SEL_TYPE_ACCESSED | X86_SEL_TYPE_WRITE | X86DESCATTR_DT | X86DESCATTR_P | X86_SEL_TYPE_CODE))
2376 == (X86_SEL_TYPE_ACCESSED | X86_SEL_TYPE_WRITE | X86DESCATTR_DT | X86DESCATTR_P),
2377 ("%#x\n", pSel->Attr.u),
2378 false);
2379
2380 /* DPL must equal RPL.
2381 Note! This is also a hard requirement like above. */
2382 AssertMsgReturn(pSel->Attr.n.u2Dpl == (pSel->Sel & X86_SEL_RPL),
2383 ("u2Dpl=%u Sel=%#x\n", pSel->Attr.n.u2Dpl, pSel->Sel),
2384 false);
2385
2386 /*
2387 * The following two requirements are VT-x specific:
2388 * - G bit must be set if any high limit bits are set.
2389 * - G bit must be clear if any low limit bits are clear.
2390 */
2391 if ( ((pSel->u32Limit & 0xfff00000) == 0x00000000 || pSel->Attr.n.u1Granularity)
2392 && ((pSel->u32Limit & 0x00000fff) == 0x00000fff || !pSel->Attr.n.u1Granularity) )
2393 return true;
2394 return false;
2395}
2396
2397
2398/**
2399 * Force execution of the current IO code in the recompiler.
2400 *
2401 * @returns VBox status code.
2402 * @param pVM Pointer to the VM.
2403 * @param pCtx Partial VM execution context.
2404 */
2405VMMR3_INT_DECL(int) HMR3EmulateIoBlock(PVM pVM, PCPUMCTX pCtx)
2406{
2407 PVMCPU pVCpu = VMMGetCpu(pVM);
2408
2409 Assert(HMIsEnabled(pVM));
2410 Log(("HMR3EmulateIoBlock\n"));
2411
2412 /* This is primarily intended to speed up Grub, so we don't care about paged protected mode. */
2413 if (HMCanEmulateIoBlockEx(pCtx))
2414 {
2415 Log(("HMR3EmulateIoBlock -> enabled\n"));
2416 pVCpu->hm.s.EmulateIoBlock.fEnabled = true;
2417 pVCpu->hm.s.EmulateIoBlock.GCPtrFunctionEip = pCtx->rip;
2418 pVCpu->hm.s.EmulateIoBlock.cr0 = pCtx->cr0;
2419 return VINF_EM_RESCHEDULE_REM;
2420 }
2421 return VINF_SUCCESS;
2422}
2423
2424
2425/**
2426 * Checks if we can currently use hardware accelerated raw mode.
2427 *
2428 * @returns true if we can currently use hardware acceleration, otherwise false.
2429 * @param pVM Pointer to the VM.
2430 * @param pCtx Partial VM execution context.
2431 */
2432VMMR3DECL(bool) HMR3CanExecuteGuest(PVM pVM, PCPUMCTX pCtx)
2433{
2434 PVMCPU pVCpu = VMMGetCpu(pVM);
2435
2436 Assert(HMIsEnabled(pVM));
2437
2438 /* If we're still executing the IO code, then return false. */
2439 if ( RT_UNLIKELY(pVCpu->hm.s.EmulateIoBlock.fEnabled)
2440 && pCtx->rip < pVCpu->hm.s.EmulateIoBlock.GCPtrFunctionEip + 0x200
2441 && pCtx->rip > pVCpu->hm.s.EmulateIoBlock.GCPtrFunctionEip - 0x200
2442 && pCtx->cr0 == pVCpu->hm.s.EmulateIoBlock.cr0)
2443 return false;
2444
2445 pVCpu->hm.s.EmulateIoBlock.fEnabled = false;
2446
2447 /* AMD-V supports real & protected mode with or without paging. */
2448 if (pVM->hm.s.svm.fEnabled)
2449 {
2450 pVCpu->hm.s.fActive = true;
2451 return true;
2452 }
2453
2454 pVCpu->hm.s.fActive = false;
2455
2456 /* Note! The context supplied by REM is partial. If we add more checks here, be sure to verify that REM provides this info! */
2457 Assert( (pVM->hm.s.vmx.fUnrestrictedGuest && !pVM->hm.s.vmx.pRealModeTSS)
2458 || (!pVM->hm.s.vmx.fUnrestrictedGuest && pVM->hm.s.vmx.pRealModeTSS));
2459
2460 bool fSupportsRealMode = pVM->hm.s.vmx.fUnrestrictedGuest || PDMVmmDevHeapIsEnabled(pVM);
2461 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
2462 {
2463 /*
2464 * The VMM device heap is a requirement for emulating real mode or protected mode without paging with the unrestricted
2465 * guest execution feature i missing (VT-x only).
2466 */
2467 if (fSupportsRealMode)
2468 {
2469 if (CPUMIsGuestInRealModeEx(pCtx))
2470 {
2471 /* In V86 mode (VT-x or not), the CPU enforces real-mode compatible selector
2472 * bases and limits, i.e. limit must be 64K and base must be selector * 16.
2473 * If this is not true, we cannot execute real mode as V86 and have to fall
2474 * back to emulation.
2475 */
2476 if ( pCtx->cs.Sel != (pCtx->cs.u64Base >> 4)
2477 || pCtx->ds.Sel != (pCtx->ds.u64Base >> 4)
2478 || pCtx->es.Sel != (pCtx->es.u64Base >> 4)
2479 || pCtx->ss.Sel != (pCtx->ss.u64Base >> 4)
2480 || pCtx->fs.Sel != (pCtx->fs.u64Base >> 4)
2481 || pCtx->gs.Sel != (pCtx->gs.u64Base >> 4))
2482 {
2483 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxCheckBadRmSelBase);
2484 return false;
2485 }
2486 if ( (pCtx->cs.u32Limit != 0xffff)
2487 || (pCtx->ds.u32Limit != 0xffff)
2488 || (pCtx->es.u32Limit != 0xffff)
2489 || (pCtx->ss.u32Limit != 0xffff)
2490 || (pCtx->fs.u32Limit != 0xffff)
2491 || (pCtx->gs.u32Limit != 0xffff))
2492 {
2493 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxCheckBadRmSelLimit);
2494 return false;
2495 }
2496 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxCheckRmOk);
2497 }
2498 else
2499 {
2500 /* Verify the requirements for executing code in protected
2501 mode. VT-x can't handle the CPU state right after a switch
2502 from real to protected mode. (all sorts of RPL & DPL assumptions). */
2503 if (pVCpu->hm.s.vmx.fWasInRealMode)
2504 {
2505 /** @todo If guest is in V86 mode, these checks should be different! */
2506 if ((pCtx->cs.Sel & X86_SEL_RPL) != (pCtx->ss.Sel & X86_SEL_RPL))
2507 {
2508 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxCheckBadRpl);
2509 return false;
2510 }
2511 if ( !hmR3IsCodeSelectorOkForVmx(&pCtx->cs, pCtx->ss.Attr.n.u2Dpl)
2512 || !hmR3IsDataSelectorOkForVmx(&pCtx->ds)
2513 || !hmR3IsDataSelectorOkForVmx(&pCtx->es)
2514 || !hmR3IsDataSelectorOkForVmx(&pCtx->fs)
2515 || !hmR3IsDataSelectorOkForVmx(&pCtx->gs)
2516 || !hmR3IsStackSelectorOkForVmx(&pCtx->ss))
2517 {
2518 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxCheckBadSel);
2519 return false;
2520 }
2521 }
2522 /* VT-x also chokes on invalid TR or LDTR selectors (minix). */
2523 if (pCtx->gdtr.cbGdt)
2524 {
2525 if (pCtx->tr.Sel > pCtx->gdtr.cbGdt)
2526 {
2527 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxCheckBadTr);
2528 return false;
2529 }
2530 else if (pCtx->ldtr.Sel > pCtx->gdtr.cbGdt)
2531 {
2532 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxCheckBadLdt);
2533 return false;
2534 }
2535 }
2536 STAM_COUNTER_INC(&pVCpu->hm.s.StatVmxCheckPmOk);
2537 }
2538 }
2539 else
2540 {
2541 if ( !CPUMIsGuestInLongModeEx(pCtx)
2542 && !pVM->hm.s.vmx.fUnrestrictedGuest)
2543 {
2544 if ( !pVM->hm.s.fNestedPaging /* Requires a fake PD for real *and* protected mode without paging - stored in the VMM device heap */
2545 || CPUMIsGuestInRealModeEx(pCtx)) /* Requires a fake TSS for real mode - stored in the VMM device heap */
2546 return false;
2547
2548 /* Too early for VT-x; Solaris guests will fail with a guru meditation otherwise; same for XP. */
2549 if (pCtx->idtr.pIdt == 0 || pCtx->idtr.cbIdt == 0 || pCtx->tr.Sel == 0)
2550 return false;
2551
2552 /* The guest is about to complete the switch to protected mode. Wait a bit longer. */
2553 /* Windows XP; switch to protected mode; all selectors are marked not present in the
2554 * hidden registers (possible recompiler bug; see load_seg_vm) */
2555 if (pCtx->cs.Attr.n.u1Present == 0)
2556 return false;
2557 if (pCtx->ss.Attr.n.u1Present == 0)
2558 return false;
2559
2560 /* Windows XP: possible same as above, but new recompiler requires new heuristics?
2561 VT-x doesn't seem to like something about the guest state and this stuff avoids it. */
2562 /** @todo This check is actually wrong, it doesn't take the direction of the
2563 * stack segment into account. But, it does the job for now. */
2564 if (pCtx->rsp >= pCtx->ss.u32Limit)
2565 return false;
2566 }
2567 }
2568 }
2569
2570 if (pVM->hm.s.vmx.fEnabled)
2571 {
2572 uint32_t mask;
2573
2574 /* if bit N is set in cr0_fixed0, then it must be set in the guest's cr0. */
2575 mask = (uint32_t)pVM->hm.s.vmx.Msrs.u64Cr0Fixed0;
2576 /* Note: We ignore the NE bit here on purpose; see vmmr0\hmr0.cpp for details. */
2577 mask &= ~X86_CR0_NE;
2578
2579 if (fSupportsRealMode)
2580 {
2581 /* Note: We ignore the PE & PG bits here on purpose; we emulate real and protected mode without paging. */
2582 mask &= ~(X86_CR0_PG|X86_CR0_PE);
2583 }
2584 else
2585 {
2586 /* We support protected mode without paging using identity mapping. */
2587 mask &= ~X86_CR0_PG;
2588 }
2589 if ((pCtx->cr0 & mask) != mask)
2590 return false;
2591
2592 /* if bit N is cleared in cr0_fixed1, then it must be zero in the guest's cr0. */
2593 mask = (uint32_t)~pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
2594 if ((pCtx->cr0 & mask) != 0)
2595 return false;
2596
2597 /* if bit N is set in cr4_fixed0, then it must be set in the guest's cr4. */
2598 mask = (uint32_t)pVM->hm.s.vmx.Msrs.u64Cr4Fixed0;
2599 mask &= ~X86_CR4_VMXE;
2600 if ((pCtx->cr4 & mask) != mask)
2601 return false;
2602
2603 /* if bit N is cleared in cr4_fixed1, then it must be zero in the guest's cr4. */
2604 mask = (uint32_t)~pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
2605 if ((pCtx->cr4 & mask) != 0)
2606 return false;
2607
2608 pVCpu->hm.s.fActive = true;
2609 return true;
2610 }
2611
2612 return false;
2613}
2614
2615
2616/**
2617 * Checks if we need to reschedule due to VMM device heap changes.
2618 *
2619 * @returns true if a reschedule is required, otherwise false.
2620 * @param pVM Pointer to the VM.
2621 * @param pCtx VM execution context.
2622 */
2623VMMR3_INT_DECL(bool) HMR3IsRescheduleRequired(PVM pVM, PCPUMCTX pCtx)
2624{
2625 /*
2626 * The VMM device heap is a requirement for emulating real-mode or protected-mode without paging
2627 * when the unrestricted guest execution feature is missing (VT-x only).
2628 */
2629 if ( pVM->hm.s.vmx.fEnabled
2630 && !pVM->hm.s.vmx.fUnrestrictedGuest
2631 && CPUMIsGuestInRealModeEx(pCtx)
2632 && !PDMVmmDevHeapIsEnabled(pVM))
2633 {
2634 return true;
2635 }
2636
2637 return false;
2638}
2639
2640
2641/**
2642 * Notification from EM about a rescheduling into hardware assisted execution
2643 * mode.
2644 *
2645 * @param pVCpu Pointer to the current VMCPU.
2646 */
2647VMMR3_INT_DECL(void) HMR3NotifyScheduled(PVMCPU pVCpu)
2648{
2649 pVCpu->hm.s.fContextUseFlags |= HM_CHANGED_ALL_GUEST;
2650}
2651
2652
2653/**
2654 * Notification from EM about returning from instruction emulation (REM / EM).
2655 *
2656 * @param pVCpu Pointer to the VMCPU.
2657 */
2658VMMR3_INT_DECL(void) HMR3NotifyEmulated(PVMCPU pVCpu)
2659{
2660 pVCpu->hm.s.fContextUseFlags |= HM_CHANGED_ALL_GUEST;
2661}
2662
2663
2664/**
2665 * Checks if we are currently using hardware accelerated raw mode.
2666 *
2667 * @returns true if hardware acceleration is being used, otherwise false.
2668 * @param pVCpu Pointer to the VMCPU.
2669 */
2670VMMR3_INT_DECL(bool) HMR3IsActive(PVMCPU pVCpu)
2671{
2672 return pVCpu->hm.s.fActive;
2673}
2674
2675
2676/**
2677 * External interface for querying whether hardware accelerated raw mode is
2678 * enabled.
2679 *
2680 * @returns true if VT-x or AMD-V is being used, otherwise false.
2681 * @param pUVM The user mode VM handle.
2682 * @sa HMIsEnabled, HMIsEnabledNotMacro.
2683 */
2684VMMR3DECL(bool) HMR3IsEnabled(PUVM pUVM)
2685{
2686 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
2687 PVM pVM = pUVM->pVM;
2688 VM_ASSERT_VALID_EXT_RETURN(pVM, false);
2689 return pVM->fHMEnabled; /* Don't use the macro as the GUI may query us very very early. */
2690}
2691
2692
2693/**
2694 * External interface for querying whether VT-x is being used.
2695 *
2696 * @returns true if VT-x is being used, otherwise false.
2697 * @param pUVM The user mode VM handle.
2698 * @sa HMR3IsSvmEnabled, HMIsEnabled
2699 */
2700VMMR3DECL(bool) HMR3IsVmxEnabled(PUVM pUVM)
2701{
2702 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
2703 PVM pVM = pUVM->pVM;
2704 VM_ASSERT_VALID_EXT_RETURN(pVM, false);
2705 return pVM->hm.s.vmx.fEnabled
2706 && pVM->hm.s.vmx.fSupported
2707 && pVM->fHMEnabled;
2708}
2709
2710
2711/**
2712 * External interface for querying whether AMD-V is being used.
2713 *
2714 * @returns true if VT-x is being used, otherwise false.
2715 * @param pUVM The user mode VM handle.
2716 * @sa HMR3IsVmxEnabled, HMIsEnabled
2717 */
2718VMMR3DECL(bool) HMR3IsSvmEnabled(PUVM pUVM)
2719{
2720 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
2721 PVM pVM = pUVM->pVM;
2722 VM_ASSERT_VALID_EXT_RETURN(pVM, false);
2723 return pVM->hm.s.svm.fEnabled
2724 && pVM->hm.s.svm.fSupported
2725 && pVM->fHMEnabled;
2726}
2727
2728
2729/**
2730 * Checks if we are currently using nested paging.
2731 *
2732 * @returns true if nested paging is being used, otherwise false.
2733 * @param pUVM The user mode VM handle.
2734 */
2735VMMR3DECL(bool) HMR3IsNestedPagingActive(PUVM pUVM)
2736{
2737 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
2738 PVM pVM = pUVM->pVM;
2739 VM_ASSERT_VALID_EXT_RETURN(pVM, false);
2740 return pVM->hm.s.fNestedPaging;
2741}
2742
2743
2744/**
2745 * Checks if we are currently using VPID in VT-x mode.
2746 *
2747 * @returns true if VPID is being used, otherwise false.
2748 * @param pUVM The user mode VM handle.
2749 */
2750VMMR3DECL(bool) HMR3IsVpidActive(PUVM pUVM)
2751{
2752 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
2753 PVM pVM = pUVM->pVM;
2754 VM_ASSERT_VALID_EXT_RETURN(pVM, false);
2755 return pVM->hm.s.vmx.fVpid;
2756}
2757
2758
2759/**
2760 * Checks if we are currently using VT-x unrestricted execution,
2761 * aka UX.
2762 *
2763 * @returns true if UX is being used, otherwise false.
2764 * @param pUVM The user mode VM handle.
2765 */
2766VMMR3DECL(bool) HMR3IsUXActive(PUVM pUVM)
2767{
2768 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
2769 PVM pVM = pUVM->pVM;
2770 VM_ASSERT_VALID_EXT_RETURN(pVM, false);
2771 return pVM->hm.s.vmx.fUnrestrictedGuest;
2772}
2773
2774
2775/**
2776 * Checks if internal events are pending. In that case we are not allowed to dispatch interrupts.
2777 *
2778 * @returns true if an internal event is pending, otherwise false.
2779 * @param pVM Pointer to the VM.
2780 */
2781VMMR3_INT_DECL(bool) HMR3IsEventPending(PVMCPU pVCpu)
2782{
2783 return HMIsEnabled(pVCpu->pVMR3) && pVCpu->hm.s.Event.fPending;
2784}
2785
2786
2787/**
2788 * Checks if the VMX-preemption timer is being used.
2789 *
2790 * @returns true if the VMX-preemption timer is being used, otherwise false.
2791 * @param pVM Pointer to the VM.
2792 */
2793VMMR3_INT_DECL(bool) HMR3IsVmxPreemptionTimerUsed(PVM pVM)
2794{
2795 return HMIsEnabled(pVM)
2796 && pVM->hm.s.vmx.fEnabled
2797 && pVM->hm.s.vmx.fUsePreemptTimer;
2798}
2799
2800
2801/**
2802 * Restart an I/O instruction that was refused in ring-0
2803 *
2804 * @returns Strict VBox status code. Informational status codes other than the one documented
2805 * here are to be treated as internal failure. Use IOM_SUCCESS() to check for success.
2806 * @retval VINF_SUCCESS Success.
2807 * @retval VINF_EM_FIRST-VINF_EM_LAST Success with some exceptions (see IOM_SUCCESS()), the
2808 * status code must be passed on to EM.
2809 * @retval VERR_NOT_FOUND if no pending I/O instruction.
2810 *
2811 * @param pVM Pointer to the VM.
2812 * @param pVCpu Pointer to the VMCPU.
2813 * @param pCtx Pointer to the guest CPU context.
2814 */
2815VMMR3_INT_DECL(VBOXSTRICTRC) HMR3RestartPendingIOInstr(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
2816{
2817 HMPENDINGIO enmType = pVCpu->hm.s.PendingIO.enmType;
2818
2819 pVCpu->hm.s.PendingIO.enmType = HMPENDINGIO_INVALID;
2820
2821 if ( pVCpu->hm.s.PendingIO.GCPtrRip != pCtx->rip
2822 || enmType == HMPENDINGIO_INVALID)
2823 return VERR_NOT_FOUND;
2824
2825 VBOXSTRICTRC rcStrict;
2826 switch (enmType)
2827 {
2828 case HMPENDINGIO_PORT_READ:
2829 {
2830 uint32_t uAndVal = pVCpu->hm.s.PendingIO.s.Port.uAndVal;
2831 uint32_t u32Val = 0;
2832
2833 rcStrict = IOMIOPortRead(pVM, pVCpu, pVCpu->hm.s.PendingIO.s.Port.uPort,
2834 &u32Val,
2835 pVCpu->hm.s.PendingIO.s.Port.cbSize);
2836 if (IOM_SUCCESS(rcStrict))
2837 {
2838 /* Write back to the EAX register. */
2839 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Val & uAndVal);
2840 pCtx->rip = pVCpu->hm.s.PendingIO.GCPtrRipNext;
2841 }
2842 break;
2843 }
2844
2845 case HMPENDINGIO_PORT_WRITE:
2846 rcStrict = IOMIOPortWrite(pVM, pVCpu, pVCpu->hm.s.PendingIO.s.Port.uPort,
2847 pCtx->eax & pVCpu->hm.s.PendingIO.s.Port.uAndVal,
2848 pVCpu->hm.s.PendingIO.s.Port.cbSize);
2849 if (IOM_SUCCESS(rcStrict))
2850 pCtx->rip = pVCpu->hm.s.PendingIO.GCPtrRipNext;
2851 break;
2852
2853 default:
2854 AssertLogRelFailedReturn(VERR_HM_UNKNOWN_IO_INSTRUCTION);
2855 }
2856
2857 if (IOM_SUCCESS(rcStrict))
2858 {
2859 /*
2860 * Check for I/O breakpoints.
2861 */
2862 uint32_t const uDr7 = pCtx->dr[7];
2863 if ( ( (uDr7 & X86_DR7_ENABLED_MASK)
2864 && X86_DR7_ANY_RW_IO(uDr7)
2865 && (pCtx->cr4 & X86_CR4_DE))
2866 || DBGFBpIsHwIoArmed(pVM))
2867 {
2868 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, pVCpu->hm.s.PendingIO.s.Port.uPort,
2869 pVCpu->hm.s.PendingIO.s.Port.cbSize);
2870 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
2871 rcStrict2 = TRPMAssertTrap(pVCpu, X86_XCPT_DB, TRPM_TRAP);
2872 /* rcStrict is VINF_SUCCESS or in [VINF_EM_FIRST..VINF_EM_LAST]. */
2873 else if (rcStrict2 != VINF_SUCCESS && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
2874 rcStrict = rcStrict2;
2875 }
2876 }
2877 return rcStrict;
2878}
2879
2880
2881/**
2882 * Check fatal VT-x/AMD-V error and produce some meaningful
2883 * log release message.
2884 *
2885 * @param pVM Pointer to the VM.
2886 * @param iStatusCode VBox status code.
2887 */
2888VMMR3_INT_DECL(void) HMR3CheckError(PVM pVM, int iStatusCode)
2889{
2890 for (VMCPUID i = 0; i < pVM->cCpus; i++)
2891 {
2892 PVMCPU pVCpu = &pVM->aCpus[i];
2893 switch (iStatusCode)
2894 {
2895 case VERR_VMX_INVALID_VMCS_FIELD:
2896 break;
2897
2898 case VERR_VMX_INVALID_VMCS_PTR:
2899 LogRel(("HM: VERR_VMX_INVALID_VMCS_PTR:\n"));
2900 LogRel(("HM: CPU[%u] Current pointer %#RGp vs %#RGp\n", i, pVCpu->hm.s.vmx.LastError.u64VMCSPhys,
2901 pVCpu->hm.s.vmx.HCPhysVmcs));
2902 LogRel(("HM: CPU[%u] Current VMCS version %#x\n", i, pVCpu->hm.s.vmx.LastError.u32VMCSRevision));
2903 LogRel(("HM: CPU[%u] Entered Host Cpu %u\n", i, pVCpu->hm.s.vmx.LastError.idEnteredCpu));
2904 LogRel(("HM: CPU[%u] Current Host Cpu %u\n", i, pVCpu->hm.s.vmx.LastError.idCurrentCpu));
2905 break;
2906
2907 case VERR_VMX_UNABLE_TO_START_VM:
2908 LogRel(("HM: VERR_VMX_UNABLE_TO_START_VM:\n"));
2909 LogRel(("HM: CPU[%u] Instruction error %#x\n", i, pVCpu->hm.s.vmx.LastError.u32InstrError));
2910 LogRel(("HM: CPU[%u] Exit reason %#x\n", i, pVCpu->hm.s.vmx.LastError.u32ExitReason));
2911
2912 if ( pVM->aCpus[i].hm.s.vmx.LastError.u32InstrError == VMX_ERROR_VMLAUCH_NON_CLEAR_VMCS
2913 || pVM->aCpus[i].hm.s.vmx.LastError.u32InstrError == VMX_ERROR_VMRESUME_NON_LAUNCHED_VMCS)
2914 {
2915 LogRel(("HM: CPU[%u] Entered Host Cpu %u\n", i, pVCpu->hm.s.vmx.LastError.idEnteredCpu));
2916 LogRel(("HM: CPU[%u] Current Host Cpu %u\n", i, pVCpu->hm.s.vmx.LastError.idCurrentCpu));
2917 }
2918 else if (pVM->aCpus[i].hm.s.vmx.LastError.u32InstrError == VMX_ERROR_VMENTRY_INVALID_CONTROL_FIELDS)
2919 {
2920 LogRel(("HM: CPU[%u] PinCtls %#RX32\n", i, pVCpu->hm.s.vmx.u32PinCtls));
2921 LogRel(("HM: CPU[%u] ProcCtls %#RX32\n", i, pVCpu->hm.s.vmx.u32ProcCtls));
2922 LogRel(("HM: CPU[%u] ProcCtls2 %#RX32\n", i, pVCpu->hm.s.vmx.u32ProcCtls2));
2923 LogRel(("HM: CPU[%u] EntryCtls %#RX32\n", i, pVCpu->hm.s.vmx.u32EntryCtls));
2924 LogRel(("HM: CPU[%u] ExitCtls %#RX32\n", i, pVCpu->hm.s.vmx.u32ExitCtls));
2925 LogRel(("HM: CPU[%u] MSRBitmapPhys %#RHp\n", i, pVCpu->hm.s.vmx.HCPhysMsrBitmap));
2926#ifdef VBOX_WITH_AUTO_MSR_LOAD_RESTORE
2927 LogRel(("HM: CPU[%u] GuestMSRPhys %#RHp\n", i, pVCpu->hm.s.vmx.HCPhysGuestMsr));
2928 LogRel(("HM: CPU[%u] HostMsrPhys %#RHp\n", i, pVCpu->hm.s.vmx.HCPhysHostMsr));
2929 LogRel(("HM: CPU[%u] cGuestMSRs %u\n", i, pVCpu->hm.s.vmx.cGuestMsrs));
2930#endif
2931 }
2932 /** @todo Log VM-entry event injection control fields
2933 * VMX_VMCS_CTRL_ENTRY_IRQ_INFO, VMX_VMCS_CTRL_ENTRY_EXCEPTION_ERRCODE
2934 * and VMX_VMCS_CTRL_ENTRY_INSTR_LENGTH from the VMCS. */
2935 break;
2936
2937 case VERR_VMX_INVALID_VMXON_PTR:
2938 break;
2939
2940 case VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO:
2941 case VERR_VMX_INVALID_GUEST_STATE:
2942 case VERR_VMX_UNEXPECTED_EXIT_CODE:
2943 case VERR_SVM_UNKNOWN_EXIT:
2944 case VERR_SVM_UNEXPECTED_EXIT:
2945 case VERR_SVM_UNEXPECTED_PATCH_TYPE:
2946 case VERR_SVM_UNEXPECTED_XCPT_EXIT:
2947 {
2948 LogRel(("HM: CPU[%u] HM error %#x (%u)\n", i, pVCpu->hm.s.u32HMError, pVCpu->hm.s.u32HMError));
2949 break;
2950 }
2951 }
2952 }
2953
2954 if (iStatusCode == VERR_VMX_UNABLE_TO_START_VM)
2955 {
2956 LogRel(("VERR_VMX_UNABLE_TO_START_VM: VM-entry allowed %#RX32\n", pVM->hm.s.vmx.Msrs.VmxEntry.n.allowed1));
2957 LogRel(("VERR_VMX_UNABLE_TO_START_VM: VM-entry disallowed %#RX32\n", pVM->hm.s.vmx.Msrs.VmxEntry.n.disallowed0));
2958 }
2959}
2960
2961
2962/**
2963 * Execute state save operation.
2964 *
2965 * @returns VBox status code.
2966 * @param pVM Pointer to the VM.
2967 * @param pSSM SSM operation handle.
2968 */
2969static DECLCALLBACK(int) hmR3Save(PVM pVM, PSSMHANDLE pSSM)
2970{
2971 int rc;
2972
2973 Log(("hmR3Save:\n"));
2974
2975 for (VMCPUID i = 0; i < pVM->cCpus; i++)
2976 {
2977 /*
2978 * Save the basic bits - fortunately all the other things can be resynced on load.
2979 */
2980 rc = SSMR3PutU32(pSSM, pVM->aCpus[i].hm.s.Event.fPending);
2981 AssertRCReturn(rc, rc);
2982 rc = SSMR3PutU32(pSSM, pVM->aCpus[i].hm.s.Event.u32ErrCode);
2983 AssertRCReturn(rc, rc);
2984 rc = SSMR3PutU64(pSSM, pVM->aCpus[i].hm.s.Event.u64IntrInfo);
2985 AssertRCReturn(rc, rc);
2986
2987 /** @todo We only need to save pVM->aCpus[i].hm.s.vmx.fWasInRealMode and
2988 * perhaps not even that (the initial value of @c true is safe. */
2989 uint32_t u32Dummy = PGMMODE_REAL;
2990 rc = SSMR3PutU32(pSSM, u32Dummy);
2991 AssertRCReturn(rc, rc);
2992 rc = SSMR3PutU32(pSSM, u32Dummy);
2993 AssertRCReturn(rc, rc);
2994 rc = SSMR3PutU32(pSSM, u32Dummy);
2995 AssertRCReturn(rc, rc);
2996 }
2997
2998#ifdef VBOX_HM_WITH_GUEST_PATCHING
2999 rc = SSMR3PutGCPtr(pSSM, pVM->hm.s.pGuestPatchMem);
3000 AssertRCReturn(rc, rc);
3001 rc = SSMR3PutGCPtr(pSSM, pVM->hm.s.pFreeGuestPatchMem);
3002 AssertRCReturn(rc, rc);
3003 rc = SSMR3PutU32(pSSM, pVM->hm.s.cbGuestPatchMem);
3004 AssertRCReturn(rc, rc);
3005
3006 /* Store all the guest patch records too. */
3007 rc = SSMR3PutU32(pSSM, pVM->hm.s.cPatches);
3008 AssertRCReturn(rc, rc);
3009
3010 for (unsigned i = 0; i < pVM->hm.s.cPatches; i++)
3011 {
3012 PHMTPRPATCH pPatch = &pVM->hm.s.aPatches[i];
3013
3014 rc = SSMR3PutU32(pSSM, pPatch->Core.Key);
3015 AssertRCReturn(rc, rc);
3016
3017 rc = SSMR3PutMem(pSSM, pPatch->aOpcode, sizeof(pPatch->aOpcode));
3018 AssertRCReturn(rc, rc);
3019
3020 rc = SSMR3PutU32(pSSM, pPatch->cbOp);
3021 AssertRCReturn(rc, rc);
3022
3023 rc = SSMR3PutMem(pSSM, pPatch->aNewOpcode, sizeof(pPatch->aNewOpcode));
3024 AssertRCReturn(rc, rc);
3025
3026 rc = SSMR3PutU32(pSSM, pPatch->cbNewOp);
3027 AssertRCReturn(rc, rc);
3028
3029 AssertCompileSize(HMTPRINSTR, 4);
3030 rc = SSMR3PutU32(pSSM, (uint32_t)pPatch->enmType);
3031 AssertRCReturn(rc, rc);
3032
3033 rc = SSMR3PutU32(pSSM, pPatch->uSrcOperand);
3034 AssertRCReturn(rc, rc);
3035
3036 rc = SSMR3PutU32(pSSM, pPatch->uDstOperand);
3037 AssertRCReturn(rc, rc);
3038
3039 rc = SSMR3PutU32(pSSM, pPatch->pJumpTarget);
3040 AssertRCReturn(rc, rc);
3041
3042 rc = SSMR3PutU32(pSSM, pPatch->cFaults);
3043 AssertRCReturn(rc, rc);
3044 }
3045#endif
3046 return VINF_SUCCESS;
3047}
3048
3049
3050/**
3051 * Execute state load operation.
3052 *
3053 * @returns VBox status code.
3054 * @param pVM Pointer to the VM.
3055 * @param pSSM SSM operation handle.
3056 * @param uVersion Data layout version.
3057 * @param uPass The data pass.
3058 */
3059static DECLCALLBACK(int) hmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
3060{
3061 int rc;
3062
3063 Log(("hmR3Load:\n"));
3064 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
3065
3066 /*
3067 * Validate version.
3068 */
3069 if ( uVersion != HM_SSM_VERSION
3070 && uVersion != HM_SSM_VERSION_NO_PATCHING
3071 && uVersion != HM_SSM_VERSION_2_0_X)
3072 {
3073 AssertMsgFailed(("hmR3Load: Invalid version uVersion=%d!\n", uVersion));
3074 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
3075 }
3076 for (VMCPUID i = 0; i < pVM->cCpus; i++)
3077 {
3078 rc = SSMR3GetU32(pSSM, &pVM->aCpus[i].hm.s.Event.fPending);
3079 AssertRCReturn(rc, rc);
3080 rc = SSMR3GetU32(pSSM, &pVM->aCpus[i].hm.s.Event.u32ErrCode);
3081 AssertRCReturn(rc, rc);
3082 rc = SSMR3GetU64(pSSM, &pVM->aCpus[i].hm.s.Event.u64IntrInfo);
3083 AssertRCReturn(rc, rc);
3084
3085 if (uVersion >= HM_SSM_VERSION_NO_PATCHING)
3086 {
3087 uint32_t val;
3088 /** @todo See note in hmR3Save(). */
3089 rc = SSMR3GetU32(pSSM, &val);
3090 AssertRCReturn(rc, rc);
3091 rc = SSMR3GetU32(pSSM, &val);
3092 AssertRCReturn(rc, rc);
3093 rc = SSMR3GetU32(pSSM, &val);
3094 AssertRCReturn(rc, rc);
3095 }
3096 }
3097#ifdef VBOX_HM_WITH_GUEST_PATCHING
3098 if (uVersion > HM_SSM_VERSION_NO_PATCHING)
3099 {
3100 rc = SSMR3GetGCPtr(pSSM, &pVM->hm.s.pGuestPatchMem);
3101 AssertRCReturn(rc, rc);
3102 rc = SSMR3GetGCPtr(pSSM, &pVM->hm.s.pFreeGuestPatchMem);
3103 AssertRCReturn(rc, rc);
3104 rc = SSMR3GetU32(pSSM, &pVM->hm.s.cbGuestPatchMem);
3105 AssertRCReturn(rc, rc);
3106
3107 /* Fetch all TPR patch records. */
3108 rc = SSMR3GetU32(pSSM, &pVM->hm.s.cPatches);
3109 AssertRCReturn(rc, rc);
3110
3111 for (unsigned i = 0; i < pVM->hm.s.cPatches; i++)
3112 {
3113 PHMTPRPATCH pPatch = &pVM->hm.s.aPatches[i];
3114
3115 rc = SSMR3GetU32(pSSM, &pPatch->Core.Key);
3116 AssertRCReturn(rc, rc);
3117
3118 rc = SSMR3GetMem(pSSM, pPatch->aOpcode, sizeof(pPatch->aOpcode));
3119 AssertRCReturn(rc, rc);
3120
3121 rc = SSMR3GetU32(pSSM, &pPatch->cbOp);
3122 AssertRCReturn(rc, rc);
3123
3124 rc = SSMR3GetMem(pSSM, pPatch->aNewOpcode, sizeof(pPatch->aNewOpcode));
3125 AssertRCReturn(rc, rc);
3126
3127 rc = SSMR3GetU32(pSSM, &pPatch->cbNewOp);
3128 AssertRCReturn(rc, rc);
3129
3130 rc = SSMR3GetU32(pSSM, (uint32_t *)&pPatch->enmType);
3131 AssertRCReturn(rc, rc);
3132
3133 if (pPatch->enmType == HMTPRINSTR_JUMP_REPLACEMENT)
3134 pVM->hm.s.fTPRPatchingActive = true;
3135
3136 Assert(pPatch->enmType == HMTPRINSTR_JUMP_REPLACEMENT || pVM->hm.s.fTPRPatchingActive == false);
3137
3138 rc = SSMR3GetU32(pSSM, &pPatch->uSrcOperand);
3139 AssertRCReturn(rc, rc);
3140
3141 rc = SSMR3GetU32(pSSM, &pPatch->uDstOperand);
3142 AssertRCReturn(rc, rc);
3143
3144 rc = SSMR3GetU32(pSSM, &pPatch->cFaults);
3145 AssertRCReturn(rc, rc);
3146
3147 rc = SSMR3GetU32(pSSM, &pPatch->pJumpTarget);
3148 AssertRCReturn(rc, rc);
3149
3150 Log(("hmR3Load: patch %d\n", i));
3151 Log(("Key = %x\n", pPatch->Core.Key));
3152 Log(("cbOp = %d\n", pPatch->cbOp));
3153 Log(("cbNewOp = %d\n", pPatch->cbNewOp));
3154 Log(("type = %d\n", pPatch->enmType));
3155 Log(("srcop = %d\n", pPatch->uSrcOperand));
3156 Log(("dstop = %d\n", pPatch->uDstOperand));
3157 Log(("cFaults = %d\n", pPatch->cFaults));
3158 Log(("target = %x\n", pPatch->pJumpTarget));
3159 rc = RTAvloU32Insert(&pVM->hm.s.PatchTree, &pPatch->Core);
3160 AssertRC(rc);
3161 }
3162 }
3163#endif
3164
3165 return VINF_SUCCESS;
3166}
3167
Note: See TracBrowser for help on using the repository browser.

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