VirtualBox

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

Last change on this file since 45894 was 45879, checked in by vboxsync, 12 years ago

VMM: Log spacing/indent inconsistencies.

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

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