VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/NEMR3.cpp@ 72267

Last change on this file since 72267 was 72267, checked in by vboxsync, 7 years ago

VMM: Added NEMR3IsEnabled to go aloneside HMR3IsEnabled for the debugger and main API.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.0 KB
Line 
1/* $Id: NEMR3.cpp 72267 2018-05-20 23:28:40Z vboxsync $ */
2/** @file
3 * NEM - Native execution manager.
4 */
5
6/*
7 * Copyright (C) 2018 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/** @page pg_nem NEM - Native Execution Manager.
19 *
20 * This is an alternative execution manage to HM and raw-mode. On one host
21 * (Windows) we're forced to use this, on the others we just do it because we
22 * can. Since this is host specific in nature, information about an
23 * implementation is contained in the NEMR3Native-xxxx.cpp files.
24 *
25 * @ref pg_nem_win
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_NEM
33#include <VBox/vmm/nem.h>
34#include "NEMInternal.h"
35#include <VBox/vmm/vm.h>
36#include <VBox/vmm/uvm.h>
37
38#include <iprt/asm.h>
39
40
41
42/**
43 * Basic init and configuration reading.
44 *
45 * Always call NEMR3Term after calling this.
46 *
47 * @returns VBox status code.
48 * @param pVM The cross context VM structure.
49 */
50VMMR3_INT_DECL(int) NEMR3InitConfig(PVM pVM)
51{
52 LogFlow(("NEMR3Init\n"));
53
54 /*
55 * Assert alignment and sizes.
56 */
57 AssertCompileMemberAlignment(VM, nem.s, 64);
58 AssertCompile(sizeof(pVM->nem.s) <= sizeof(pVM->nem.padding));
59
60 /*
61 * Initialize state info so NEMR3Term will always be happy.
62 * No returning prior to setting magics!
63 */
64 pVM->nem.s.u32Magic = NEM_MAGIC;
65 for (VMCPUID iCpu = 0; iCpu < pVM->cCpus; iCpu++)
66 pVM->aCpus[iCpu].nem.s.u32Magic = NEMCPU_MAGIC;
67
68 /*
69 * Read configuration.
70 */
71 PCFGMNODE pCfgNem = CFGMR3GetChild(CFGMR3GetRoot(pVM), "NEM/");
72
73 /*
74 * Validate the NEM settings.
75 */
76 int rc = CFGMR3ValidateConfig(pCfgNem,
77 "/NEM/",
78 "Enabled",
79 "" /* pszValidNodes */, "NEM" /* pszWho */, 0 /* uInstance */);
80 if (RT_FAILURE(rc))
81 return rc;
82
83 /** @cfgm{/NEM/NEMEnabled, bool, true}
84 * Whether NEM is enabled. */
85 rc = CFGMR3QueryBoolDef(pCfgNem, "Enabled", &pVM->nem.s.fEnabled, true);
86 AssertLogRelRCReturn(rc, rc);
87
88 return VINF_SUCCESS;
89}
90
91
92/**
93 * This is called by HMR3Init() when HM cannot be used.
94 *
95 * Sets VM::bMainExecutionEngine to VM_EXEC_ENGINE_NATIVE_API if we can use a
96 * native hypervisor API to execute the VM.
97 *
98 * @returns VBox status code.
99 * @param pVM The cross context VM structure.
100 * @param fFallback Whether this is a fallback call. Cleared if the VM is
101 * configured to use NEM instead of HM.
102 * @param fForced Whether /HM/HMForced was set. If set and we fail to
103 * enable NEM, we'll return a failure status code.
104 * Otherwise we'll assume HMR3Init falls back on raw-mode.
105 */
106VMMR3_INT_DECL(int) NEMR3Init(PVM pVM, bool fFallback, bool fForced)
107{
108 Assert(pVM->bMainExecutionEngine != VM_EXEC_ENGINE_NATIVE_API);
109 int rc;
110 if (pVM->nem.s.fEnabled)
111 {
112#ifdef VBOX_WITH_NATIVE_NEM
113 rc = nemR3NativeInit(pVM, fFallback, fForced);
114 ASMCompilerBarrier(); /* May have changed bMainExecutionEngine. */
115#else
116 RT_NOREF(fFallback);
117 rc = VINF_SUCCESS;
118#endif
119 if (RT_SUCCESS(rc))
120 {
121 if (pVM->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API)
122 LogRel(("NEM: NEMR3Init: Active.\n"));
123 else
124 {
125 LogRel(("NEM: NEMR3Init: Not available.\n"));
126 if (fForced)
127 rc = VERR_NEM_NOT_AVAILABLE;
128 }
129 }
130 else
131 LogRel(("NEM: NEMR3Init: Native init failed: %Rrc.\n", rc));
132 }
133 else
134 {
135 LogRel(("NEM: NEMR3Init: Disabled.\n"));
136 rc = fForced ? VERR_NEM_NOT_ENABLED : VINF_SUCCESS;
137 }
138 return rc;
139}
140
141
142/**
143 * Perform initialization that depends on CPUM working.
144 *
145 * This is a noop if NEM wasn't activated by a previous NEMR3Init() call.
146 *
147 * @returns VBox status code.
148 * @param pVM The cross context VM structure.
149 */
150VMMR3_INT_DECL(int) NEMR3InitAfterCPUM(PVM pVM)
151{
152 int rc = VINF_SUCCESS;
153#ifdef VBOX_WITH_NATIVE_NEM
154 if (pVM->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API)
155 rc = nemR3NativeInitAfterCPUM(pVM);
156#else
157 RT_NOREF(pVM);
158#endif
159 return rc;
160}
161
162
163/**
164 * Called when a init phase has completed.
165 *
166 * @returns VBox status code.
167 * @param pVM The cross context VM structure.
168 * @param enmWhat The phase that completed.
169 */
170VMMR3_INT_DECL(int) NEMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat)
171{
172 int rc = VINF_SUCCESS;
173#ifdef VBOX_WITH_NATIVE_NEM
174 if (pVM->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API)
175 rc = nemR3NativeInitCompleted(pVM, enmWhat);
176#else
177 RT_NOREF(pVM, enmWhat);
178#endif
179 return rc;
180}
181
182
183/**
184 *
185 * @returns VBox status code.
186 * @param pVM The cross context VM structure.
187 */
188VMMR3_INT_DECL(int) NEMR3Term(PVM pVM)
189{
190 AssertReturn(pVM->nem.s.u32Magic == NEM_MAGIC, VERR_WRONG_ORDER);
191 for (VMCPUID iCpu = 0; iCpu < pVM->cCpus; iCpu++)
192 AssertReturn(pVM->aCpus[iCpu].nem.s.u32Magic == NEMCPU_MAGIC, VERR_WRONG_ORDER);
193
194 /* Do native termination. */
195 int rc = VINF_SUCCESS;
196#ifdef VBOX_WITH_NATIVE_NEM
197 if (pVM->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API)
198 rc = nemR3NativeTerm(pVM);
199#endif
200
201 /* Mark it as terminated. */
202 for (VMCPUID iCpu = 0; iCpu < pVM->cCpus; iCpu++)
203 pVM->aCpus[iCpu].nem.s.u32Magic = NEMCPU_MAGIC_DEAD;
204 pVM->nem.s.u32Magic = NEM_MAGIC_DEAD;
205 return rc;
206}
207
208/**
209 * External interface for querying whether native execution API is used.
210 *
211 * @returns true if NEM is being used, otherwise false.
212 * @param pUVM The user mode VM handle.
213 * @sa HMR3IsEnabled
214 */
215VMMR3DECL(bool) NEMR3IsEnabled(PUVM pUVM)
216{
217 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
218 PVM pVM = pUVM->pVM;
219 VM_ASSERT_VALID_EXT_RETURN(pVM, false);
220 return VM_IS_NEM_ENABLED(pVM);
221}
222
223
224/**
225 * The VM is being reset.
226 *
227 * @param pVM The cross context VM structure.
228 */
229VMMR3_INT_DECL(void) NEMR3Reset(PVM pVM)
230{
231#ifdef VBOX_WITH_NATIVE_NEM
232 if (pVM->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API)
233 nemR3NativeReset(pVM);
234#else
235 RT_NOREF(pVM);
236#endif
237}
238
239
240/**
241 * Resets a virtual CPU.
242 *
243 * Used to bring up secondary CPUs on SMP as well as CPU hot plugging.
244 *
245 * @param pVCpu The cross context virtual CPU structure to reset.
246 * @param fInitIpi Set if being reset due to INIT IPI.
247 */
248VMMR3_INT_DECL(void) NEMR3ResetCpu(PVMCPU pVCpu, bool fInitIpi)
249{
250#ifdef VBOX_WITH_NATIVE_NEM
251 if (pVCpu->pVMR3->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API)
252 nemR3NativeResetCpu(pVCpu, fInitIpi);
253#else
254 RT_NOREF(pVCpu, fInitIpi);
255#endif
256}
257
258
259VMMR3_INT_DECL(VBOXSTRICTRC) NEMR3RunGC(PVM pVM, PVMCPU pVCpu)
260{
261 Assert(VM_IS_NEM_ENABLED(pVM));
262#ifdef VBOX_WITH_NATIVE_NEM
263 return nemR3NativeRunGC(pVM, pVCpu);
264#else
265 NOREF(pVM); NOREF(pVCpu);
266 return VERR_INTERNAL_ERROR_3;
267#endif
268}
269
270
271VMMR3_INT_DECL(bool) NEMR3CanExecuteGuest(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
272{
273 Assert(VM_IS_NEM_ENABLED(pVM));
274#ifdef VBOX_WITH_NATIVE_NEM
275 return nemR3NativeCanExecuteGuest(pVM, pVCpu, pCtx);
276#else
277 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx);
278 return false;
279#endif
280}
281
282
283VMMR3_INT_DECL(bool) NEMR3SetSingleInstruction(PVM pVM, PVMCPU pVCpu, bool fEnable)
284{
285 Assert(VM_IS_NEM_ENABLED(pVM));
286#ifdef VBOX_WITH_NATIVE_NEM
287 return nemR3NativeSetSingleInstruction(pVM, pVCpu, fEnable);
288#else
289 NOREF(pVM); NOREF(pVCpu); NOREF(fEnable);
290 return false;
291#endif
292}
293
294
295VMMR3_INT_DECL(void) NEMR3NotifyFF(PVM pVM, PVMCPU pVCpu, uint32_t fFlags)
296{
297 AssertLogRelReturnVoid(VM_IS_NEM_ENABLED(pVM));
298#ifdef VBOX_WITH_NATIVE_NEM
299 nemR3NativeNotifyFF(pVM, pVCpu, fFlags);
300#else
301 RT_NOREF(pVM, pVCpu, fFlags);
302#endif
303}
304
305
306
307
308VMMR3_INT_DECL(int) NEMR3NotifyPhysRamRegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb)
309{
310 int rc = VINF_SUCCESS;
311#ifdef VBOX_WITH_NATIVE_NEM
312 if (pVM->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API)
313 rc = nemR3NativeNotifyPhysRamRegister(pVM, GCPhys, cb);
314#else
315 NOREF(pVM); NOREF(GCPhys); NOREF(cb);
316#endif
317 return rc;
318}
319
320
321VMMR3_INT_DECL(int) NEMR3NotifyPhysMmioExMap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags, void *pvMmio2)
322{
323 int rc = VINF_SUCCESS;
324#ifdef VBOX_WITH_NATIVE_NEM
325 if (pVM->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API)
326 rc = nemR3NativeNotifyPhysMmioExMap(pVM, GCPhys, cb, fFlags, pvMmio2);
327#else
328 NOREF(pVM); NOREF(GCPhys); NOREF(cb); NOREF(fFlags); NOREF(pvMmio2);
329#endif
330 return rc;
331}
332
333
334VMMR3_INT_DECL(int) NEMR3NotifyPhysMmioExUnmap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags)
335{
336 int rc = VINF_SUCCESS;
337#ifdef VBOX_WITH_NATIVE_NEM
338 if (pVM->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API)
339 rc = nemR3NativeNotifyPhysMmioExUnmap(pVM, GCPhys, cb, fFlags);
340#else
341 NOREF(pVM); NOREF(GCPhys); NOREF(cb); NOREF(fFlags);
342#endif
343 return rc;
344}
345
346
347VMMR3_INT_DECL(int) NEMR3NotifyPhysRomRegisterEarly(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags)
348{
349 int rc = VINF_SUCCESS;
350#ifdef VBOX_WITH_NATIVE_NEM
351 if (pVM->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API)
352 rc = nemR3NativeNotifyPhysRomRegisterEarly(pVM, GCPhys, cb, fFlags);
353#else
354 NOREF(pVM); NOREF(GCPhys); NOREF(cb); NOREF(fFlags);
355#endif
356 return rc;
357}
358
359
360/**
361 * Called after the ROM range has been fully completed.
362 *
363 * This will be preceeded by a NEMR3NotifyPhysRomRegisterEarly() call as well a
364 * number of NEMHCNotifyPhysPageProtChanged calls.
365 *
366 * @returns VBox status code
367 * @param pVM The cross context VM structure.
368 * @param GCPhys The ROM address (page aligned).
369 * @param cb The size (page aligned).
370 * @param fFlags NEM_NOTIFY_PHYS_ROM_F_XXX.
371 */
372VMMR3_INT_DECL(int) NEMR3NotifyPhysRomRegisterLate(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags)
373{
374 int rc = VINF_SUCCESS;
375#ifdef VBOX_WITH_NATIVE_NEM
376 if (pVM->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API)
377 rc = nemR3NativeNotifyPhysRomRegisterLate(pVM, GCPhys, cb, fFlags);
378#else
379 NOREF(pVM); NOREF(GCPhys); NOREF(cb); NOREF(fFlags);
380#endif
381 return rc;
382}
383
384
385VMMR3_INT_DECL(void) NEMR3NotifySetA20(PVMCPU pVCpu, bool fEnabled)
386{
387#ifdef VBOX_WITH_NATIVE_NEM
388 if (pVCpu->pVMR3->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API)
389 nemR3NativeNotifySetA20(pVCpu, fEnabled);
390#else
391 NOREF(pVCpu); NOREF(fEnabled);
392#endif
393}
394
Note: See TracBrowser for help on using the repository browser.

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