VirtualBox

source: vbox/trunk/src/VBox/VMM/HWACCM.cpp@ 15462

Last change on this file since 15462 was 15439, checked in by vboxsync, 16 years ago

Enable 64 bits guest support on 32 bits hosts. Only use rem64 if the guest OS type is 64 bits.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 70.6 KB
Line 
1/* $Id: HWACCM.cpp 15439 2008-12-13 12:48:22Z vboxsync $ */
2/** @file
3 * HWACCM - Intel/AMD VM Hardware Support Manager
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22/*******************************************************************************
23* Header Files *
24*******************************************************************************/
25#define LOG_GROUP LOG_GROUP_HWACCM
26#include <VBox/cpum.h>
27#include <VBox/stam.h>
28#include <VBox/mm.h>
29#include <VBox/pdm.h>
30#include <VBox/pgm.h>
31#include <VBox/trpm.h>
32#include <VBox/dbgf.h>
33#include <VBox/patm.h>
34#include <VBox/csam.h>
35#include <VBox/selm.h>
36#include <VBox/rem.h>
37#include <VBox/hwacc_vmx.h>
38#include <VBox/hwacc_svm.h>
39#include "HWACCMInternal.h"
40#include <VBox/vm.h>
41#include <VBox/err.h>
42#include <VBox/param.h>
43
44#include <iprt/assert.h>
45#include <VBox/log.h>
46#include <iprt/asm.h>
47#include <iprt/string.h>
48#include <iprt/thread.h>
49
50/*******************************************************************************
51* Global Variables *
52*******************************************************************************/
53#ifdef VBOX_WITH_STATISTICS
54# define EXIT_REASON(def, val, str) #def " - " #val " - " str
55# define EXIT_REASON_NIL() NULL
56/** Exit reason descriptions for VT-x, used to describe statistics. */
57static const char * const g_apszVTxExitReasons[MAX_EXITREASON_STAT] =
58{
59 EXIT_REASON(VMX_EXIT_EXCEPTION , 0, "Exception or non-maskable interrupt (NMI)."),
60 EXIT_REASON(VMX_EXIT_EXTERNAL_IRQ , 1, "External interrupt."),
61 EXIT_REASON(VMX_EXIT_TRIPLE_FAULT , 2, "Triple fault."),
62 EXIT_REASON(VMX_EXIT_INIT_SIGNAL , 3, "INIT signal."),
63 EXIT_REASON(VMX_EXIT_SIPI , 4, "Start-up IPI (SIPI)."),
64 EXIT_REASON(VMX_EXIT_IO_SMI_IRQ , 5, "I/O system-management interrupt (SMI)."),
65 EXIT_REASON(VMX_EXIT_SMI_IRQ , 6, "Other SMI."),
66 EXIT_REASON(VMX_EXIT_IRQ_WINDOW , 7, "Interrupt window."),
67 EXIT_REASON_NIL(),
68 EXIT_REASON(VMX_EXIT_TASK_SWITCH , 9, "Task switch."),
69 EXIT_REASON(VMX_EXIT_CPUID , 10, "Guest software attempted to execute CPUID."),
70 EXIT_REASON_NIL(),
71 EXIT_REASON(VMX_EXIT_HLT , 12, "Guest software attempted to execute HLT."),
72 EXIT_REASON(VMX_EXIT_INVD , 13, "Guest software attempted to execute INVD."),
73 EXIT_REASON(VMX_EXIT_INVPG , 14, "Guest software attempted to execute INVPG."),
74 EXIT_REASON(VMX_EXIT_RDPMC , 15, "Guest software attempted to execute RDPMC."),
75 EXIT_REASON(VMX_EXIT_RDTSC , 16, "Guest software attempted to execute RDTSC."),
76 EXIT_REASON(VMX_EXIT_RSM , 17, "Guest software attempted to execute RSM in SMM."),
77 EXIT_REASON(VMX_EXIT_VMCALL , 18, "Guest software executed VMCALL."),
78 EXIT_REASON(VMX_EXIT_VMCLEAR , 19, "Guest software executed VMCLEAR."),
79 EXIT_REASON(VMX_EXIT_VMLAUNCH , 20, "Guest software executed VMLAUNCH."),
80 EXIT_REASON(VMX_EXIT_VMPTRLD , 21, "Guest software executed VMPTRLD."),
81 EXIT_REASON(VMX_EXIT_VMPTRST , 22, "Guest software executed VMPTRST."),
82 EXIT_REASON(VMX_EXIT_VMREAD , 23, "Guest software executed VMREAD."),
83 EXIT_REASON(VMX_EXIT_VMRESUME , 24, "Guest software executed VMRESUME."),
84 EXIT_REASON(VMX_EXIT_VMWRITE , 25, "Guest software executed VMWRITE."),
85 EXIT_REASON(VMX_EXIT_VMXOFF , 26, "Guest software executed VMXOFF."),
86 EXIT_REASON(VMX_EXIT_VMXON , 27, "Guest software executed VMXON."),
87 EXIT_REASON(VMX_EXIT_CRX_MOVE , 28, "Control-register accesses."),
88 EXIT_REASON(VMX_EXIT_DRX_MOVE , 29, "Debug-register accesses."),
89 EXIT_REASON(VMX_EXIT_PORT_IO , 30, "I/O instruction."),
90 EXIT_REASON(VMX_EXIT_RDMSR , 31, "RDMSR. Guest software attempted to execute RDMSR."),
91 EXIT_REASON(VMX_EXIT_WRMSR , 32, "WRMSR. Guest software attempted to execute WRMSR."),
92 EXIT_REASON(VMX_EXIT_ERR_INVALID_GUEST_STATE, 33, "VM-entry failure due to invalid guest state."),
93 EXIT_REASON(VMX_EXIT_ERR_MSR_LOAD , 34, "VM-entry failure due to MSR loading."),
94 EXIT_REASON_NIL(),
95 EXIT_REASON(VMX_EXIT_MWAIT , 36, "Guest software executed MWAIT."),
96 EXIT_REASON_NIL(),
97 EXIT_REASON_NIL(),
98 EXIT_REASON(VMX_EXIT_MONITOR , 39, "Guest software attempted to execute MONITOR."),
99 EXIT_REASON(VMX_EXIT_PAUSE , 40, "Guest software attempted to execute PAUSE."),
100 EXIT_REASON(VMX_EXIT_ERR_MACHINE_CHECK , 41, "VM-entry failure due to machine-check."),
101 EXIT_REASON_NIL(),
102 EXIT_REASON(VMX_EXIT_TPR , 43, "TPR below threshold. Guest software executed MOV to CR8."),
103 EXIT_REASON(VMX_EXIT_APIC_ACCESS , 44, "APIC access. Guest software attempted to access memory at a physical address on the APIC-access page."),
104 EXIT_REASON_NIL(),
105 EXIT_REASON(VMX_EXIT_XDTR_ACCESS , 46, "Access to GDTR or IDTR. Guest software attempted to execute LGDT, LIDT, SGDT, or SIDT."),
106 EXIT_REASON(VMX_EXIT_TR_ACCESS , 47, "Access to LDTR or TR. Guest software attempted to execute LLDT, LTR, SLDT, or STR."),
107 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."),
108 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."),
109 EXIT_REASON(VMX_EXIT_INVEPT , 50, "INVEPT. Guest software attempted to execute INVEPT."),
110 EXIT_REASON_NIL(),
111 EXIT_REASON(VMX_EXIT_PREEMPTION_TIMER , 52, "VMX-preemption timer expired. The preemption timer counted down to zero."),
112 EXIT_REASON(VMX_EXIT_INVVPID , 53, "INVVPID. Guest software attempted to execute INVVPID."),
113 EXIT_REASON(VMX_EXIT_WBINVD , 54, "WBINVD. Guest software attempted to execute WBINVD."),
114 EXIT_REASON(VMX_EXIT_XSETBV , 55, "XSETBV. Guest software attempted to execute XSETBV."),
115 EXIT_REASON_NIL()
116};
117/** Exit reason descriptions for AMD-V, used to describe statistics. */
118static const char * const g_apszAmdVExitReasons[MAX_EXITREASON_STAT] =
119{
120 /** @todo fill in these. */
121 EXIT_REASON_NIL()
122};
123# undef EXIT_REASON
124# undef EXIT_REASON_NIL
125#endif /* VBOX_WITH_STATISTICS */
126
127/*******************************************************************************
128* Internal Functions *
129*******************************************************************************/
130static DECLCALLBACK(int) hwaccmR3Save(PVM pVM, PSSMHANDLE pSSM);
131static DECLCALLBACK(int) hwaccmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version);
132
133
134/**
135 * Initializes the HWACCM.
136 *
137 * @returns VBox status code.
138 * @param pVM The VM to operate on.
139 */
140VMMR3DECL(int) HWACCMR3Init(PVM pVM)
141{
142 LogFlow(("HWACCMR3Init\n"));
143
144 /*
145 * Assert alignment and sizes.
146 */
147 AssertRelease(!(RT_OFFSETOF(VM, hwaccm.s) & 31));
148 AssertRelease(sizeof(pVM->hwaccm.s) <= sizeof(pVM->hwaccm.padding));
149
150 /* Some structure checks. */
151 AssertReleaseMsg(RT_OFFSETOF(SVM_VMCB, u8Reserved3) == 0xC0, ("u8Reserved3 offset = %x\n", RT_OFFSETOF(SVM_VMCB, u8Reserved3)));
152 AssertReleaseMsg(RT_OFFSETOF(SVM_VMCB, ctrl.EventInject) == 0xA8, ("ctrl.EventInject offset = %x\n", RT_OFFSETOF(SVM_VMCB, ctrl.EventInject)));
153 AssertReleaseMsg(RT_OFFSETOF(SVM_VMCB, ctrl.ExitIntInfo) == 0x88, ("ctrl.ExitIntInfo offset = %x\n", RT_OFFSETOF(SVM_VMCB, ctrl.ExitIntInfo)));
154 AssertReleaseMsg(RT_OFFSETOF(SVM_VMCB, ctrl.TLBCtrl) == 0x58, ("ctrl.TLBCtrl offset = %x\n", RT_OFFSETOF(SVM_VMCB, ctrl.TLBCtrl)));
155
156 AssertReleaseMsg(RT_OFFSETOF(SVM_VMCB, guest) == 0x400, ("guest offset = %x\n", RT_OFFSETOF(SVM_VMCB, guest)));
157 AssertReleaseMsg(RT_OFFSETOF(SVM_VMCB, guest.u8Reserved4) == 0x4A0, ("guest.u8Reserved4 offset = %x\n", RT_OFFSETOF(SVM_VMCB, guest.u8Reserved4)));
158 AssertReleaseMsg(RT_OFFSETOF(SVM_VMCB, guest.u8Reserved6) == 0x4D8, ("guest.u8Reserved6 offset = %x\n", RT_OFFSETOF(SVM_VMCB, guest.u8Reserved6)));
159 AssertReleaseMsg(RT_OFFSETOF(SVM_VMCB, guest.u8Reserved7) == 0x580, ("guest.u8Reserved7 offset = %x\n", RT_OFFSETOF(SVM_VMCB, guest.u8Reserved7)));
160 AssertReleaseMsg(RT_OFFSETOF(SVM_VMCB, guest.u8Reserved9) == 0x648, ("guest.u8Reserved9 offset = %x\n", RT_OFFSETOF(SVM_VMCB, guest.u8Reserved9)));
161 AssertReleaseMsg(RT_OFFSETOF(SVM_VMCB, u8Reserved10) == 0x698, ("u8Reserved3 offset = %x\n", RT_OFFSETOF(SVM_VMCB, u8Reserved10)));
162 AssertReleaseMsg(sizeof(SVM_VMCB) == 0x1000, ("SVM_VMCB size = %x\n", sizeof(SVM_VMCB)));
163
164
165 /*
166 * Register the saved state data unit.
167 */
168 int rc = SSMR3RegisterInternal(pVM, "HWACCM", 0, HWACCM_SSM_VERSION, sizeof(HWACCM),
169 NULL, hwaccmR3Save, NULL,
170 NULL, hwaccmR3Load, NULL);
171 if (RT_FAILURE(rc))
172 return rc;
173
174 /* Misc initialisation. */
175 pVM->hwaccm.s.vmx.fSupported = false;
176 pVM->hwaccm.s.svm.fSupported = false;
177 pVM->hwaccm.s.vmx.fEnabled = false;
178 pVM->hwaccm.s.svm.fEnabled = false;
179
180 pVM->hwaccm.s.fActive = false;
181 pVM->hwaccm.s.fNestedPaging = false;
182
183 /* Disabled by default. */
184 pVM->fHWACCMEnabled = false;
185
186 /*
187 * Check CFGM options.
188 */
189 PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
190 PCFGMNODE pHWVirtExt = CFGMR3GetChild(pRoot, "HWVirtExt/");
191 /* Nested paging: disabled by default. */
192 rc = CFGMR3QueryBoolDef(pRoot, "EnableNestedPaging", &pVM->hwaccm.s.fAllowNestedPaging, false);
193 AssertRC(rc);
194
195 /* VT-x VPID: disabled by default. */
196 rc = CFGMR3QueryBoolDef(pRoot, "EnableVPID", &pVM->hwaccm.s.vmx.fAllowVPID, false);
197 AssertRC(rc);
198
199 /* HWACCM support must be explicitely enabled in the configuration file. */
200 rc = CFGMR3QueryBoolDef(pHWVirtExt, "Enabled", &pVM->hwaccm.s.fAllowed, false);
201 AssertRC(rc);
202
203#ifdef RT_OS_DARWIN
204 if (VMMIsHwVirtExtForced(pVM) != pVM->hwaccm.s.fAllowed)
205#else
206 if (VMMIsHwVirtExtForced(pVM) && !pVM->hwaccm.s.fAllowed)
207#endif
208 {
209 AssertLogRelMsgFailed(("VMMIsHwVirtExtForced=%RTbool fAllowed=%RTbool\n",
210 VMMIsHwVirtExtForced(pVM), pVM->hwaccm.s.fAllowed));
211 return VERR_HWACCM_CONFIG_MISMATCH;
212 }
213
214 if (VMMIsHwVirtExtForced(pVM))
215 pVM->fHWACCMEnabled = true;
216
217#if HC_ARCH_BITS == 32
218 /* 64-bit mode is configurable and it depends on both the kernel mode and VT-x.
219 * (To use the default, don't set 64bitEnabled in CFGM.) */
220 rc = CFGMR3QueryBoolDef(pHWVirtExt, "64bitEnabled", &pVM->hwaccm.s.fAllow64BitGuests, false);
221 AssertLogRelRCReturn(rc, rc);
222 if (pVM->hwaccm.s.fAllow64BitGuests)
223 {
224# ifdef RT_OS_DARWIN
225 if (!VMMIsHwVirtExtForced(pVM))
226# else
227 if (!pVM->hwaccm.s.fAllowed)
228# endif
229 return VM_SET_ERROR(pVM, VERR_INVALID_PARAMETER, "64-bit guest support was requested without also enabling VT-x.");
230 }
231#else
232 /* We always allow 64 bits guests on 64 bits hosts. */
233 pVM->hwaccm.s.fAllow64BitGuests = true;
234#endif
235
236 return VINF_SUCCESS;
237}
238
239/**
240 * Initializes the per-VCPU HWACCM.
241 *
242 * @returns VBox status code.
243 * @param pVM The VM to operate on.
244 */
245VMMR3DECL(int) HWACCMR3InitCPU(PVM pVM)
246{
247 LogFlow(("HWACCMR3InitCPU\n"));
248
249#ifdef VBOX_WITH_STATISTICS
250 /*
251 * Statistics.
252 */
253 for (unsigned i=0;i<pVM->cCPUs;i++)
254 {
255 PVMCPU pVCpu = &pVM->aCpus[i];
256 int rc;
257
258 rc = STAMR3RegisterF(pVM, &pVCpu->hwaccm.s.StatEntry, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, "Profiling of VMXR0RunGuestCode entry",
259 "/PROF/HWACCM/CPU%d/SwitchToGC", i);
260 AssertRC(rc);
261 rc = STAMR3RegisterF(pVM, &pVCpu->hwaccm.s.StatExit1, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, "Profiling of VMXR0RunGuestCode exit part 1",
262 "/PROF/HWACCM/CPU%d/SwitchFromGC_1", i);
263 AssertRC(rc);
264 rc = STAMR3RegisterF(pVM, &pVCpu->hwaccm.s.StatExit2, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, "Profiling of VMXR0RunGuestCode exit part 2",
265 "/PROF/HWACCM/CPU%d/SwitchFromGC_2", i);
266 AssertRC(rc);
267# if 1 /* temporary for tracking down darwin holdup. */
268 rc = STAMR3RegisterF(pVM, &pVCpu->hwaccm.s.StatExit2Sub1, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, "Temporary - I/O",
269 "/PROF/HWACCM/CPU%d/SwitchFromGC_2/Sub1", i);
270 AssertRC(rc);
271 rc = STAMR3RegisterF(pVM, &pVCpu->hwaccm.s.StatExit2Sub2, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, "Temporary - CRx RWs",
272 "/PROF/HWACCM/CPU%d/SwitchFromGC_2/Sub2", i);
273 AssertRC(rc);
274 rc = STAMR3RegisterF(pVM, &pVCpu->hwaccm.s.StatExit2Sub3, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, "Temporary - Exceptions",
275 "/PROF/HWACCM/CPU%d/SwitchFromGC_2/Sub3", i);
276 AssertRC(rc);
277# endif
278 rc = STAMR3RegisterF(pVM, &pVCpu->hwaccm.s.StatInGC, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, "Profiling of vmlaunch",
279 "/PROF/HWACCM/CPU%d/InGC", i);
280 AssertRC(rc);
281
282# define HWACCM_REG_COUNTER(a, b) \
283 rc = STAMR3RegisterF(pVM, a, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Profiling of vmlaunch", b, i); \
284 AssertRC(rc);
285
286 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitShadowNM, "/HWACCM/CPU%d/Exit/Trap/Shw/#NM");
287 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitGuestNM, "/HWACCM/CPU%d/Exit/Trap/Gst/#NM");
288 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitShadowPF, "/HWACCM/CPU%d/Exit/Trap/Shw/#PF");
289 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitGuestPF, "/HWACCM/CPU%d/Exit/Trap/Gst/#PF");
290 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitGuestUD, "/HWACCM/CPU%d/Exit/Trap/Gst/#UD");
291 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitGuestSS, "/HWACCM/CPU%d/Exit/Trap/Gst/#SS");
292 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitGuestNP, "/HWACCM/CPU%d/Exit/Trap/Gst/#NP");
293 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitGuestGP, "/HWACCM/CPU%d/Exit/Trap/Gst/#GP");
294 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitGuestMF, "/HWACCM/CPU%d/Exit/Trap/Gst/#MF");
295 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitGuestDE, "/HWACCM/CPU%d/Exit/Trap/Gst/#DE");
296 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitGuestDB, "/HWACCM/CPU%d/Exit/Trap/Gst/#DB");
297 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitInvpg, "/HWACCM/CPU%d/Exit/Instr/Invlpg");
298 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitInvd, "/HWACCM/CPU%d/Exit/Instr/Invd");
299 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitCpuid, "/HWACCM/CPU%d/Exit/Instr/Cpuid");
300 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitRdtsc, "/HWACCM/CPU%d/Exit/Instr/Rdtsc");
301 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitDRxWrite, "/HWACCM/CPU%d/Exit/Instr/DR/Write");
302 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitDRxRead, "/HWACCM/CPU%d/Exit/Instr/DR/Read");
303 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitCLTS, "/HWACCM/CPU%d/Exit/Instr/CLTS");
304 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitLMSW, "/HWACCM/CPU%d/Exit/Instr/LMSW");
305 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitIOWrite, "/HWACCM/CPU%d/Exit/IO/Write");
306 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitIORead, "/HWACCM/CPU%d/Exit/IO/Read");
307 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitIOStringWrite, "/HWACCM/CPU%d/Exit/IO/WriteString");
308 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitIOStringRead, "/HWACCM/CPU%d/Exit/IO/ReadString");
309 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitIrqWindow, "/HWACCM/CPU%d/Exit/IrqWindow");
310 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatExitMaxResume, "/HWACCM/CPU%d/Exit/MaxResume");
311
312 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatSwitchGuestIrq, "/HWACCM/CPU%d/Switch/IrqPending");
313 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatSwitchToR3, "/HWACCM/CPU%d/Switch/ToR3");
314
315 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatIntInject, "/HWACCM/CPU%d/Irq/Inject");
316 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatIntReinject, "/HWACCM/CPU%d/Irq/Reinject");
317 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatPendingHostIrq, "/HWACCM/CPU%d/Irq/PendingOnHost");
318
319 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatFlushPageManual, "/HWACCM/CPU%d/Flush/Page/Virt");
320 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatFlushPhysPageManual, "/HWACCM/CPU%d/Flush/Page/Phys");
321 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatFlushTLBManual, "/HWACCM/CPU%d/Flush/TLB/Manual");
322 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatFlushTLBCRxChange, "/HWACCM/CPU%d/Flush/TLB/CRx");
323 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatFlushPageInvlpg, "/HWACCM/CPU%d/Flush/Page/Invlpg");
324 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatFlushTLBWorldSwitch, "/HWACCM/CPU%d/Flush/TLB/Switch");
325 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatNoFlushTLBWorldSwitch, "/HWACCM/CPU%d/Flush/TLB/Skipped");
326 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatFlushASID, "/HWACCM/CPU%d/Flush/TLB/ASID");
327 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatFlushTLBInvlpga, "/HWACCM/CPU%d/Flush/TLB/PhysInvl");
328
329 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatTSCOffset, "/HWACCM/CPU%d/TSC/Offset");
330 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatTSCIntercept, "/HWACCM/CPU%d/TSC/Intercept");
331
332 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatDRxArmed, "/HWACCM/CPU%d/Debug/Armed");
333 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatDRxContextSwitch, "/HWACCM/CPU%d/Debug/ContextSwitch");
334 HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatDRxIOCheck, "/HWACCM/CPU%d/Debug/IOCheck");
335
336 for (unsigned j=0;j<RT_ELEMENTS(pVCpu->hwaccm.s.StatExitCRxWrite);j++)
337 {
338 rc = STAMR3RegisterF(pVM, &pVCpu->hwaccm.s.StatExitCRxWrite[j], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, "Profiling of CRx writes",
339 "/HWACCM/CPU%d/Exit/Instr/CR/Write/%x", i, j);
340 AssertRC(rc);
341 rc = STAMR3RegisterF(pVM, &pVCpu->hwaccm.s.StatExitCRxRead[j], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, "Profiling of CRx reads",
342 "/HWACCM/CPU%d/Exit/Instr/CR/Read/%x", i, j);
343 AssertRC(rc);
344 }
345
346#undef HWACCM_REG_COUNTER
347
348 pVCpu->hwaccm.s.paStatExitReason = NULL;
349
350 rc = MMHyperAlloc(pVM, MAX_EXITREASON_STAT*sizeof(*pVCpu->hwaccm.s.paStatExitReason), 0, MM_TAG_HWACCM, (void **)&pVCpu->hwaccm.s.paStatExitReason);
351 AssertRC(rc);
352 if (RT_SUCCESS(rc))
353 {
354 const char * const *papszDesc = ASMIsIntelCpu() ? &g_apszVTxExitReasons[0] : &g_apszAmdVExitReasons[0];
355 for (int j=0;j<MAX_EXITREASON_STAT;j++)
356 {
357 rc = STAMR3RegisterF(pVM, &pVCpu->hwaccm.s.paStatExitReason[j], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
358 papszDesc[j] ? papszDesc[j] : "Exit reason",
359 "/HWACCM/CPU%d/Exit/Reason/%02x", i, j);
360 AssertRC(rc);
361 }
362 rc = STAMR3RegisterF(pVM, &pVCpu->hwaccm.s.StatExitReasonNPF, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, "Nested page fault", "/HWACCM/CPU%d/Exit/Reason/#NPF", i);
363 AssertRC(rc);
364 }
365 pVCpu->hwaccm.s.paStatExitReasonR0 = MMHyperR3ToR0(pVM, pVCpu->hwaccm.s.paStatExitReason);
366# ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
367 Assert(pVCpu->hwaccm.s.paStatExitReasonR0 != NIL_RTR0PTR || !VMMIsHwVirtExtForced(pVM));
368# else
369 Assert(pVCpu->hwaccm.s.paStatExitReasonR0 != NIL_RTR0PTR);
370# endif
371 }
372#endif /* VBOX_WITH_STATISTICS */
373 return VINF_SUCCESS;
374}
375
376/**
377 * Turns off normal raw mode features
378 *
379 * @param pVM The VM to operate on.
380 */
381static void hwaccmR3DisableRawMode(PVM pVM)
382{
383 /* Disable PATM & CSAM. */
384 PATMR3AllowPatching(pVM, false);
385 CSAMDisableScanning(pVM);
386
387 /* Turn off IDT/LDT/GDT and TSS monitoring and sycing. */
388 SELMR3DisableMonitoring(pVM);
389 TRPMR3DisableMonitoring(pVM);
390
391 /* The hidden selector registers are now valid. */
392 CPUMSetHiddenSelRegsValid(pVM, true);
393
394 /* Disable the switcher code (safety precaution). */
395 VMMR3DisableSwitcher(pVM);
396
397 /* Disable mapping of the hypervisor into the shadow page table. */
398 PGMR3ChangeShwPDMappings(pVM, false);
399
400 /* Disable the switcher */
401 VMMR3DisableSwitcher(pVM);
402
403 if (pVM->hwaccm.s.fNestedPaging)
404 {
405 /* Reinit the paging mode to force the new shadow mode. */
406 PGMR3ChangeMode(pVM, PGMMODE_REAL);
407 }
408}
409
410/**
411 * Initialize VT-x or AMD-V.
412 *
413 * @returns VBox status code.
414 * @param pVM The VM handle.
415 */
416VMMR3DECL(int) HWACCMR3InitFinalizeR0(PVM pVM)
417{
418 int rc;
419
420 if ( !pVM->hwaccm.s.vmx.fSupported
421 && !pVM->hwaccm.s.svm.fSupported)
422 {
423 LogRel(("HWACCM: No VMX or SVM CPU extension found. Reason %Rrc\n", pVM->hwaccm.s.lLastError));
424 LogRel(("HWACCM: VMX MSR_IA32_FEATURE_CONTROL=%RX64\n", pVM->hwaccm.s.vmx.msr.feature_ctrl));
425#ifdef RT_OS_DARWIN
426 if (VMMIsHwVirtExtForced(pVM))
427 return VM_SET_ERROR(pVM, VERR_VMX_NO_VMX, "VT-x is not available.");
428#endif
429 return VINF_SUCCESS;
430 }
431
432 /*
433 * Note that we have a global setting for VT-x/AMD-V usage. VMX root mode changes the way the CPU operates. Our 64 bits switcher will trap
434 * because it turns off paging, which is not allowed in VMX root mode.
435 *
436 * To simplify matters we'll just force all running VMs to either use raw or VT-x mode. No mixing allowed in the VT-x case.
437 * There's no such problem with AMD-V. (@todo)
438 *
439 */
440 /* If we enabled or disabled hwaccm mode, then it can't be changed until all the VMs are shutdown. */
441 rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_HWACC_ENABLE, (pVM->hwaccm.s.fAllowed) ? HWACCMSTATE_ENABLED : HWACCMSTATE_DISABLED, NULL);
442 if (RT_FAILURE(rc))
443 {
444 LogRel(("HWACCMR3InitFinalize: SUPCallVMMR0Ex VMMR0_DO_HWACC_ENABLE failed with %Rrc\n", rc));
445 LogRel(("HWACCMR3InitFinalize: disallowed %s of HWACCM\n", pVM->hwaccm.s.fAllowed ? "enabling" : "disabling"));
446
447#ifdef RT_OS_DARWIN
448 /*
449 * This is 100% fatal if we didn't prepare for a HwVirtExt setup because of
450 * missing ring-0 allocations. For VMs that require HwVirtExt it doesn't normally
451 * make sense to try run them in software mode, so fail that too.
452 */
453 if (VMMIsHwVirtExtForced(pVM))
454 VM_SET_ERROR(pVM, rc, "An active VM already uses software virtualization. It is not allowed to "
455 "simultaneously use VT-x.");
456 else
457 VM_SET_ERROR(pVM, rc, "An active VM already uses Intel VT-x hardware acceleration. It is not "
458 "allowed to simultaneously use software virtualization.");
459 return rc;
460
461#else /* !RT_OS_DARWIN */
462
463 /* Invert the selection */
464 pVM->hwaccm.s.fAllowed ^= 1;
465 if (pVM->hwaccm.s.fAllowed)
466 {
467 if (pVM->hwaccm.s.vmx.fSupported)
468 VM_SET_ERROR(pVM, rc, "An active VM already uses Intel VT-x hardware acceleration. It is not allowed "
469 "to simultaneously use software virtualization.\n");
470 else
471 VM_SET_ERROR(pVM, rc, "An active VM already uses AMD-V hardware acceleration. It is not allowed to "
472 "simultaneously use software virtualization.\n");
473 }
474 else
475 VM_SET_ERROR(pVM, rc, "An active VM already uses software virtualization. It is not allowed to simultaneously "
476 "use VT-x or AMD-V.\n");
477 return rc;
478#endif /* !RT_OS_DARWIN */
479 }
480
481 if (pVM->hwaccm.s.fAllowed == false)
482 return VINF_SUCCESS; /* disabled */
483
484 Assert(!pVM->fHWACCMEnabled || VMMIsHwVirtExtForced(pVM));
485
486 if (pVM->hwaccm.s.vmx.fSupported)
487 {
488 Log(("pVM->hwaccm.s.vmx.fSupported = %d\n", pVM->hwaccm.s.vmx.fSupported));
489
490 if ( pVM->hwaccm.s.fInitialized == false
491 && pVM->hwaccm.s.vmx.msr.feature_ctrl != 0)
492 {
493 uint64_t val;
494 RTGCPHYS GCPhys = 0;
495
496 LogRel(("HWACCM: Host CR4=%08X\n", pVM->hwaccm.s.vmx.hostCR4));
497 LogRel(("HWACCM: MSR_IA32_FEATURE_CONTROL = %RX64\n", pVM->hwaccm.s.vmx.msr.feature_ctrl));
498 LogRel(("HWACCM: MSR_IA32_VMX_BASIC_INFO = %RX64\n", pVM->hwaccm.s.vmx.msr.vmx_basic_info));
499 LogRel(("HWACCM: VMCS id = %x\n", MSR_IA32_VMX_BASIC_INFO_VMCS_ID(pVM->hwaccm.s.vmx.msr.vmx_basic_info)));
500 LogRel(("HWACCM: VMCS size = %x\n", MSR_IA32_VMX_BASIC_INFO_VMCS_SIZE(pVM->hwaccm.s.vmx.msr.vmx_basic_info)));
501 LogRel(("HWACCM: VMCS physical address limit = %s\n", MSR_IA32_VMX_BASIC_INFO_VMCS_PHYS_WIDTH(pVM->hwaccm.s.vmx.msr.vmx_basic_info) ? "< 4 GB" : "None"));
502 LogRel(("HWACCM: VMCS memory type = %x\n", MSR_IA32_VMX_BASIC_INFO_VMCS_MEM_TYPE(pVM->hwaccm.s.vmx.msr.vmx_basic_info)));
503 LogRel(("HWACCM: Dual monitor treatment = %d\n", MSR_IA32_VMX_BASIC_INFO_VMCS_DUAL_MON(pVM->hwaccm.s.vmx.msr.vmx_basic_info)));
504
505 LogRel(("HWACCM: MSR_IA32_VMX_PINBASED_CTLS = %RX64\n", pVM->hwaccm.s.vmx.msr.vmx_pin_ctls.u));
506 val = pVM->hwaccm.s.vmx.msr.vmx_pin_ctls.n.allowed1;
507 if (val & VMX_VMCS_CTRL_PIN_EXEC_CONTROLS_EXT_INT_EXIT)
508 LogRel(("HWACCM: VMX_VMCS_CTRL_PIN_EXEC_CONTROLS_EXT_INT_EXIT\n"));
509 if (val & VMX_VMCS_CTRL_PIN_EXEC_CONTROLS_NMI_EXIT)
510 LogRel(("HWACCM: VMX_VMCS_CTRL_PIN_EXEC_CONTROLS_NMI_EXIT\n"));
511 val = pVM->hwaccm.s.vmx.msr.vmx_pin_ctls.n.disallowed0;
512 if (val & VMX_VMCS_CTRL_PIN_EXEC_CONTROLS_EXT_INT_EXIT)
513 LogRel(("HWACCM: VMX_VMCS_CTRL_PIN_EXEC_CONTROLS_EXT_INT_EXIT *must* be set\n"));
514 if (val & VMX_VMCS_CTRL_PIN_EXEC_CONTROLS_NMI_EXIT)
515 LogRel(("HWACCM: VMX_VMCS_CTRL_PIN_EXEC_CONTROLS_NMI_EXIT *must* be set\n"));
516
517 LogRel(("HWACCM: MSR_IA32_VMX_PROCBASED_CTLS = %RX64\n", pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.u));
518 val = pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1;
519 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_IRQ_WINDOW_EXIT)
520 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_IRQ_WINDOW_EXIT\n"));
521 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_TSC_OFFSET)
522 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_TSC_OFFSET\n"));
523 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_HLT_EXIT)
524 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_HLT_EXIT\n"));
525 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_INVLPG_EXIT)
526 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_INVLPG_EXIT\n"));
527 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MWAIT_EXIT)
528 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MWAIT_EXIT\n"));
529 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDPMC_EXIT)
530 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDPMC_EXIT\n"));
531 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT)
532 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT\n"));
533 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR3_LOAD_EXIT)
534 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR3_LOAD_EXIT\n"));
535 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR3_STORE_EXIT)
536 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR3_STORE_EXIT\n"));
537 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR8_LOAD_EXIT)
538 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR8_LOAD_EXIT\n"));
539 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR8_STORE_EXIT)
540 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR8_STORE_EXIT\n"));
541 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_TPR_SHADOW)
542 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_TPR_SHADOW\n"));
543 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MOV_DR_EXIT)
544 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MOV_DR_EXIT\n"));
545 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_UNCOND_IO_EXIT)
546 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_UNCOND_IO_EXIT\n"));
547 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_IO_BITMAPS)
548 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_IO_BITMAPS\n"));
549 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MONITOR_TRAP_FLAG)
550 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MONITOR_TRAP_FLAG\n"));
551 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_MSR_BITMAPS)
552 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_MSR_BITMAPS\n"));
553 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MONITOR_EXIT)
554 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MONITOR_EXIT\n"));
555 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_PAUSE_EXIT)
556 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_PAUSE_EXIT\n"));
557 if (val & VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL)
558 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL\n"));
559
560 val = pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.disallowed0;
561 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_IRQ_WINDOW_EXIT)
562 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_IRQ_WINDOW_EXIT *must* be set\n"));
563 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_TSC_OFFSET)
564 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_TSC_OFFSET *must* be set\n"));
565 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_HLT_EXIT)
566 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_HLT_EXIT *must* be set\n"));
567 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_INVLPG_EXIT)
568 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_INVLPG_EXIT *must* be set\n"));
569 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MWAIT_EXIT)
570 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MWAIT_EXIT *must* be set\n"));
571 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDPMC_EXIT)
572 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDPMC_EXIT *must* be set\n"));
573 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT)
574 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT *must* be set\n"));
575 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR3_LOAD_EXIT)
576 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR3_LOAD_EXIT *must* be set\n"));
577 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR3_STORE_EXIT)
578 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR3_STORE_EXIT *must* be set\n"));
579 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR8_LOAD_EXIT)
580 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR8_LOAD_EXIT *must* be set\n"));
581 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR8_STORE_EXIT)
582 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR8_STORE_EXIT *must* be set\n"));
583 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_TPR_SHADOW)
584 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_TPR_SHADOW *must* be set\n"));
585 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MOV_DR_EXIT)
586 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MOV_DR_EXIT *must* be set\n"));
587 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_UNCOND_IO_EXIT)
588 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_UNCOND_IO_EXIT *must* be set\n"));
589 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_IO_BITMAPS)
590 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_IO_BITMAPS *must* be set\n"));
591 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MONITOR_TRAP_FLAG)
592 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MONITOR_TRAP_FLAG *must* be set\n"));
593 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_MSR_BITMAPS)
594 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_MSR_BITMAPS *must* be set\n"));
595 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MONITOR_EXIT)
596 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MONITOR_EXIT *must* be set\n"));
597 if (val & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_PAUSE_EXIT)
598 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_PAUSE_EXIT *must* be set\n"));
599 if (val & VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL)
600 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL *must* be set\n"));
601
602 if (pVM->hwaccm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL)
603 {
604 LogRel(("HWACCM: MSR_IA32_VMX_PROCBASED_CTLS2 = %RX64\n", pVM->hwaccm.s.vmx.msr.vmx_proc_ctls2.u));
605 val = pVM->hwaccm.s.vmx.msr.vmx_proc_ctls2.n.allowed1;
606 if (val & VMX_VMCS_CTRL_PROC_EXEC2_VIRT_APIC)
607 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC2_VIRT_APIC\n"));
608 if (val & VMX_VMCS_CTRL_PROC_EXEC2_EPT)
609 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC2_EPT\n"));
610 if (val & VMX_VMCS_CTRL_PROC_EXEC2_VPID)
611 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC2_VPID\n"));
612 if (val & VMX_VMCS_CTRL_PROC_EXEC2_WBINVD_EXIT)
613 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC2_WBINVD_EXIT\n"));
614
615 val = pVM->hwaccm.s.vmx.msr.vmx_proc_ctls2.n.disallowed0;
616 if (val & VMX_VMCS_CTRL_PROC_EXEC2_VIRT_APIC)
617 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC2_VIRT_APIC *must* be set\n"));
618 if (val & VMX_VMCS_CTRL_PROC_EXEC2_EPT)
619 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC2_EPT *must* be set\n"));
620 if (val & VMX_VMCS_CTRL_PROC_EXEC2_VPID)
621 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC2_VPID *must* be set\n"));
622 if (val & VMX_VMCS_CTRL_PROC_EXEC2_WBINVD_EXIT)
623 LogRel(("HWACCM: VMX_VMCS_CTRL_PROC_EXEC2_WBINVD_EXIT *must* be set\n"));
624 }
625
626 LogRel(("HWACCM: MSR_IA32_VMX_ENTRY_CTLS = %RX64\n", pVM->hwaccm.s.vmx.msr.vmx_entry.u));
627 val = pVM->hwaccm.s.vmx.msr.vmx_entry.n.allowed1;
628 if (val & VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_DEBUG)
629 LogRel(("HWACCM: VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_DEBUG\n"));
630 if (val & VMX_VMCS_CTRL_ENTRY_CONTROLS_IA64_MODE)
631 LogRel(("HWACCM: VMX_VMCS_CTRL_ENTRY_CONTROLS_IA64_MODE\n"));
632 if (val & VMX_VMCS_CTRL_ENTRY_CONTROLS_ENTRY_SMM)
633 LogRel(("HWACCM: VMX_VMCS_CTRL_ENTRY_CONTROLS_ENTRY_SMM\n"));
634 if (val & VMX_VMCS_CTRL_ENTRY_CONTROLS_DEACTIVATE_DUALMON)
635 LogRel(("HWACCM: VMX_VMCS_CTRL_ENTRY_CONTROLS_DEACTIVATE_DUALMON\n"));
636 if (val & VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_GUEST_PERF_MSR)
637 LogRel(("HWACCM: VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_GUEST_PERF_MSR\n"));
638 if (val & VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_GUEST_PAT_MSR)
639 LogRel(("HWACCM: VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_GUEST_PAT_MSR\n"));
640 if (val & VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_GUEST_EFER_MSR)
641 LogRel(("HWACCM: VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_GUEST_EFER_MSR\n"));
642 val = pVM->hwaccm.s.vmx.msr.vmx_entry.n.disallowed0;
643 if (val & VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_DEBUG)
644 LogRel(("HWACCM: VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_DEBUG *must* be set\n"));
645 if (val & VMX_VMCS_CTRL_ENTRY_CONTROLS_IA64_MODE)
646 LogRel(("HWACCM: VMX_VMCS_CTRL_ENTRY_CONTROLS_IA64_MODE *must* be set\n"));
647 if (val & VMX_VMCS_CTRL_ENTRY_CONTROLS_ENTRY_SMM)
648 LogRel(("HWACCM: VMX_VMCS_CTRL_ENTRY_CONTROLS_ENTRY_SMM *must* be set\n"));
649 if (val & VMX_VMCS_CTRL_ENTRY_CONTROLS_DEACTIVATE_DUALMON)
650 LogRel(("HWACCM: VMX_VMCS_CTRL_ENTRY_CONTROLS_DEACTIVATE_DUALMON *must* be set\n"));
651 if (val & VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_GUEST_PERF_MSR)
652 LogRel(("HWACCM: VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_GUEST_PERF_MSR *must* be set\n"));
653 if (val & VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_GUEST_PAT_MSR)
654 LogRel(("HWACCM: VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_GUEST_PAT_MSR *must* be set\n"));
655 if (val & VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_GUEST_EFER_MSR)
656 LogRel(("HWACCM: VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_GUEST_EFER_MSR *must* be set\n"));
657
658 LogRel(("HWACCM: MSR_IA32_VMX_EXIT_CTLS = %RX64\n", pVM->hwaccm.s.vmx.msr.vmx_exit.u));
659 val = pVM->hwaccm.s.vmx.msr.vmx_exit.n.allowed1;
660 if (val & VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_DEBUG)
661 LogRel(("HWACCM: VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_DEBUG\n"));
662 if (val & VMX_VMCS_CTRL_EXIT_CONTROLS_HOST_AMD64)
663 LogRel(("HWACCM: VMX_VMCS_CTRL_EXIT_CONTROLS_HOST_AMD64\n"));
664 if (val & VMX_VMCS_CTRL_EXIT_CONTROLS_ACK_EXTERNAL_IRQ)
665 LogRel(("HWACCM: VMX_VMCS_CTRL_EXIT_CONTROLS_ACK_EXTERNAL_IRQ\n"));
666 if (val & VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_GUEST_PAT_MSR)
667 LogRel(("HWACCM: VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_GUEST_PAT_MSR\n"));
668 if (val & VMX_VMCS_CTRL_EXIT_CONTROLS_LOAD_HOST_PAT_MSR)
669 LogRel(("HWACCM: VMX_VMCS_CTRL_EXIT_CONTROLS_LOAD_HOST_PAT_MSR\n"));
670 if (val & VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_GUEST_EFER_MSR)
671 LogRel(("HWACCM: VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_GUEST_EFER_MSR\n"));
672 if (val & VMX_VMCS_CTRL_EXIT_CONTROLS_LOAD_HOST_EFER_MSR)
673 LogRel(("HWACCM: VMX_VMCS_CTRL_EXIT_CONTROLS_LOAD_HOST_EFER_MSR\n"));
674 if (val & VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_VMX_PREEMPT_TIMER)
675 LogRel(("HWACCM: VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_VMX_PREEMPT_TIMER\n"));
676 val = pVM->hwaccm.s.vmx.msr.vmx_exit.n.disallowed0;
677 if (val & VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_DEBUG)
678 LogRel(("HWACCM: VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_DEBUG *must* be set\n"));
679 if (val & VMX_VMCS_CTRL_EXIT_CONTROLS_HOST_AMD64)
680 LogRel(("HWACCM: VMX_VMCS_CTRL_EXIT_CONTROLS_HOST_AMD64 *must* be set\n"));
681 if (val & VMX_VMCS_CTRL_EXIT_CONTROLS_ACK_EXTERNAL_IRQ)
682 LogRel(("HWACCM: VMX_VMCS_CTRL_EXIT_CONTROLS_ACK_EXTERNAL_IRQ *must* be set\n"));
683 if (val & VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_GUEST_PAT_MSR)
684 LogRel(("HWACCM: VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_GUEST_PAT_MSR *must* be set\n"));
685 if (val & VMX_VMCS_CTRL_EXIT_CONTROLS_LOAD_HOST_PAT_MSR)
686 LogRel(("HWACCM: VMX_VMCS_CTRL_EXIT_CONTROLS_LOAD_HOST_PAT_MSR *must* be set\n"));
687 if (val & VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_GUEST_EFER_MSR)
688 LogRel(("HWACCM: VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_GUEST_EFER_MSR *must* be set\n"));
689 if (val & VMX_VMCS_CTRL_EXIT_CONTROLS_LOAD_HOST_EFER_MSR)
690 LogRel(("HWACCM: VMX_VMCS_CTRL_EXIT_CONTROLS_LOAD_HOST_EFER_MSR *must* be set\n"));
691 if (val & VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_VMX_PREEMPT_TIMER)
692 LogRel(("HWACCM: VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_VMX_PREEMPT_TIMER *must* be set\n"));
693
694 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps)
695 {
696 LogRel(("HWACCM: MSR_IA32_VMX_EPT_VPID_CAPS = %RX64\n", pVM->hwaccm.s.vmx.msr.vmx_eptcaps));
697
698 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_RWX_X_ONLY)
699 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_RWX_X_ONLY\n"));
700 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_RWX_W_ONLY)
701 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_RWX_W_ONLY\n"));
702 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_RWX_WX_ONLY)
703 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_RWX_WX_ONLY\n"));
704 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_GAW_21_BITS)
705 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_GAW_21_BITS\n"));
706 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_GAW_30_BITS)
707 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_GAW_30_BITS\n"));
708 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_GAW_39_BITS)
709 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_GAW_39_BITS\n"));
710 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_GAW_48_BITS)
711 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_GAW_48_BITS\n"));
712 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_GAW_57_BITS)
713 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_GAW_57_BITS\n"));
714 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_EMT_UC)
715 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_EMT_UC\n"));
716 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_EMT_WC)
717 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_EMT_WC\n"));
718 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_EMT_WT)
719 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_EMT_WT\n"));
720 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_EMT_WP)
721 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_EMT_WP\n"));
722 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_EMT_WB)
723 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_EMT_WB\n"));
724 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_SP_21_BITS)
725 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_SP_21_BITS\n"));
726 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_SP_30_BITS)
727 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_SP_30_BITS\n"));
728 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_SP_39_BITS)
729 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_SP_39_BITS\n"));
730 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_SP_48_BITS)
731 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_SP_48_BITS\n"));
732 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_INVEPT)
733 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_INVEPT\n"));
734 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_INVEPT_CAPS_INDIV)
735 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_INVEPT_CAPS_INDIV\n"));
736 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_INVEPT_CAPS_CONTEXT)
737 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_INVEPT_CAPS_CONTEXT\n"));
738 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_INVEPT_CAPS_ALL)
739 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_INVEPT_CAPS_ALL\n"));
740 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_INVVPID)
741 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_INVVPID\n"));
742 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_INDIV)
743 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_INDIV\n"));
744 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_CONTEXT)
745 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_CONTEXT\n"));
746 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_ALL)
747 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_ALL\n"));
748 if (pVM->hwaccm.s.vmx.msr.vmx_eptcaps & MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_CONTEXT_GLOBAL)
749 LogRel(("HWACCM: MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_CONTEXT_GLOBAL\n"));
750 }
751
752 LogRel(("HWACCM: MSR_IA32_VMX_MISC = %RX64\n", pVM->hwaccm.s.vmx.msr.vmx_misc));
753 LogRel(("HWACCM: MSR_IA32_VMX_MISC_ACTIVITY_STATES %x\n", MSR_IA32_VMX_MISC_ACTIVITY_STATES(pVM->hwaccm.s.vmx.msr.vmx_misc)));
754 LogRel(("HWACCM: MSR_IA32_VMX_MISC_CR3_TARGET %x\n", MSR_IA32_VMX_MISC_CR3_TARGET(pVM->hwaccm.s.vmx.msr.vmx_misc)));
755 LogRel(("HWACCM: MSR_IA32_VMX_MISC_MAX_MSR %x\n", MSR_IA32_VMX_MISC_MAX_MSR(pVM->hwaccm.s.vmx.msr.vmx_misc)));
756 LogRel(("HWACCM: MSR_IA32_VMX_MISC_MSEG_ID %x\n", MSR_IA32_VMX_MISC_MSEG_ID(pVM->hwaccm.s.vmx.msr.vmx_misc)));
757
758 LogRel(("HWACCM: MSR_IA32_VMX_CR0_FIXED0 = %RX64\n", pVM->hwaccm.s.vmx.msr.vmx_cr0_fixed0));
759 LogRel(("HWACCM: MSR_IA32_VMX_CR0_FIXED1 = %RX64\n", pVM->hwaccm.s.vmx.msr.vmx_cr0_fixed1));
760 LogRel(("HWACCM: MSR_IA32_VMX_CR4_FIXED0 = %RX64\n", pVM->hwaccm.s.vmx.msr.vmx_cr4_fixed0));
761 LogRel(("HWACCM: MSR_IA32_VMX_CR4_FIXED1 = %RX64\n", pVM->hwaccm.s.vmx.msr.vmx_cr4_fixed1));
762 LogRel(("HWACCM: MSR_IA32_VMX_VMCS_ENUM = %RX64\n", pVM->hwaccm.s.vmx.msr.vmx_vmcs_enum));
763
764 LogRel(("HWACCM: TPR shadow physaddr = %RHp\n", pVM->hwaccm.s.vmx.pAPICPhys));
765 LogRel(("HWACCM: MSR bitmap physaddr = %RHp\n", pVM->hwaccm.s.vmx.pMSRBitmapPhys));
766
767 for (unsigned i=0;i<pVM->cCPUs;i++)
768 LogRel(("HWACCM: VMCS physaddr VCPU%d = %RHp\n", i, pVM->aCpus[i].hwaccm.s.vmx.pVMCSPhys));
769
770#ifdef HWACCM_VTX_WITH_EPT
771 if (pVM->hwaccm.s.vmx.msr.vmx_proc_ctls2.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC2_EPT)
772 pVM->hwaccm.s.fNestedPaging = pVM->hwaccm.s.fAllowNestedPaging;
773#endif /* HWACCM_VTX_WITH_EPT */
774#ifdef HWACCM_VTX_WITH_VPID
775 if ( (pVM->hwaccm.s.vmx.msr.vmx_proc_ctls2.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC2_VPID)
776 && !pVM->hwaccm.s.fNestedPaging) /* VPID and EPT are mutually exclusive. */
777 pVM->hwaccm.s.vmx.fVPID = pVM->hwaccm.s.vmx.fAllowVPID;
778#endif /* HWACCM_VTX_WITH_VPID */
779
780 /* Only try once. */
781 pVM->hwaccm.s.fInitialized = true;
782
783 /* Allocate three pages for the TSS we need for real mode emulation. (2 page for the IO bitmap) */
784 rc = PDMR3VMMDevHeapAlloc(pVM, HWACCM_VTX_TOTAL_DEVHEAP_MEM, (RTR3PTR *)&pVM->hwaccm.s.vmx.pRealModeTSS);
785 AssertRC(rc);
786 if (RT_FAILURE(rc))
787 return rc;
788
789 /* The I/O bitmap starts right after the virtual interrupt redirection bitmap. */
790 ASMMemZero32(pVM->hwaccm.s.vmx.pRealModeTSS, sizeof(*pVM->hwaccm.s.vmx.pRealModeTSS));
791 pVM->hwaccm.s.vmx.pRealModeTSS->offIoBitmap = sizeof(*pVM->hwaccm.s.vmx.pRealModeTSS);
792 /* Bit set to 0 means redirection enabled. */
793 memset(pVM->hwaccm.s.vmx.pRealModeTSS->IntRedirBitmap, 0x0, sizeof(pVM->hwaccm.s.vmx.pRealModeTSS->IntRedirBitmap));
794 /* Allow all port IO, so the VT-x IO intercepts do their job. */
795 memset(pVM->hwaccm.s.vmx.pRealModeTSS + 1, 0, PAGE_SIZE*2);
796 *((unsigned char *)pVM->hwaccm.s.vmx.pRealModeTSS + HWACCM_VTX_TSS_SIZE - 2) = 0xff;
797
798 /* Construct a 1024 element page directory with 4 MB pages for the identity mapped page table used in
799 * real and protected mode without paging with EPT.
800 */
801 pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable = (PX86PD)((char *)pVM->hwaccm.s.vmx.pRealModeTSS + PAGE_SIZE * 3);
802 for (unsigned i=0;i<X86_PG_ENTRIES;i++)
803 {
804 pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable->a[i].u = _4M * i;
805 pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable->a[i].u |= X86_PDE4M_P | X86_PDE4M_RW | X86_PDE4M_US | X86_PDE4M_A | X86_PDE4M_D | X86_PDE4M_PS | X86_PDE4M_G;
806 }
807
808 /* We convert it here every time as pci regions could be reconfigured. */
809 rc = PDMVMMDevHeapR3ToGCPhys(pVM, pVM->hwaccm.s.vmx.pRealModeTSS, &GCPhys);
810 AssertRC(rc);
811 LogRel(("HWACCM: Real Mode TSS guest physaddr = %RGp\n", GCPhys));
812
813 rc = PDMVMMDevHeapR3ToGCPhys(pVM, pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
814 AssertRC(rc);
815 LogRel(("HWACCM: Non-Paging Mode EPT CR3 = %RGp\n", GCPhys));
816
817 rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_HWACC_SETUP_VM, 0, NULL);
818 AssertRC(rc);
819 if (rc == VINF_SUCCESS)
820 {
821 pVM->fHWACCMEnabled = true;
822 pVM->hwaccm.s.vmx.fEnabled = true;
823 hwaccmR3DisableRawMode(pVM);
824
825 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_SEP);
826#ifdef VBOX_ENABLE_64_BITS_GUESTS
827 if (pVM->hwaccm.s.fAllow64BitGuests)
828 {
829 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_PAE);
830 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_LONG_MODE);
831 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_SYSCALL); /* 64 bits only on Intel CPUs */
832 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_LAHF);
833 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_NXE);
834 }
835#endif
836 LogRel(("HWACCM: VMX enabled!\n"));
837 LogRel((pVM->hwaccm.s.fAllow64BitGuests
838 ? "HWACCM: 32-bit and 64-bit guest supported.\n"
839 : "HWACCM: 32-bit guest supported.\n"));
840 if (pVM->hwaccm.s.fNestedPaging)
841 {
842 LogRel(("HWACCM: Enabled nested paging\n"));
843 LogRel(("HWACCM: EPT root page = %RHp\n", PGMGetEPTCR3(pVM)));
844 }
845 if (pVM->hwaccm.s.vmx.fVPID)
846 LogRel(("HWACCM: Enabled VPID\n"));
847
848 if ( pVM->hwaccm.s.fNestedPaging
849 || pVM->hwaccm.s.vmx.fVPID)
850 {
851 LogRel(("HWACCM: enmFlushPage %d\n", pVM->hwaccm.s.vmx.enmFlushPage));
852 LogRel(("HWACCM: enmFlushContext %d\n", pVM->hwaccm.s.vmx.enmFlushContext));
853 }
854 }
855 else
856 {
857 LogRel(("HWACCM: VMX setup failed with rc=%Rrc!\n", rc));
858 LogRel(("HWACCM: Last instruction error %x\n", pVM->aCpus[0].hwaccm.s.vmx.lasterror.ulInstrError));
859 pVM->fHWACCMEnabled = false;
860 }
861 }
862 }
863 else
864 if (pVM->hwaccm.s.svm.fSupported)
865 {
866 Log(("pVM->hwaccm.s.svm.fSupported = %d\n", pVM->hwaccm.s.svm.fSupported));
867
868 if (pVM->hwaccm.s.fInitialized == false)
869 {
870 /* Erratum 170 which requires a forced TLB flush for each world switch:
871 * See http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/33610.pdf
872 *
873 * All BH-G1/2 and DH-G1/2 models include a fix:
874 * Athlon X2: 0x6b 1/2
875 * 0x68 1/2
876 * Athlon 64: 0x7f 1
877 * 0x6f 2
878 * Sempron: 0x7f 1/2
879 * 0x6f 2
880 * 0x6c 2
881 * 0x7c 2
882 * Turion 64: 0x68 2
883 *
884 */
885 uint32_t u32Dummy;
886 uint32_t u32Version, u32Family, u32Model, u32Stepping, u32BaseFamily;
887 ASMCpuId(1, &u32Version, &u32Dummy, &u32Dummy, &u32Dummy);
888 u32BaseFamily= (u32Version >> 8) & 0xf;
889 u32Family = u32BaseFamily + (u32BaseFamily == 0xf ? ((u32Version >> 20) & 0x7f) : 0);
890 u32Model = ((u32Version >> 4) & 0xf);
891 u32Model = u32Model | ((u32BaseFamily == 0xf ? (u32Version >> 16) & 0x0f : 0) << 4);
892 u32Stepping = u32Version & 0xf;
893 if ( u32Family == 0xf
894 && !((u32Model == 0x68 || u32Model == 0x6b || u32Model == 0x7f) && u32Stepping >= 1)
895 && !((u32Model == 0x6f || u32Model == 0x6c || u32Model == 0x7c) && u32Stepping >= 2))
896 {
897 LogRel(("HWACMM: AMD cpu with erratum 170 family %x model %x stepping %x\n", u32Family, u32Model, u32Stepping));
898 }
899
900 LogRel(("HWACMM: cpuid 0x80000001.u32AMDFeatureECX = %RX32\n", pVM->hwaccm.s.cpuid.u32AMDFeatureECX));
901 LogRel(("HWACMM: cpuid 0x80000001.u32AMDFeatureEDX = %RX32\n", pVM->hwaccm.s.cpuid.u32AMDFeatureEDX));
902 LogRel(("HWACCM: SVM revision = %X\n", pVM->hwaccm.s.svm.u32Rev));
903 LogRel(("HWACCM: SVM max ASID = %d\n", pVM->hwaccm.s.uMaxASID));
904 LogRel(("HWACCM: SVM features = %X\n", pVM->hwaccm.s.svm.u32Features));
905
906 if (pVM->hwaccm.s.svm.u32Features & AMD_CPUID_SVM_FEATURE_EDX_NESTED_PAGING)
907 LogRel(("HWACCM: AMD_CPUID_SVM_FEATURE_EDX_NESTED_PAGING\n"));
908 if (pVM->hwaccm.s.svm.u32Features & AMD_CPUID_SVM_FEATURE_EDX_LBR_VIRT)
909 LogRel(("HWACCM: AMD_CPUID_SVM_FEATURE_EDX_LBR_VIRT\n"));
910 if (pVM->hwaccm.s.svm.u32Features & AMD_CPUID_SVM_FEATURE_EDX_SVM_LOCK)
911 LogRel(("HWACCM: AMD_CPUID_SVM_FEATURE_EDX_SVM_LOCK\n"));
912 if (pVM->hwaccm.s.svm.u32Features & AMD_CPUID_SVM_FEATURE_EDX_NRIP_SAVE)
913 LogRel(("HWACCM: AMD_CPUID_SVM_FEATURE_EDX_NRIP_SAVE\n"));
914 if (pVM->hwaccm.s.svm.u32Features & AMD_CPUID_SVM_FEATURE_EDX_SSE_3_5_DISABLE)
915 LogRel(("HWACCM: AMD_CPUID_SVM_FEATURE_EDX_SSE_3_5_DISABLE\n"));
916
917 /* Only try once. */
918 pVM->hwaccm.s.fInitialized = true;
919
920 if (pVM->hwaccm.s.svm.u32Features & AMD_CPUID_SVM_FEATURE_EDX_NESTED_PAGING)
921 pVM->hwaccm.s.fNestedPaging = pVM->hwaccm.s.fAllowNestedPaging;
922
923 rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_HWACC_SETUP_VM, 0, NULL);
924 AssertRC(rc);
925 if (rc == VINF_SUCCESS)
926 {
927 pVM->fHWACCMEnabled = true;
928 pVM->hwaccm.s.svm.fEnabled = true;
929
930 if (pVM->hwaccm.s.fNestedPaging)
931 LogRel(("HWACCM: Enabled nested paging\n"));
932
933 hwaccmR3DisableRawMode(pVM);
934 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_SEP);
935 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_SYSCALL);
936 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_RDTSCP);
937#ifdef VBOX_ENABLE_64_BITS_GUESTS
938 if (pVM->hwaccm.s.fAllow64BitGuests)
939 {
940 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_PAE);
941 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_LONG_MODE);
942 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_NXE);
943 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_LAHF);
944 }
945#endif
946 LogRel((pVM->hwaccm.s.fAllow64BitGuests
947 ? "HWACCM: 32-bit and 64-bit guest supported.\n"
948 : "HWACCM: 32-bit guest supported.\n"));
949 }
950 else
951 {
952 pVM->fHWACCMEnabled = false;
953 }
954 }
955 }
956
957#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS) && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)
958 if (pVM->fHWACCMEnabled)
959 {
960 switch(PGMGetHostMode(pVM))
961 {
962 case PGMMODE_32_BIT:
963 pVM->hwaccm.s.pfnHost32ToGuest64R0 = VMMR3GetHostToGuestSwitcher(pVM, VMMSWITCHER_32_TO_AMD64);
964 break;
965
966 case PGMMODE_PAE:
967 case PGMMODE_PAE_NX:
968 pVM->hwaccm.s.pfnHost32ToGuest64R0 = VMMR3GetHostToGuestSwitcher(pVM, VMMSWITCHER_PAE_TO_AMD64);
969 break;
970
971 default:
972 AssertFailed();
973 break;
974 }
975
976 rc = PDMR3LdrGetSymbolRC(pVM, NULL, "VMXGCStartVM64", &pVM->hwaccm.s.pfnVMXGCStartVM64);
977 AssertMsgRCReturn(rc, ("VMXGCStartVM64 -> rc=%Rrc\n", rc), rc);
978
979 rc = PDMR3LdrGetSymbolRC(pVM, NULL, "SVMGCVMRun64", &pVM->hwaccm.s.pfnSVMGCVMRun64);
980 AssertMsgRCReturn(rc, ("SVMGCVMRun64 -> rc=%Rrc\n", rc), rc);
981
982 rc = PDMR3LdrGetSymbolRC(pVM, NULL, "HWACCMSaveGuestFPU64", &pVM->hwaccm.s.pfnSaveGuestFPU64);
983 AssertMsgRCReturn(rc, ("HWACCMSetupFPU64 -> rc=%Rrc\n", rc), rc);
984
985 rc = PDMR3LdrGetSymbolRC(pVM, NULL, "HWACCMSaveGuestDebug64", &pVM->hwaccm.s.pfnSaveGuestDebug64);
986 AssertMsgRCReturn(rc, ("HWACCMSetupDebug64 -> rc=%Rrc\n", rc), rc);
987
988# ifdef DEBUG
989 rc = PDMR3LdrGetSymbolRC(pVM, NULL, "HWACCMTestSwitcher64", &pVM->hwaccm.s.pfnTest64);
990 AssertMsgRCReturn(rc, ("HWACCMTestSwitcher64 -> rc=%Rrc\n", rc), rc);
991# endif
992 }
993#endif
994 return VINF_SUCCESS;
995}
996
997/**
998 * Applies relocations to data and code managed by this
999 * component. This function will be called at init and
1000 * whenever the VMM need to relocate it self inside the GC.
1001 *
1002 * @param pVM The VM.
1003 */
1004VMMR3DECL(void) HWACCMR3Relocate(PVM pVM)
1005{
1006 Log(("HWACCMR3Relocate to %RGv\n", MMHyperGetArea(pVM, 0)));
1007
1008 /* Fetch the current paging mode during the relocate callback during state loading. */
1009 if (VMR3GetState(pVM) == VMSTATE_LOADING)
1010 {
1011 for (unsigned i=0;i<pVM->cCPUs;i++)
1012 {
1013 PVMCPU pVCpu = &pVM->aCpus[i];
1014 /* @todo SMP */
1015 pVCpu->hwaccm.s.enmShadowMode = PGMGetShadowMode(pVM);
1016 pVCpu->hwaccm.s.vmx.enmCurrGuestMode = PGMGetGuestMode(pVM);
1017 }
1018 }
1019
1020 return;
1021}
1022
1023/**
1024 * Checks hardware accelerated raw mode is allowed.
1025 *
1026 * @returns boolean
1027 * @param pVM The VM to operate on.
1028 */
1029VMMR3DECL(bool) HWACCMR3IsAllowed(PVM pVM)
1030{
1031 return pVM->hwaccm.s.fAllowed;
1032}
1033
1034/**
1035 * Notification callback which is called whenever there is a chance that a CR3
1036 * value might have changed.
1037 *
1038 * This is called by PGM.
1039 *
1040 * @param pVM The VM to operate on.
1041 * @param enmShadowMode New shadow paging mode.
1042 * @param enmGuestMode New guest paging mode.
1043 */
1044VMMR3DECL(void) HWACCMR3PagingModeChanged(PVM pVM, PGMMODE enmShadowMode, PGMMODE enmGuestMode)
1045{
1046 /* Ignore page mode changes during state loading. */
1047 if (VMR3GetState(pVM) == VMSTATE_LOADING)
1048 return;
1049
1050 PVMCPU pVCpu = VMMGetCpu(pVM);
1051 pVCpu->hwaccm.s.enmShadowMode = enmShadowMode;
1052
1053 if ( pVM->hwaccm.s.vmx.fEnabled
1054 && pVM->fHWACCMEnabled)
1055 {
1056 if ( pVCpu->hwaccm.s.vmx.enmCurrGuestMode == PGMMODE_REAL
1057 && enmGuestMode >= PGMMODE_PROTECTED)
1058 {
1059 PCPUMCTX pCtx;
1060
1061 pCtx = CPUMQueryGuestCtxPtr(pVM);
1062
1063 /* After a real mode switch to protected mode we must force
1064 * CPL to 0. Our real mode emulation had to set it to 3.
1065 */
1066 pCtx->ssHid.Attr.n.u2Dpl = 0;
1067 }
1068 }
1069}
1070
1071/**
1072 * Terminates the HWACCM.
1073 *
1074 * Termination means cleaning up and freeing all resources,
1075 * the VM it self is at this point powered off or suspended.
1076 *
1077 * @returns VBox status code.
1078 * @param pVM The VM to operate on.
1079 */
1080VMMR3DECL(int) HWACCMR3Term(PVM pVM)
1081{
1082 if (pVM->hwaccm.s.vmx.pRealModeTSS)
1083 {
1084 PDMR3VMMDevHeapFree(pVM, pVM->hwaccm.s.vmx.pRealModeTSS);
1085 pVM->hwaccm.s.vmx.pRealModeTSS = 0;
1086 }
1087 return 0;
1088}
1089
1090/**
1091 * Terminates the per-VCPU HWACCM.
1092 *
1093 * Termination means cleaning up and freeing all resources,
1094 * the VM it self is at this point powered off or suspended.
1095 *
1096 * @returns VBox status code.
1097 * @param pVM The VM to operate on.
1098 */
1099VMMR3DECL(int) HWACCMR3TermCPU(PVM pVM)
1100{
1101 for (unsigned i=0;i<pVM->cCPUs;i++)
1102 {
1103 PVMCPU pVCpu = &pVM->aCpus[i];
1104
1105 if (pVCpu->hwaccm.s.paStatExitReason)
1106 {
1107 MMHyperFree(pVM, pVCpu->hwaccm.s.paStatExitReason);
1108 pVCpu->hwaccm.s.paStatExitReason = NULL;
1109 pVCpu->hwaccm.s.paStatExitReasonR0 = NIL_RTR0PTR;
1110 }
1111 }
1112 return 0;
1113}
1114
1115/**
1116 * The VM is being reset.
1117 *
1118 * For the HWACCM component this means that any GDT/LDT/TSS monitors
1119 * needs to be removed.
1120 *
1121 * @param pVM VM handle.
1122 */
1123VMMR3DECL(void) HWACCMR3Reset(PVM pVM)
1124{
1125 LogFlow(("HWACCMR3Reset:\n"));
1126
1127 if (pVM->fHWACCMEnabled)
1128 hwaccmR3DisableRawMode(pVM);
1129
1130 for (unsigned i=0;i<pVM->cCPUs;i++)
1131 {
1132 PVMCPU pVCpu = &pVM->aCpus[i];
1133
1134 /* On first entry we'll sync everything. */
1135 pVCpu->hwaccm.s.fContextUseFlags = HWACCM_CHANGED_ALL;
1136
1137 pVCpu->hwaccm.s.vmx.cr0_mask = 0;
1138 pVCpu->hwaccm.s.vmx.cr4_mask = 0;
1139
1140 pVCpu->hwaccm.s.Event.fPending = false;
1141
1142 /* Reset state information for real-mode emulation in VT-x. */
1143 pVCpu->hwaccm.s.vmx.enmCurrGuestMode = PGMMODE_REAL;
1144 }
1145}
1146
1147/**
1148 * Checks if we can currently use hardware accelerated raw mode.
1149 *
1150 * @returns boolean
1151 * @param pVM The VM to operate on.
1152 * @param pCtx Partial VM execution context
1153 */
1154VMMR3DECL(bool) HWACCMR3CanExecuteGuest(PVM pVM, PCPUMCTX pCtx)
1155{
1156 Assert(pVM->fHWACCMEnabled);
1157
1158 /* AMD SVM supports real & protected mode with or without paging. */
1159 if (pVM->hwaccm.s.svm.fEnabled)
1160 {
1161 pVM->hwaccm.s.fActive = true;
1162 return true;
1163 }
1164
1165 pVM->hwaccm.s.fActive = false;
1166
1167 /* Note! The context supplied by REM is partial. If we add more checks here, be sure to verify that REM provides this info! */
1168#ifdef HWACCM_VMX_EMULATE_REALMODE
1169 if (CPUMIsGuestInRealModeEx(pCtx))
1170 {
1171 /* VT-x will not allow high selector bases in v86 mode; fall back to the recompiler in that case.
1172 * The base must also be equal to (sel << 4).
1173 */
1174 if ( ( pCtx->cs != (pCtx->csHid.u64Base >> 4)
1175 && pCtx->csHid.u64Base != 0xffff0000 /* we can deal with the BIOS code as it's also mapped into the lower region. */)
1176 || pCtx->ds != (pCtx->dsHid.u64Base >> 4)
1177 || pCtx->es != (pCtx->esHid.u64Base >> 4)
1178 || pCtx->fs != (pCtx->fsHid.u64Base >> 4)
1179 || pCtx->gs != (pCtx->gsHid.u64Base >> 4)
1180 || pCtx->ss != (pCtx->ssHid.u64Base >> 4))
1181 return false;
1182 }
1183 else
1184 {
1185 PGMMODE enmGuestMode = PGMGetGuestMode(pVM);
1186 /* Verify the requirements for executing code in protected mode. VT-x can't handle the CPU state right after a switch
1187 * from real to protected mode. (all sorts of RPL & DPL assumptions)
1188 */
1189 PVMCPU pVCpu = VMMGetCpu(pVM);
1190
1191 if ( pVCpu->hwaccm.s.vmx.enmCurrGuestMode == PGMMODE_REAL
1192 && enmGuestMode >= PGMMODE_PROTECTED)
1193 {
1194 if ( (pCtx->cs & X86_SEL_RPL)
1195 || (pCtx->ds & X86_SEL_RPL)
1196 || (pCtx->es & X86_SEL_RPL)
1197 || (pCtx->fs & X86_SEL_RPL)
1198 || (pCtx->gs & X86_SEL_RPL)
1199 || (pCtx->ss & X86_SEL_RPL))
1200 {
1201 return false;
1202 }
1203 }
1204 }
1205#else
1206 if (!CPUMIsGuestInLongModeEx(pCtx))
1207 {
1208 /* Too early for VT-x; Solaris guests will fail with a guru meditation otherwise; same for XP. */
1209 if (pCtx->idtr.pIdt == 0 || pCtx->idtr.cbIdt == 0 || pCtx->tr == 0)
1210 return false;
1211
1212 /* The guest is about to complete the switch to protected mode. Wait a bit longer. */
1213 /* Windows XP; switch to protected mode; all selectors are marked not present in the
1214 * hidden registers (possible recompiler bug; see load_seg_vm) */
1215 if (pCtx->csHid.Attr.n.u1Present == 0)
1216 return false;
1217 if (pCtx->ssHid.Attr.n.u1Present == 0)
1218 return false;
1219 }
1220#endif
1221
1222 if (pVM->hwaccm.s.vmx.fEnabled)
1223 {
1224 uint32_t mask;
1225
1226 /* if bit N is set in cr0_fixed0, then it must be set in the guest's cr0. */
1227 mask = (uint32_t)pVM->hwaccm.s.vmx.msr.vmx_cr0_fixed0;
1228 /* Note: We ignore the NE bit here on purpose; see vmmr0\hwaccmr0.cpp for details. */
1229 mask &= ~X86_CR0_NE;
1230
1231#ifdef HWACCM_VMX_EMULATE_REALMODE
1232 /* Note: We ignore the PE & PG bits here on purpose; we emulate real and protected mode without paging. */
1233 mask &= ~(X86_CR0_PG|X86_CR0_PE);
1234#else
1235 /* We support protected mode without paging using identity mapping. */
1236 mask &= ~X86_CR0_PG;
1237#endif
1238 if ((pCtx->cr0 & mask) != mask)
1239 return false;
1240
1241 /* if bit N is cleared in cr0_fixed1, then it must be zero in the guest's cr0. */
1242 mask = (uint32_t)~pVM->hwaccm.s.vmx.msr.vmx_cr0_fixed1;
1243 if ((pCtx->cr0 & mask) != 0)
1244 return false;
1245
1246 /* if bit N is set in cr4_fixed0, then it must be set in the guest's cr4. */
1247 mask = (uint32_t)pVM->hwaccm.s.vmx.msr.vmx_cr4_fixed0;
1248 mask &= ~X86_CR4_VMXE;
1249 if ((pCtx->cr4 & mask) != mask)
1250 return false;
1251
1252 /* if bit N is cleared in cr4_fixed1, then it must be zero in the guest's cr4. */
1253 mask = (uint32_t)~pVM->hwaccm.s.vmx.msr.vmx_cr4_fixed1;
1254 if ((pCtx->cr4 & mask) != 0)
1255 return false;
1256
1257 pVM->hwaccm.s.fActive = true;
1258 return true;
1259 }
1260
1261 return false;
1262}
1263
1264/**
1265 * Checks if we are currently using hardware accelerated raw mode.
1266 *
1267 * @returns boolean
1268 * @param pVM The VM to operate on.
1269 */
1270VMMR3DECL(bool) HWACCMR3IsActive(PVM pVM)
1271{
1272 return pVM->hwaccm.s.fActive;
1273}
1274
1275/**
1276 * Checks if we are currently using nested paging.
1277 *
1278 * @returns boolean
1279 * @param pVM The VM to operate on.
1280 */
1281VMMR3DECL(bool) HWACCMR3IsNestedPagingActive(PVM pVM)
1282{
1283 return pVM->hwaccm.s.fNestedPaging;
1284}
1285
1286/**
1287 * Checks if we are currently using VPID in VT-x mode.
1288 *
1289 * @returns boolean
1290 * @param pVM The VM to operate on.
1291 */
1292VMMR3DECL(bool) HWACCMR3IsVPIDActive(PVM pVM)
1293{
1294 return pVM->hwaccm.s.vmx.fVPID;
1295}
1296
1297
1298/**
1299 * Checks if internal events are pending. In that case we are not allowed to dispatch interrupts.
1300 *
1301 * @returns boolean
1302 * @param pVM The VM to operate on.
1303 */
1304VMMR3DECL(bool) HWACCMR3IsEventPending(PVM pVM)
1305{
1306 /* @todo SMP */
1307 return HWACCMIsEnabled(pVM) && pVM->aCpus[0].hwaccm.s.Event.fPending;
1308}
1309
1310
1311/**
1312 * Inject an NMI into a running VM
1313 *
1314 * @returns boolean
1315 * @param pVM The VM to operate on.
1316 */
1317VMMR3DECL(int) HWACCMR3InjectNMI(PVM pVM)
1318{
1319 pVM->hwaccm.s.fInjectNMI = true;
1320 return VINF_SUCCESS;
1321}
1322
1323/**
1324 * Check fatal VT-x/AMD-V error and produce some meaningful
1325 * log release message.
1326 *
1327 * @param pVM The VM to operate on.
1328 * @param iStatusCode VBox status code
1329 */
1330VMMR3DECL(void) HWACCMR3CheckError(PVM pVM, int iStatusCode)
1331{
1332 for (unsigned i=0;i<pVM->cCPUs;i++)
1333 {
1334 switch(iStatusCode)
1335 {
1336 case VERR_VMX_INVALID_VMCS_FIELD:
1337 break;
1338
1339 case VERR_VMX_INVALID_VMCS_PTR:
1340 LogRel(("VERR_VMX_INVALID_VMCS_PTR: CPU%d Current pointer %RGp vs %RGp\n", i, pVM->aCpus[i].hwaccm.s.vmx.lasterror.u64VMCSPhys, pVM->aCpus[i].hwaccm.s.vmx.pVMCSPhys));
1341 LogRel(("VERR_VMX_INVALID_VMCS_PTR: CPU%d Current VMCS version %x\n", i, pVM->aCpus[i].hwaccm.s.vmx.lasterror.ulVMCSRevision));
1342 LogRel(("VERR_VMX_INVALID_VMCS_PTR: CPU%d Entered Cpu %d\n", i, pVM->aCpus[i].hwaccm.s.vmx.lasterror.idEnteredCpu));
1343 LogRel(("VERR_VMX_INVALID_VMCS_PTR: CPU%d Current Cpu %d\n", i, pVM->aCpus[i].hwaccm.s.vmx.lasterror.idCurrentCpu));
1344 break;
1345
1346 case VERR_VMX_UNABLE_TO_START_VM:
1347 LogRel(("VERR_VMX_UNABLE_TO_START_VM: CPU%d instruction error %x\n", i, pVM->aCpus[i].hwaccm.s.vmx.lasterror.ulInstrError));
1348 LogRel(("VERR_VMX_UNABLE_TO_START_VM: CPU%d exit reason %x\n", i, pVM->aCpus[i].hwaccm.s.vmx.lasterror.ulExitReason));
1349#if 0 /* @todo dump the current control fields to the release log */
1350 if (pVM->aCpus[i].hwaccm.s.vmx.lasterror.ulInstrError == VMX_ERROR_VMENTRY_INVALID_CONTROL_FIELDS)
1351 {
1352
1353 }
1354#endif
1355 break;
1356
1357 case VERR_VMX_UNABLE_TO_RESUME_VM:
1358 LogRel(("VERR_VMX_UNABLE_TO_RESUME_VM: CPU%d instruction error %x\n", i, pVM->aCpus[i].hwaccm.s.vmx.lasterror.ulInstrError));
1359 LogRel(("VERR_VMX_UNABLE_TO_RESUME_VM: CPU%d exit reason %x\n", i, pVM->aCpus[i].hwaccm.s.vmx.lasterror.ulExitReason));
1360 break;
1361
1362 case VERR_VMX_INVALID_VMXON_PTR:
1363 break;
1364 }
1365 }
1366}
1367
1368/**
1369 * Execute state save operation.
1370 *
1371 * @returns VBox status code.
1372 * @param pVM VM Handle.
1373 * @param pSSM SSM operation handle.
1374 */
1375static DECLCALLBACK(int) hwaccmR3Save(PVM pVM, PSSMHANDLE pSSM)
1376{
1377 int rc;
1378
1379 Log(("hwaccmR3Save:\n"));
1380
1381 for (unsigned i=0;i<pVM->cCPUs;i++)
1382 {
1383 /*
1384 * Save the basic bits - fortunately all the other things can be resynced on load.
1385 */
1386 rc = SSMR3PutU32(pSSM, pVM->aCpus[i].hwaccm.s.Event.fPending);
1387 AssertRCReturn(rc, rc);
1388 rc = SSMR3PutU32(pSSM, pVM->aCpus[i].hwaccm.s.Event.errCode);
1389 AssertRCReturn(rc, rc);
1390 rc = SSMR3PutU64(pSSM, pVM->aCpus[i].hwaccm.s.Event.intInfo);
1391 AssertRCReturn(rc, rc);
1392 }
1393
1394 return VINF_SUCCESS;
1395}
1396
1397/**
1398 * Execute state load operation.
1399 *
1400 * @returns VBox status code.
1401 * @param pVM VM Handle.
1402 * @param pSSM SSM operation handle.
1403 * @param u32Version Data layout version.
1404 */
1405static DECLCALLBACK(int) hwaccmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version)
1406{
1407 int rc;
1408
1409 Log(("hwaccmR3Load:\n"));
1410
1411 /*
1412 * Validate version.
1413 */
1414 if (u32Version != HWACCM_SSM_VERSION)
1415 {
1416 AssertMsgFailed(("hwaccmR3Load: Invalid version u32Version=%d!\n", u32Version));
1417 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
1418 }
1419 for (unsigned i=0;i<pVM->cCPUs;i++)
1420 {
1421 rc = SSMR3GetU32(pSSM, &pVM->aCpus[i].hwaccm.s.Event.fPending);
1422 AssertRCReturn(rc, rc);
1423 rc = SSMR3GetU32(pSSM, &pVM->aCpus[i].hwaccm.s.Event.errCode);
1424 AssertRCReturn(rc, rc);
1425 rc = SSMR3GetU64(pSSM, &pVM->aCpus[i].hwaccm.s.Event.intInfo);
1426 AssertRCReturn(rc, rc);
1427 }
1428 return VINF_SUCCESS;
1429}
1430
1431
1432
1433
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