VirtualBox

source: vbox/trunk/src/VBox/VMM/VM.cpp@ 13667

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

#1865: VM.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 92.2 KB
Line 
1/* $Id: VM.cpp 13667 2008-10-29 18:27:15Z vboxsync $ */
2/** @file
3 * VM - Virtual Machine
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/** @page pg_vm VM API
23 *
24 * This is the encapsulating bit. It provides the APIs that Main and VBoxBFE
25 * use to create a VMM instance for running a guest in. It also provides
26 * facilities for queuing request for execution in EMT (serialization purposes
27 * mostly) and for reporting error back to the VMM user (Main/VBoxBFE).
28 *
29 *
30 * @section sec_vm_design Design Critique / Things To Do
31 *
32 * In hindsight this component is a big design mistake, all this stuff really
33 * belongs in the VMM component. It just seemed like a kind of ok idea at a
34 * time when the VMM bit was a bit vague. 'VM' also happend to be the name of
35 * the per-VM instance structure (see vm.h), so it kind of made sense. However
36 * as it turned out, VMM(.cpp) is almost empty all it provides in ring-3 is some
37 * minor functionally and some "routing" services.
38 *
39 * Fixing this is just a matter of some more or less straight forward
40 * refactoring, the question is just when someone will get to it.
41 *
42 */
43
44/*******************************************************************************
45* Header Files *
46*******************************************************************************/
47#define LOG_GROUP LOG_GROUP_VM
48#include <VBox/cfgm.h>
49#include <VBox/vmm.h>
50#include <VBox/gvmm.h>
51#include <VBox/mm.h>
52#include <VBox/cpum.h>
53#include <VBox/selm.h>
54#include <VBox/trpm.h>
55#include <VBox/dbgf.h>
56#include <VBox/pgm.h>
57#include <VBox/pdmapi.h>
58#include <VBox/pdmcritsect.h>
59#include <VBox/em.h>
60#include <VBox/rem.h>
61#include <VBox/tm.h>
62#include <VBox/stam.h>
63#include <VBox/patm.h>
64#ifdef VBOX_WITH_VMI
65# include <VBox/parav.h>
66#endif
67#include <VBox/csam.h>
68#include <VBox/iom.h>
69#include <VBox/ssm.h>
70#include <VBox/hwaccm.h>
71#include "VMInternal.h"
72#include <VBox/vm.h>
73#include <VBox/uvm.h>
74
75#include <VBox/sup.h>
76#include <VBox/dbg.h>
77#include <VBox/err.h>
78#include <VBox/param.h>
79#include <VBox/log.h>
80#include <iprt/assert.h>
81#include <iprt/alloc.h>
82#include <iprt/asm.h>
83#include <iprt/env.h>
84#include <iprt/string.h>
85#include <iprt/time.h>
86#include <iprt/semaphore.h>
87#include <iprt/thread.h>
88
89
90/*******************************************************************************
91* Structures and Typedefs *
92*******************************************************************************/
93/**
94 * VM destruction callback registration record.
95 */
96typedef struct VMATDTOR
97{
98 /** Pointer to the next record in the list. */
99 struct VMATDTOR *pNext;
100 /** Pointer to the callback function. */
101 PFNVMATDTOR pfnAtDtor;
102 /** The user argument. */
103 void *pvUser;
104} VMATDTOR;
105/** Pointer to a VM destruction callback registration record. */
106typedef VMATDTOR *PVMATDTOR;
107
108
109/*******************************************************************************
110* Global Variables *
111*******************************************************************************/
112/** Pointer to the list of VMs. */
113static PUVM g_pUVMsHead = NULL;
114
115/** Pointer to the list of at VM destruction callbacks. */
116static PVMATDTOR g_pVMAtDtorHead = NULL;
117/** Lock the g_pVMAtDtorHead list. */
118#define VM_ATDTOR_LOCK() do { } while (0)
119/** Unlock the g_pVMAtDtorHead list. */
120#define VM_ATDTOR_UNLOCK() do { } while (0)
121
122
123/*******************************************************************************
124* Internal Functions *
125*******************************************************************************/
126static int vmR3CreateUVM(PUVM *ppUVM);
127static int vmR3CreateU(PUVM pUVM, PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUserCFGM);
128static int vmR3InitRing3(PVM pVM, PUVM pUVM);
129static int vmR3InitRing0(PVM pVM);
130static int vmR3InitGC(PVM pVM);
131static int vmR3InitDoCompleted(PVM pVM, VMINITCOMPLETED enmWhat);
132static DECLCALLBACK(int) vmR3PowerOn(PVM pVM);
133static DECLCALLBACK(int) vmR3Suspend(PVM pVM);
134static DECLCALLBACK(int) vmR3Resume(PVM pVM);
135static DECLCALLBACK(int) vmR3Save(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser);
136static DECLCALLBACK(int) vmR3Load(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser);
137static DECLCALLBACK(int) vmR3PowerOff(PVM pVM);
138static void vmR3DestroyUVM(PUVM pUVM);
139static void vmR3AtDtor(PVM pVM);
140static int vmR3AtResetU(PUVM pUVM);
141static DECLCALLBACK(int) vmR3Reset(PVM pVM);
142static DECLCALLBACK(int) vmR3AtStateRegisterU(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser);
143static DECLCALLBACK(int) vmR3AtStateDeregisterU(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser);
144static DECLCALLBACK(int) vmR3AtErrorRegisterU(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser);
145static DECLCALLBACK(int) vmR3AtErrorDeregisterU(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser);
146static int vmR3SetErrorU(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...);
147static DECLCALLBACK(int) vmR3AtRuntimeErrorRegisterU(PUVM pUVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser);
148static DECLCALLBACK(int) vmR3AtRuntimeErrorDeregisterU(PUVM pUVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser);
149
150
151/**
152 * Do global VMM init.
153 *
154 * @returns VBox status code.
155 */
156VMMR3DECL(int) VMR3GlobalInit(void)
157{
158 /*
159 * Only once.
160 */
161 static bool volatile s_fDone = false;
162 if (s_fDone)
163 return VINF_SUCCESS;
164
165 /*
166 * We're done.
167 */
168 s_fDone = true;
169 return VINF_SUCCESS;
170}
171
172
173
174/**
175 * Creates a virtual machine by calling the supplied configuration constructor.
176 *
177 * On successful returned the VM is powered, i.e. VMR3PowerOn() should be
178 * called to start the execution.
179 *
180 * @returns 0 on success.
181 * @returns VBox error code on failure.
182 * @param pfnVMAtError Pointer to callback function for setting VM errors.
183 * This is called in the EM.
184 * @param pvUserVM The user argument passed to pfnVMAtError.
185 * @param pfnCFGMConstructor Pointer to callback function for constructing the VM configuration tree.
186 * This is called in the EM.
187 * @param pvUserCFGM The user argument passed to pfnCFGMConstructor.
188 * @param ppVM Where to store the 'handle' of the created VM.
189 */
190VMMR3DECL(int) VMR3Create(PFNVMATERROR pfnVMAtError, void *pvUserVM, PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUserCFGM, PVM *ppVM)
191{
192 LogFlow(("VMR3Create: pfnVMAtError=%p pvUserVM=%p pfnCFGMConstructor=%p pvUserCFGM=%p ppVM=%p\n", pfnVMAtError, pvUserVM, pfnCFGMConstructor, pvUserCFGM, ppVM));
193
194 /*
195 * Because of the current hackiness of the applications
196 * we'll have to initialize global stuff from here.
197 * Later the applications will take care of this in a proper way.
198 */
199 static bool fGlobalInitDone = false;
200 if (!fGlobalInitDone)
201 {
202 int rc = VMR3GlobalInit();
203 if (VBOX_FAILURE(rc))
204 return rc;
205 fGlobalInitDone = true;
206 }
207
208 /*
209 * Create the UVM so we can register the at-error callback
210 * and consoliate a bit of cleanup code.
211 */
212 PUVM pUVM;
213 int rc = vmR3CreateUVM(&pUVM);
214 if (RT_FAILURE(rc))
215 return rc;
216 if (pfnVMAtError)
217 rc = VMR3AtErrorRegisterU(pUVM, pfnVMAtError, pvUserVM);
218 if (RT_SUCCESS(rc))
219 {
220 /*
221 * Initialize the support library creating the session for this v
222 */
223 rc = SUPR3Init(&pUVM->vm.s.pSession);
224 if (RT_SUCCESS(rc))
225 {
226 /*
227 * Call vmR3CreateU in the EMT thread and wait for it to finish.
228 */
229 PVMREQ pReq;
230 rc = VMR3ReqCallU(pUVM, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)vmR3CreateU,
231 3, pUVM, pfnCFGMConstructor, pvUserCFGM);
232 if (RT_SUCCESS(rc))
233 {
234 rc = pReq->iStatus;
235 VMR3ReqFree(pReq);
236 if (RT_SUCCESS(rc))
237 {
238 /*
239 * Success!
240 */
241 *ppVM = pUVM->pVM;
242 LogFlow(("VMR3Create: returns VINF_SUCCESS *ppVM=%p\n", *ppVM));
243 return VINF_SUCCESS;
244 }
245 }
246 else
247 AssertMsgFailed(("VMR3ReqCall failed rc=%Vrc\n", rc));
248
249 /*
250 * An error occurred during VM creation. Set the error message directly
251 * using the initial callback, as the callback list doesn't exist yet.
252 */
253 const char *pszError = NULL;
254 switch (rc)
255 {
256 case VERR_VMX_IN_VMX_ROOT_MODE:
257#ifdef RT_OS_LINUX
258 pszError = N_("VirtualBox can't operate in VMX root mode. "
259 "Please disable the KVM kernel extension, recompile your kernel and reboot");
260#else
261 pszError = N_("VirtualBox can't operate in VMX root mode. Please close all other virtualization programs.");
262#endif
263 break;
264
265 default:
266 pszError = N_("Unknown error creating VM");
267 break;
268 }
269 vmR3SetErrorU(pUVM, rc, RT_SRC_POS, pszError, rc);
270 }
271 else
272 {
273 /*
274 * An error occurred at support library initialization time (before the
275 * VM could be created). Set the error message directly using the
276 * initial callback, as the callback list doesn't exist yet.
277 */
278 const char *pszError;
279 switch (rc)
280 {
281 case VERR_VM_DRIVER_LOAD_ERROR:
282#ifdef RT_OS_LINUX
283 pszError = N_("VirtualBox kernel driver not loaded. The vboxdrv kernel module "
284 "was either not loaded or /dev/vboxdrv is not set up properly. "
285 "Re-setup the kernel module by executing "
286 "'/etc/init.d/vboxdrv setup' as root");
287#else
288 pszError = N_("VirtualBox kernel driver not loaded");
289#endif
290 break;
291 case VERR_VM_DRIVER_OPEN_ERROR:
292 pszError = N_("VirtualBox kernel driver cannot be opened");
293 break;
294 case VERR_VM_DRIVER_NOT_ACCESSIBLE:
295#ifdef VBOX_WITH_HARDENING
296 /* This should only happen if the executable wasn't hardened - bad code/build. */
297 pszError = N_("VirtualBox kernel driver not accessible, permission problem. "
298 "Re-install VirtualBox. If you are building it yourself, you "
299 "should make sure it installed correctly and that the setuid "
300 "bit is set on the executables calling VMR3Create.");
301#else
302 /* This should only happen when mixing builds or with the usual /dev/vboxdrv access issues. */
303# if defined(RT_OS_DARWIN)
304 pszError = N_("VirtualBox KEXT is not accessible, permission problem. "
305 "If you have built VirtualBox yourself, make sure that you do not "
306 "have the vboxdrv KEXT from a different build or installation loaded.");
307# elif defined(RT_OS_LINUX)
308 pszError = N_("VirtualBox kernel driver is not accessible, permission problem. "
309 "If you have built VirtualBox yourself, make sure that you do "
310 "not have the vboxdrv kernel module from a different build or "
311 "installation loaded. Also, make sure the vboxdrv udev rule gives "
312 "you the permission you need to access the device.");
313# elif defined(RT_OS_WINDOWS)
314 pszError = N_("VirtualBox kernel driver is not accessible, permission problem.");
315# else /* solaris, freebsd, ++. */
316 pszError = N_("VirtualBox kernel module is not accessible, permission problem. "
317 "If you have built VirtualBox yourself, make sure that you do "
318 "not have the vboxdrv kernel module from a different install loaded.");
319# endif
320#endif
321 break;
322 case VERR_INVALID_HANDLE: /** @todo track down and fix this error. */
323 case VERR_VM_DRIVER_NOT_INSTALLED:
324#ifdef RT_OS_LINUX
325 pszError = N_("VirtualBox kernel driver not installed. The vboxdrv kernel module "
326 "was either not loaded or /dev/vboxdrv was not created for some "
327 "reason. Re-setup the kernel module by executing "
328 "'/etc/init.d/vboxdrv setup' as root");
329#else
330 pszError = N_("VirtualBox kernel driver not installed");
331#endif
332 break;
333 case VERR_NO_MEMORY:
334 pszError = N_("VirtualBox support library out of memory");
335 break;
336 case VERR_VERSION_MISMATCH:
337 case VERR_VM_DRIVER_VERSION_MISMATCH:
338 pszError = N_("The VirtualBox support driver which is running is from a different "
339 "version of VirtualBox. You can correct this by stopping all "
340 "running instances of VirtualBox and reinstalling the software.");
341 break;
342 default:
343 pszError = N_("Unknown error initializing kernel driver");
344 AssertMsgFailed(("Add error message for rc=%d (%Vrc)\n", rc, rc));
345 }
346 vmR3SetErrorU(pUVM, rc, RT_SRC_POS, pszError, rc);
347 }
348 }
349
350 /* cleanup */
351 vmR3DestroyUVM(pUVM);
352 LogFlow(("VMR3Create: returns %Vrc\n", rc));
353 return rc;
354}
355
356
357/**
358 * Creates the UVM.
359 *
360 * This will not initialize the support library even if vmR3DestroyUVM
361 * will terminate that.
362 *
363 * @returns VBox status code.
364 * @param ppUVM Where to store the UVM pointer.
365 */
366static int vmR3CreateUVM(PUVM *ppUVM)
367{
368 /*
369 * Create the UVM, initialize the fundamental stuff (VM+MMR3Heap+STAM)
370 * and start the emulation thread (EMT).
371 */
372 PUVM pUVM = (PUVM)RTMemAllocZ(sizeof(*pUVM));
373 AssertReturn(pUVM, VERR_NO_MEMORY);
374 pUVM->u32Magic = UVM_MAGIC;
375
376 AssertCompile(sizeof(pUVM->vm.s) <= sizeof(pUVM->vm.padding));
377 AssertRelease(sizeof(pUVM->vm.s) <= sizeof(pUVM->vm.padding));
378
379 pUVM->vm.s.ppAtResetNext = &pUVM->vm.s.pAtReset;
380 pUVM->vm.s.ppAtStateNext = &pUVM->vm.s.pAtState;
381 pUVM->vm.s.ppAtErrorNext = &pUVM->vm.s.pAtError;
382 pUVM->vm.s.ppAtRuntimeErrorNext = &pUVM->vm.s.pAtRuntimeError;
383 pUVM->vm.s.enmHaltMethod = VMHALTMETHOD_BOOTSTRAP;
384 int rc = RTSemEventCreate(&pUVM->vm.s.EventSemWait);
385 if (RT_SUCCESS(rc))
386 {
387 rc = STAMR3InitUVM(pUVM);
388 if (RT_SUCCESS(rc))
389 {
390 rc = MMR3InitUVM(pUVM);
391 if (RT_SUCCESS(rc))
392 {
393 rc = PDMR3InitUVM(pUVM);
394 if (RT_SUCCESS(rc))
395 {
396
397 rc = RTThreadCreate(&pUVM->vm.s.ThreadEMT, vmR3EmulationThread, pUVM, _1M,
398 RTTHREADTYPE_EMULATION, RTTHREADFLAGS_WAITABLE, "EMT");
399 if (RT_SUCCESS(rc))
400 {
401 *ppUVM = pUVM;
402 return VINF_SUCCESS;
403 }
404
405 /* bail out. */
406 PDMR3TermUVM(pUVM);
407 }
408 MMR3TermUVM(pUVM);
409 }
410 STAMR3TermUVM(pUVM);
411 }
412 RTSemEventDestroy(pUVM->vm.s.EventSemWait);
413 }
414 RTMemFree(pUVM);
415 return rc;
416}
417
418
419/**
420 * Creates and initializes the VM.
421 *
422 * @thread EMT
423 */
424static int vmR3CreateU(PUVM pUVM, PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUserCFGM)
425{
426 int rc = VINF_SUCCESS;
427
428 /*
429 * Load the VMMR0.r0 module so that we can call GVMMR0CreateVM.
430 */
431 rc = PDMR3LdrLoadVMMR0U(pUVM);
432 if (RT_FAILURE(rc))
433 {
434 /** @todo we need a cleaner solution for this (VERR_VMX_IN_VMX_ROOT_MODE).
435 * bird: what about moving the message down here? Main picks the first message, right? */
436 if (rc == VERR_VMX_IN_VMX_ROOT_MODE)
437 return rc; /* proper error message set later on */
438 return vmR3SetErrorU(pUVM, rc, RT_SRC_POS, N_("Failed to load VMMR0.r0"));
439 }
440
441 /*
442 * Request GVMM to create a new VM for us.
443 */
444 GVMMCREATEVMREQ CreateVMReq;
445 CreateVMReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
446 CreateVMReq.Hdr.cbReq = sizeof(CreateVMReq);
447 CreateVMReq.pSession = pUVM->vm.s.pSession;
448 CreateVMReq.pVMR0 = NIL_RTR0PTR;
449 CreateVMReq.pVMR3 = NULL;
450 rc = SUPCallVMMR0Ex(NIL_RTR0PTR, VMMR0_DO_GVMM_CREATE_VM, 0, &CreateVMReq.Hdr);
451 if (RT_SUCCESS(rc))
452 {
453 PVM pVM = pUVM->pVM = CreateVMReq.pVMR3;
454 AssertRelease(VALID_PTR(pVM));
455 AssertRelease(pVM->pVMR0 == CreateVMReq.pVMR0);
456 AssertRelease(pVM->pSession == pUVM->vm.s.pSession);
457
458 Log(("VMR3Create: Created pUVM=%p pVM=%p pVMR0=%p hSelf=%#x \n", pUVM, pVM, pVM->pVMR0, pVM->hSelf));
459
460 /*
461 * Initialize the VM structure and our internal data (VMINT).
462 */
463 pVM->pUVM = pUVM;
464 pVM->ThreadEMT = pVM->aCpus[0].hThreadR3 = pUVM->vm.s.ThreadEMT;
465 pVM->NativeThreadEMT = pVM->aCpus[0].hNativeThreadR3 = pUVM->vm.s.NativeThreadEMT;
466
467 /*
468 * Init the configuration.
469 */
470 rc = CFGMR3Init(pVM, pfnCFGMConstructor, pvUserCFGM);
471 if (VBOX_SUCCESS(rc))
472 {
473 /*
474 * If executing in fake suplib mode disable RR3 and RR0 in the config.
475 */
476 const char *psz = RTEnvGet("VBOX_SUPLIB_FAKE");
477 if (psz && !strcmp(psz, "fake"))
478 {
479 CFGMR3RemoveValue(CFGMR3GetRoot(pVM), "RawR3Enabled");
480 CFGMR3InsertInteger(CFGMR3GetRoot(pVM), "RawR3Enabled", 0);
481 CFGMR3RemoveValue(CFGMR3GetRoot(pVM), "RawR0Enabled");
482 CFGMR3InsertInteger(CFGMR3GetRoot(pVM), "RawR0Enabled", 0);
483 }
484
485 /*
486 * Init the Ring-3 components and do a round of relocations with 0 delta.
487 */
488 rc = vmR3InitRing3(pVM, pUVM);
489 if (VBOX_SUCCESS(rc))
490 {
491 VMR3Relocate(pVM, 0);
492 LogFlow(("Ring-3 init succeeded\n"));
493
494 /*
495 * Init the Ring-0 components.
496 */
497 rc = vmR3InitRing0(pVM);
498 if (VBOX_SUCCESS(rc))
499 {
500 /* Relocate again, because some switcher fixups depends on R0 init results. */
501 VMR3Relocate(pVM, 0);
502
503#ifdef VBOX_WITH_DEBUGGER
504 /*
505 * Init the tcp debugger console if we're building
506 * with debugger support.
507 */
508 void *pvUser = NULL;
509 rc = DBGCTcpCreate(pVM, &pvUser);
510 if ( VBOX_SUCCESS(rc)
511 || rc == VERR_NET_ADDRESS_IN_USE)
512 {
513 pUVM->vm.s.pvDBGC = pvUser;
514#endif
515 /*
516 * Init the Guest Context components.
517 */
518 rc = vmR3InitGC(pVM);
519 if (VBOX_SUCCESS(rc))
520 {
521 /*
522 * Now we can safely set the VM halt method to default.
523 */
524 rc = vmR3SetHaltMethodU(pUVM, VMHALTMETHOD_DEFAULT);
525 if (RT_SUCCESS(rc))
526 {
527 /*
528 * Set the state and link into the global list.
529 */
530 vmR3SetState(pVM, VMSTATE_CREATED);
531 pUVM->pNext = g_pUVMsHead;
532 g_pUVMsHead = pUVM;
533 return VINF_SUCCESS;
534 }
535 }
536#ifdef VBOX_WITH_DEBUGGER
537 DBGCTcpTerminate(pVM, pUVM->vm.s.pvDBGC);
538 pUVM->vm.s.pvDBGC = NULL;
539 }
540#endif
541 //..
542 }
543 vmR3Destroy(pVM);
544 }
545 //..
546
547 /* Clean CFGM. */
548 int rc2 = CFGMR3Term(pVM);
549 AssertRC(rc2);
550 }
551
552 /* Tell GVMM that it can destroy the VM now. */
553 int rc2 = SUPCallVMMR0Ex(CreateVMReq.pVMR0, VMMR0_DO_GVMM_DESTROY_VM, 0, NULL);
554 AssertRC(rc2);
555 pUVM->pVM = NULL;
556 }
557 else
558 vmR3SetErrorU(pUVM, rc, RT_SRC_POS, N_("VM creation failed (GVMM)"));
559
560 LogFlow(("vmR3Create: returns %Rrc\n", rc));
561 return rc;
562}
563
564
565/**
566 * Initializes all R3 components of the VM
567 */
568static int vmR3InitRing3(PVM pVM, PUVM pUVM)
569{
570 int rc;
571
572 /*
573 * Init all R3 components, the order here might be important.
574 */
575 rc = MMR3Init(pVM);
576 if (VBOX_SUCCESS(rc))
577 {
578 STAM_REG(pVM, &pVM->StatTotalInGC, STAMTYPE_PROFILE_ADV, "/PROF/VM/InGC", STAMUNIT_TICKS_PER_CALL, "Profiling the total time spent in GC.");
579 STAM_REG(pVM, &pVM->StatSwitcherToGC, STAMTYPE_PROFILE_ADV, "/PROF/VM/SwitchToGC", STAMUNIT_TICKS_PER_CALL, "Profiling switching to GC.");
580 STAM_REG(pVM, &pVM->StatSwitcherToHC, STAMTYPE_PROFILE_ADV, "/PROF/VM/SwitchToHC", STAMUNIT_TICKS_PER_CALL, "Profiling switching to HC.");
581 STAM_REG(pVM, &pVM->StatSwitcherSaveRegs, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/SaveRegs", STAMUNIT_TICKS_PER_CALL,"Profiling switching to GC.");
582 STAM_REG(pVM, &pVM->StatSwitcherSysEnter, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/SysEnter", STAMUNIT_TICKS_PER_CALL,"Profiling switching to GC.");
583 STAM_REG(pVM, &pVM->StatSwitcherDebug, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/Debug", STAMUNIT_TICKS_PER_CALL,"Profiling switching to GC.");
584 STAM_REG(pVM, &pVM->StatSwitcherCR0, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/CR0", STAMUNIT_TICKS_PER_CALL, "Profiling switching to GC.");
585 STAM_REG(pVM, &pVM->StatSwitcherCR4, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/CR4", STAMUNIT_TICKS_PER_CALL, "Profiling switching to GC.");
586 STAM_REG(pVM, &pVM->StatSwitcherLgdt, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/Lgdt", STAMUNIT_TICKS_PER_CALL, "Profiling switching to GC.");
587 STAM_REG(pVM, &pVM->StatSwitcherLidt, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/Lidt", STAMUNIT_TICKS_PER_CALL, "Profiling switching to GC.");
588 STAM_REG(pVM, &pVM->StatSwitcherLldt, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/Lldt", STAMUNIT_TICKS_PER_CALL, "Profiling switching to GC.");
589 STAM_REG(pVM, &pVM->StatSwitcherTSS, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/TSS", STAMUNIT_TICKS_PER_CALL, "Profiling switching to GC.");
590 STAM_REG(pVM, &pVM->StatSwitcherJmpCR3, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/JmpCR3", STAMUNIT_TICKS_PER_CALL,"Profiling switching to GC.");
591 STAM_REG(pVM, &pVM->StatSwitcherRstrRegs, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/RstrRegs", STAMUNIT_TICKS_PER_CALL,"Profiling switching to GC.");
592
593 STAM_REL_REG(pVM, &pUVM->vm.s.StatHaltYield, STAMTYPE_PROFILE, "/PROF/VM/Halt/Yield", STAMUNIT_TICKS_PER_CALL, "Profiling halted state yielding.");
594 STAM_REL_REG(pVM, &pUVM->vm.s.StatHaltBlock, STAMTYPE_PROFILE, "/PROF/VM/Halt/Block", STAMUNIT_TICKS_PER_CALL, "Profiling halted state blocking.");
595 STAM_REL_REG(pVM, &pUVM->vm.s.StatHaltTimers,STAMTYPE_PROFILE, "/PROF/VM/Halt/Timers", STAMUNIT_TICKS_PER_CALL, "Profiling halted state timer tasks.");
596 STAM_REL_REG(pVM, &pUVM->vm.s.StatHaltPoll, STAMTYPE_PROFILE, "/PROF/VM/Halt/Poll", STAMUNIT_TICKS_PER_CALL, "Profiling halted state poll tasks.");
597
598 STAM_REG(pVM, &pUVM->vm.s.StatReqAllocNew, STAMTYPE_COUNTER, "/VM/Req/AllocNew", STAMUNIT_OCCURENCES, "Number of VMR3ReqAlloc returning a new packet.");
599 STAM_REG(pVM, &pUVM->vm.s.StatReqAllocRaces, STAMTYPE_COUNTER, "/VM/Req/AllocRaces", STAMUNIT_OCCURENCES, "Number of VMR3ReqAlloc causing races.");
600 STAM_REG(pVM, &pUVM->vm.s.StatReqAllocRecycled, STAMTYPE_COUNTER, "/VM/Req/AllocRecycled", STAMUNIT_OCCURENCES, "Number of VMR3ReqAlloc returning a recycled packet.");
601 STAM_REG(pVM, &pUVM->vm.s.StatReqFree, STAMTYPE_COUNTER, "/VM/Req/Free", STAMUNIT_OCCURENCES, "Number of VMR3ReqFree calls.");
602 STAM_REG(pVM, &pUVM->vm.s.StatReqFreeOverflow, STAMTYPE_COUNTER, "/VM/Req/FreeOverflow", STAMUNIT_OCCURENCES, "Number of times the request was actually freed.");
603
604 rc = CPUMR3Init(pVM);
605 if (VBOX_SUCCESS(rc))
606 {
607 rc = HWACCMR3Init(pVM);
608 if (VBOX_SUCCESS(rc))
609 {
610 rc = PGMR3Init(pVM);
611 if (VBOX_SUCCESS(rc))
612 {
613 rc = REMR3Init(pVM);
614 if (VBOX_SUCCESS(rc))
615 {
616 rc = MMR3InitPaging(pVM);
617 if (VBOX_SUCCESS(rc))
618 rc = TMR3Init(pVM);
619 if (VBOX_SUCCESS(rc))
620 {
621 rc = VMMR3Init(pVM);
622 if (VBOX_SUCCESS(rc))
623 {
624 rc = SELMR3Init(pVM);
625 if (VBOX_SUCCESS(rc))
626 {
627 rc = TRPMR3Init(pVM);
628 if (VBOX_SUCCESS(rc))
629 {
630 rc = CSAMR3Init(pVM);
631 if (VBOX_SUCCESS(rc))
632 {
633 rc = PATMR3Init(pVM);
634 if (VBOX_SUCCESS(rc))
635 {
636#ifdef VBOX_WITH_VMI
637 rc = PARAVR3Init(pVM);
638 if (VBOX_SUCCESS(rc))
639 {
640#endif
641 rc = IOMR3Init(pVM);
642 if (VBOX_SUCCESS(rc))
643 {
644 rc = EMR3Init(pVM);
645 if (VBOX_SUCCESS(rc))
646 {
647 rc = DBGFR3Init(pVM);
648 if (VBOX_SUCCESS(rc))
649 {
650 rc = PDMR3Init(pVM);
651 if (VBOX_SUCCESS(rc))
652 {
653 rc = PGMR3InitDynMap(pVM);
654 if (VBOX_SUCCESS(rc))
655 rc = MMR3HyperInitFinalize(pVM);
656 if (VBOX_SUCCESS(rc))
657 rc = PATMR3InitFinalize(pVM);
658 if (VBOX_SUCCESS(rc))
659 rc = PGMR3InitFinalize(pVM);
660 if (VBOX_SUCCESS(rc))
661 rc = SELMR3InitFinalize(pVM);
662 if (VBOX_SUCCESS(rc))
663 rc = TMR3InitFinalize(pVM);
664 if (VBOX_SUCCESS(rc))
665 rc = VMMR3InitFinalize(pVM);
666 if (VBOX_SUCCESS(rc))
667 rc = vmR3InitDoCompleted(pVM, VMINITCOMPLETED_RING3);
668 if (VBOX_SUCCESS(rc))
669 {
670 LogFlow(("vmR3InitRing3: returns %Vrc\n", VINF_SUCCESS));
671 return VINF_SUCCESS;
672 }
673 int rc2 = PDMR3Term(pVM);
674 AssertRC(rc2);
675 }
676 int rc2 = DBGFR3Term(pVM);
677 AssertRC(rc2);
678 }
679 int rc2 = EMR3Term(pVM);
680 AssertRC(rc2);
681 }
682 int rc2 = IOMR3Term(pVM);
683 AssertRC(rc2);
684 }
685#ifdef VBOX_WITH_VMI
686 int rc2 = PARAVR3Term(pVM);
687 AssertRC(rc2);
688 }
689#endif
690 int rc2 = PATMR3Term(pVM);
691 AssertRC(rc2);
692 }
693 int rc2 = CSAMR3Term(pVM);
694 AssertRC(rc2);
695 }
696 int rc2 = TRPMR3Term(pVM);
697 AssertRC(rc2);
698 }
699 int rc2 = SELMR3Term(pVM);
700 AssertRC(rc2);
701 }
702 int rc2 = VMMR3Term(pVM);
703 AssertRC(rc2);
704 }
705 int rc2 = TMR3Term(pVM);
706 AssertRC(rc2);
707 }
708 int rc2 = REMR3Term(pVM);
709 AssertRC(rc2);
710 }
711 int rc2 = PGMR3Term(pVM);
712 AssertRC(rc2);
713 }
714 int rc2 = HWACCMR3Term(pVM);
715 AssertRC(rc2);
716 }
717 //int rc2 = CPUMR3Term(pVM);
718 //AssertRC(rc2);
719 }
720 /* MMR3Term is not called here because it'll kill the heap. */
721 }
722
723 LogFlow(("vmR3InitRing3: returns %Vrc\n", rc));
724 return rc;
725}
726
727
728/**
729 * Initializes all R0 components of the VM
730 */
731static int vmR3InitRing0(PVM pVM)
732{
733 LogFlow(("vmR3InitRing0:\n"));
734
735 /*
736 * Check for FAKE suplib mode.
737 */
738 int rc = VINF_SUCCESS;
739 const char *psz = RTEnvGet("VBOX_SUPLIB_FAKE");
740 if (!psz || strcmp(psz, "fake"))
741 {
742 /*
743 * Call the VMMR0 component and let it do the init.
744 */
745 rc = VMMR3InitR0(pVM);
746 }
747 else
748 Log(("vmR3InitRing0: skipping because of VBOX_SUPLIB_FAKE=fake\n"));
749
750 /*
751 * Do notifications and return.
752 */
753 if (VBOX_SUCCESS(rc))
754 rc = vmR3InitDoCompleted(pVM, VMINITCOMPLETED_RING0);
755
756 /** todo: move this to the VMINITCOMPLETED_RING0 notification handler once implemented */
757 if (VBOX_SUCCESS(rc))
758 rc = HWACCMR3InitFinalizeR0(pVM);
759
760 LogFlow(("vmR3InitRing0: returns %Vrc\n", rc));
761 return rc;
762}
763
764
765/**
766 * Initializes all GC components of the VM
767 */
768static int vmR3InitGC(PVM pVM)
769{
770 LogFlow(("vmR3InitGC:\n"));
771
772 /*
773 * Check for FAKE suplib mode.
774 */
775 int rc = VINF_SUCCESS;
776 const char *psz = RTEnvGet("VBOX_SUPLIB_FAKE");
777 if (!psz || strcmp(psz, "fake"))
778 {
779 /*
780 * Call the VMMR0 component and let it do the init.
781 */
782 rc = VMMR3InitGC(pVM);
783 }
784 else
785 Log(("vmR3InitGC: skipping because of VBOX_SUPLIB_FAKE=fake\n"));
786
787 /*
788 * Do notifications and return.
789 */
790 if (VBOX_SUCCESS(rc))
791 rc = vmR3InitDoCompleted(pVM, VMINITCOMPLETED_GC);
792 LogFlow(("vmR3InitGC: returns %Vrc\n", rc));
793 return rc;
794}
795
796
797/**
798 * Do init completed notifications.
799 * This notifications can fail.
800 *
801 * @param pVM The VM handle.
802 * @param enmWhat What's completed.
803 */
804static int vmR3InitDoCompleted(PVM pVM, VMINITCOMPLETED enmWhat)
805{
806
807 return VINF_SUCCESS;
808}
809
810
811/**
812 * Calls the relocation functions for all VMM components so they can update
813 * any GC pointers. When this function is called all the basic VM members
814 * have been updated and the actual memory relocation have been done
815 * by the PGM/MM.
816 *
817 * This is used both on init and on runtime relocations.
818 *
819 * @param pVM VM handle.
820 * @param offDelta Relocation delta relative to old location.
821 */
822VMMR3DECL(void) VMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
823{
824 LogFlow(("VMR3Relocate: offDelta=%VGv\n", offDelta));
825
826 /*
827 * The order here is very important!
828 */
829 PGMR3Relocate(pVM, offDelta);
830 PDMR3LdrRelocateU(pVM->pUVM, offDelta);
831 PGMR3Relocate(pVM, 0); /* Repeat after PDM relocation. */
832 CPUMR3Relocate(pVM);
833 HWACCMR3Relocate(pVM);
834 SELMR3Relocate(pVM);
835 VMMR3Relocate(pVM, offDelta);
836 SELMR3Relocate(pVM); /* !hack! fix stack! */
837 TRPMR3Relocate(pVM, offDelta);
838 PATMR3Relocate(pVM);
839 CSAMR3Relocate(pVM, offDelta);
840 IOMR3Relocate(pVM, offDelta);
841 EMR3Relocate(pVM);
842 TMR3Relocate(pVM, offDelta);
843 DBGFR3Relocate(pVM, offDelta);
844 PDMR3Relocate(pVM, offDelta);
845}
846
847
848/**
849 * Power on the virtual machine.
850 *
851 * @returns 0 on success.
852 * @returns VBox error code on failure.
853 * @param pVM VM to power on.
854 * @thread Any thread.
855 * @vmstate Created
856 * @vmstateto Running
857 */
858VMMR3DECL(int) VMR3PowerOn(PVM pVM)
859{
860 LogFlow(("VMR3PowerOn: pVM=%p\n", pVM));
861
862 /*
863 * Validate input.
864 */
865 if (!pVM)
866 {
867 AssertMsgFailed(("Invalid VM pointer\n"));
868 return VERR_INVALID_PARAMETER;
869 }
870
871 /*
872 * Request the operation in EMT.
873 */
874 PVMREQ pReq;
875 int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3PowerOn, 1, pVM);
876 if (VBOX_SUCCESS(rc))
877 {
878 rc = pReq->iStatus;
879 VMR3ReqFree(pReq);
880 }
881
882 LogFlow(("VMR3PowerOn: returns %Vrc\n", rc));
883 return rc;
884}
885
886
887/**
888 * Power on the virtual machine.
889 *
890 * @returns 0 on success.
891 * @returns VBox error code on failure.
892 * @param pVM VM to power on.
893 * @thread EMT
894 */
895static DECLCALLBACK(int) vmR3PowerOn(PVM pVM)
896{
897 LogFlow(("vmR3PowerOn: pVM=%p\n", pVM));
898
899 /*
900 * Validate input.
901 */
902 if (pVM->enmVMState != VMSTATE_CREATED)
903 {
904 AssertMsgFailed(("Invalid VM state %d\n", pVM->enmVMState));
905 return VERR_VM_INVALID_VM_STATE;
906 }
907
908 /*
909 * Change the state, notify the components and resume the execution.
910 */
911 vmR3SetState(pVM, VMSTATE_RUNNING);
912 PDMR3PowerOn(pVM);
913
914 return VINF_SUCCESS;
915}
916
917
918/**
919 * Suspends a running VM.
920 *
921 * @returns 0 on success.
922 * @returns VBox error code on failure.
923 * @param pVM VM to suspend.
924 * @thread Any thread.
925 * @vmstate Running
926 * @vmstateto Suspended
927 */
928VMMR3DECL(int) VMR3Suspend(PVM pVM)
929{
930 LogFlow(("VMR3Suspend: pVM=%p\n", pVM));
931
932 /*
933 * Validate input.
934 */
935 if (!pVM)
936 {
937 AssertMsgFailed(("Invalid VM pointer\n"));
938 return VERR_INVALID_PARAMETER;
939 }
940
941 /*
942 * Request the operation in EMT.
943 */
944 PVMREQ pReq;
945 int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3Suspend, 1, pVM);
946 if (VBOX_SUCCESS(rc))
947 {
948 rc = pReq->iStatus;
949 VMR3ReqFree(pReq);
950 }
951
952 LogFlow(("VMR3Suspend: returns %Vrc\n", rc));
953 return rc;
954}
955
956
957/**
958 * Suspends a running VM and prevent state saving until the VM is resumed or stopped.
959 *
960 * @returns 0 on success.
961 * @returns VBox error code on failure.
962 * @param pVM VM to suspend.
963 * @thread Any thread.
964 * @vmstate Running
965 * @vmstateto Suspended
966 */
967VMMR3DECL(int) VMR3SuspendNoSave(PVM pVM)
968{
969 pVM->vm.s.fPreventSaveState = true;
970 return VMR3Suspend(pVM);
971}
972
973
974/**
975 * Suspends a running VM.
976 *
977 * @returns 0 on success.
978 * @returns VBox error code on failure.
979 * @param pVM VM to suspend.
980 * @thread EMT
981 */
982static DECLCALLBACK(int) vmR3Suspend(PVM pVM)
983{
984 LogFlow(("vmR3Suspend: pVM=%p\n", pVM));
985
986 /*
987 * Validate input.
988 */
989 if (pVM->enmVMState != VMSTATE_RUNNING)
990 {
991 AssertMsgFailed(("Invalid VM state %d\n", pVM->enmVMState));
992 return VERR_VM_INVALID_VM_STATE;
993 }
994
995 /*
996 * Change the state, notify the components and resume the execution.
997 */
998 vmR3SetState(pVM, VMSTATE_SUSPENDED);
999 PDMR3Suspend(pVM);
1000
1001 return VINF_EM_SUSPEND;
1002}
1003
1004
1005/**
1006 * Resume VM execution.
1007 *
1008 * @returns 0 on success.
1009 * @returns VBox error code on failure.
1010 * @param pVM The VM to resume.
1011 * @thread Any thread.
1012 * @vmstate Suspended
1013 * @vmstateto Running
1014 */
1015VMMR3DECL(int) VMR3Resume(PVM pVM)
1016{
1017 LogFlow(("VMR3Resume: pVM=%p\n", pVM));
1018
1019 /*
1020 * Validate input.
1021 */
1022 if (!pVM)
1023 {
1024 AssertMsgFailed(("Invalid VM pointer\n"));
1025 return VERR_INVALID_PARAMETER;
1026 }
1027
1028 /*
1029 * Request the operation in EMT.
1030 */
1031 PVMREQ pReq;
1032 int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3Resume, 1, pVM);
1033 if (VBOX_SUCCESS(rc))
1034 {
1035 rc = pReq->iStatus;
1036 VMR3ReqFree(pReq);
1037 }
1038
1039 LogFlow(("VMR3Resume: returns %Vrc\n", rc));
1040 return rc;
1041}
1042
1043
1044/**
1045 * Resume VM execution.
1046 *
1047 * @returns 0 on success.
1048 * @returns VBox error code on failure.
1049 * @param pVM The VM to resume.
1050 * @thread EMT
1051 */
1052static DECLCALLBACK(int) vmR3Resume(PVM pVM)
1053{
1054 LogFlow(("vmR3Resume: pVM=%p\n", pVM));
1055
1056 /*
1057 * Validate input.
1058 */
1059 if (pVM->enmVMState != VMSTATE_SUSPENDED)
1060 {
1061 AssertMsgFailed(("Invalid VM state %d\n", pVM->enmVMState));
1062 return VERR_VM_INVALID_VM_STATE;
1063 }
1064
1065 /*
1066 * Change the state, notify the components and resume the execution.
1067 */
1068 pVM->vm.s.fPreventSaveState = false;
1069 vmR3SetState(pVM, VMSTATE_RUNNING);
1070 PDMR3Resume(pVM);
1071
1072 return VINF_EM_RESUME;
1073}
1074
1075
1076/**
1077 * Save current VM state.
1078 *
1079 * To save and terminate the VM, the VM must be suspended before the call.
1080 *
1081 * @returns 0 on success.
1082 * @returns VBox error code on failure.
1083 * @param pVM VM which state should be saved.
1084 * @param pszFilename Name of the save state file.
1085 * @param pfnProgress Progress callback. Optional.
1086 * @param pvUser User argument for the progress callback.
1087 * @thread Any thread.
1088 * @vmstate Suspended
1089 * @vmstateto Unchanged state.
1090 */
1091VMMR3DECL(int) VMR3Save(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser)
1092{
1093 LogFlow(("VMR3Save: pVM=%p pszFilename=%p:{%s} pfnProgress=%p pvUser=%p\n", pVM, pszFilename, pszFilename, pfnProgress, pvUser));
1094
1095 /*
1096 * Validate input.
1097 */
1098 if (!pVM)
1099 {
1100 AssertMsgFailed(("Invalid VM pointer\n"));
1101 return VERR_INVALID_PARAMETER;
1102 }
1103 if (!pszFilename)
1104 {
1105 AssertMsgFailed(("Must specify a filename to save the state to, wise guy!\n"));
1106 return VERR_INVALID_PARAMETER;
1107 }
1108
1109 /*
1110 * Request the operation in EMT.
1111 */
1112 PVMREQ pReq;
1113 int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3Save, 4, pVM, pszFilename, pfnProgress, pvUser);
1114 if (VBOX_SUCCESS(rc))
1115 {
1116 rc = pReq->iStatus;
1117 VMR3ReqFree(pReq);
1118 }
1119
1120 LogFlow(("VMR3Save: returns %Vrc\n", rc));
1121 return rc;
1122}
1123
1124
1125/**
1126 * Save current VM state.
1127 *
1128 * To save and terminate the VM, the VM must be suspended before the call.
1129 *
1130 * @returns 0 on success.
1131 * @returns VBox error code on failure.
1132 * @param pVM VM which state should be saved.
1133 * @param pszFilename Name of the save state file.
1134 * @param pfnProgress Progress callback. Optional.
1135 * @param pvUser User argument for the progress callback.
1136 * @thread EMT
1137 */
1138static DECLCALLBACK(int) vmR3Save(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser)
1139{
1140 LogFlow(("vmR3Save: pVM=%p pszFilename=%p:{%s} pfnProgress=%p pvUser=%p\n", pVM, pszFilename, pszFilename, pfnProgress, pvUser));
1141
1142 /*
1143 * Validate input.
1144 */
1145 if (pVM->enmVMState != VMSTATE_SUSPENDED)
1146 {
1147 AssertMsgFailed(("Invalid VM state %d\n", pVM->enmVMState));
1148 return VERR_VM_INVALID_VM_STATE;
1149 }
1150
1151 /* If we are in an inconsistent state, then we don't allow state saving. */
1152 if (pVM->vm.s.fPreventSaveState)
1153 {
1154 LogRel(("VMM: vmR3Save: saving the VM state is not allowed at this moment\n"));
1155 return VERR_VM_SAVE_STATE_NOT_ALLOWED;
1156 }
1157
1158 /*
1159 * Change the state and perform the save.
1160 */
1161 /** @todo implement progress support in SSM */
1162 vmR3SetState(pVM, VMSTATE_SAVING);
1163 int rc = SSMR3Save(pVM, pszFilename, SSMAFTER_CONTINUE, pfnProgress, pvUser);
1164 vmR3SetState(pVM, VMSTATE_SUSPENDED);
1165
1166 return rc;
1167}
1168
1169
1170/**
1171 * Loads a new VM state.
1172 *
1173 * To restore a saved state on VM startup, call this function and then
1174 * resume the VM instead of powering it on.
1175 *
1176 * @returns 0 on success.
1177 * @returns VBox error code on failure.
1178 * @param pVM VM which state should be saved.
1179 * @param pszFilename Name of the save state file.
1180 * @param pfnProgress Progress callback. Optional.
1181 * @param pvUser User argument for the progress callback.
1182 * @thread Any thread.
1183 * @vmstate Created, Suspended
1184 * @vmstateto Suspended
1185 */
1186VMMR3DECL(int) VMR3Load(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser)
1187{
1188 LogFlow(("VMR3Load: pVM=%p pszFilename=%p:{%s} pfnProgress=%p pvUser=%p\n", pVM, pszFilename, pszFilename, pfnProgress, pvUser));
1189
1190 /*
1191 * Validate input.
1192 */
1193 if (!pVM)
1194 {
1195 AssertMsgFailed(("Invalid VM pointer\n"));
1196 return VERR_INVALID_PARAMETER;
1197 }
1198 if (!pszFilename)
1199 {
1200 AssertMsgFailed(("Must specify a filename to load the state from, wise guy!\n"));
1201 return VERR_INVALID_PARAMETER;
1202 }
1203
1204 /*
1205 * Request the operation in EMT.
1206 */
1207 PVMREQ pReq;
1208 int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3Load, 4, pVM, pszFilename, pfnProgress, pvUser);
1209 if (VBOX_SUCCESS(rc))
1210 {
1211 rc = pReq->iStatus;
1212 VMR3ReqFree(pReq);
1213 }
1214
1215 LogFlow(("VMR3Load: returns %Vrc\n", rc));
1216 return rc;
1217}
1218
1219
1220/**
1221 * Loads a new VM state.
1222 *
1223 * To restore a saved state on VM startup, call this function and then
1224 * resume the VM instead of powering it on.
1225 *
1226 * @returns 0 on success.
1227 * @returns VBox error code on failure.
1228 * @param pVM VM which state should be saved.
1229 * @param pszFilename Name of the save state file.
1230 * @param pfnProgress Progress callback. Optional.
1231 * @param pvUser User argument for the progress callback.
1232 * @thread EMT.
1233 */
1234static DECLCALLBACK(int) vmR3Load(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser)
1235{
1236 LogFlow(("vmR3Load: pVM=%p pszFilename=%p:{%s} pfnProgress=%p pvUser=%p\n", pVM, pszFilename, pszFilename, pfnProgress, pvUser));
1237
1238 /*
1239 * Validate input.
1240 */
1241 if ( pVM->enmVMState != VMSTATE_SUSPENDED
1242 && pVM->enmVMState != VMSTATE_CREATED)
1243 {
1244 AssertMsgFailed(("Invalid VM state %d\n", pVM->enmVMState));
1245 return VMSetError(pVM, VERR_VM_INVALID_VM_STATE, RT_SRC_POS, N_("Invalid VM state (%s) for restoring state from '%s'"),
1246 VMR3GetStateName(pVM->enmVMState), pszFilename);
1247 }
1248
1249 /*
1250 * Change the state and perform the load.
1251 */
1252 vmR3SetState(pVM, VMSTATE_LOADING);
1253 int rc = SSMR3Load(pVM, pszFilename, SSMAFTER_RESUME, pfnProgress, pvUser);
1254 if (VBOX_SUCCESS(rc))
1255 {
1256 /* Not paranoia anymore; the saved guest might use different hypervisor selectors. We must call VMR3Relocate. */
1257 VMR3Relocate(pVM, 0);
1258 vmR3SetState(pVM, VMSTATE_SUSPENDED);
1259 }
1260 else
1261 {
1262 vmR3SetState(pVM, VMSTATE_LOAD_FAILURE);
1263 rc = VMSetError(pVM, rc, RT_SRC_POS, N_("Unable to restore the virtual machine's saved state from '%s'. It may be damaged or from an older version of VirtualBox. Please discard the saved state before starting the virtual machine"), pszFilename);
1264 }
1265
1266 return rc;
1267}
1268
1269
1270/**
1271 * Power Off the VM.
1272 *
1273 * @returns 0 on success.
1274 * @returns VBox error code on failure.
1275 * @param pVM VM which should be destroyed.
1276 * @thread Any thread.
1277 * @vmstate Suspended, Running, Guru Meditation, Load Failure
1278 * @vmstateto Off
1279 */
1280VMMR3DECL(int) VMR3PowerOff(PVM pVM)
1281{
1282 LogFlow(("VMR3PowerOff: pVM=%p\n", pVM));
1283
1284 /*
1285 * Validate input.
1286 */
1287 if (!pVM)
1288 {
1289 AssertMsgFailed(("Invalid VM pointer\n"));
1290 return VERR_INVALID_PARAMETER;
1291 }
1292
1293 /*
1294 * Request the operation in EMT.
1295 */
1296 PVMREQ pReq;
1297 int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3PowerOff, 1, pVM);
1298 if (VBOX_SUCCESS(rc))
1299 {
1300 rc = pReq->iStatus;
1301 VMR3ReqFree(pReq);
1302 }
1303
1304 LogFlow(("VMR3PowerOff: returns %Vrc\n", rc));
1305 return rc;
1306}
1307
1308
1309/**
1310 * Power Off the VM.
1311 *
1312 * @returns 0 on success.
1313 * @returns VBox error code on failure.
1314 * @param pVM VM which should be destroyed.
1315 * @thread EMT.
1316 */
1317static DECLCALLBACK(int) vmR3PowerOff(PVM pVM)
1318{
1319 LogFlow(("vmR3PowerOff: pVM=%p\n", pVM));
1320
1321 /*
1322 * Validate input.
1323 */
1324 if ( pVM->enmVMState != VMSTATE_RUNNING
1325 && pVM->enmVMState != VMSTATE_SUSPENDED
1326 && pVM->enmVMState != VMSTATE_LOAD_FAILURE
1327 && pVM->enmVMState != VMSTATE_GURU_MEDITATION)
1328 {
1329 AssertMsgFailed(("Invalid VM state %d\n", pVM->enmVMState));
1330 return VERR_VM_INVALID_VM_STATE;
1331 }
1332
1333 /*
1334 * For debugging purposes, we will log a summary of the guest state at this point.
1335 */
1336 if (pVM->enmVMState != VMSTATE_GURU_MEDITATION)
1337 {
1338 /** @todo make the state dumping at VMR3PowerOff optional. */
1339 RTLogRelPrintf("****************** Guest state at power off ******************\n");
1340 DBGFR3Info(pVM, "cpumguest", "verbose", DBGFR3InfoLogRelHlp());
1341 RTLogRelPrintf("***\n");
1342 DBGFR3Info(pVM, "mode", NULL, DBGFR3InfoLogRelHlp());
1343 RTLogRelPrintf("***\n");
1344 DBGFR3Info(pVM, "activetimers", NULL, DBGFR3InfoLogRelHlp());
1345 RTLogRelPrintf("***\n");
1346 DBGFR3Info(pVM, "gdt", NULL, DBGFR3InfoLogRelHlp());
1347 /** @todo dump guest call stack. */
1348#if 1 // temporary while debugging #1589
1349 RTLogRelPrintf("***\n");
1350 uint32_t esp = CPUMGetGuestESP(pVM);
1351 if ( CPUMGetGuestSS(pVM) == 0
1352 && esp < _64K)
1353 {
1354 uint8_t abBuf[PAGE_SIZE];
1355 RTLogRelPrintf("***\n"
1356 "ss:sp=0000:%04x ", esp);
1357 uint32_t Start = esp & ~(uint32_t)63;
1358 int rc = PGMPhysSimpleReadGCPhys(pVM, abBuf, Start, 0x100);
1359 if (VBOX_SUCCESS(rc))
1360 RTLogRelPrintf("0000:%04x TO 0000:%04x:\n"
1361 "%.*Rhxd\n",
1362 Start, Start + 0x100 - 1,
1363 0x100, abBuf);
1364 else
1365 RTLogRelPrintf("rc=%Vrc\n", rc);
1366
1367 /* grub ... */
1368 if (esp < 0x2000 && esp > 0x1fc0)
1369 {
1370 rc = PGMPhysSimpleReadGCPhys(pVM, abBuf, 0x8000, 0x800);
1371 if (VBOX_SUCCESS(rc))
1372 RTLogRelPrintf("0000:8000 TO 0000:87ff:\n"
1373 "%.*Rhxd\n",
1374 0x800, abBuf);
1375 }
1376 /* microsoft cdrom hang ... */
1377 if (true)
1378 {
1379 rc = PGMPhysSimpleReadGCPhys(pVM, abBuf, 0x8000, 0x200);
1380 if (VBOX_SUCCESS(rc))
1381 RTLogRelPrintf("2000:0000 TO 2000:01ff:\n"
1382 "%.*Rhxd\n",
1383 0x200, abBuf);
1384 }
1385 }
1386#endif
1387 RTLogRelPrintf("************** End of Guest state at power off ***************\n");
1388 }
1389
1390 /*
1391 * Change the state to OFF and notify the components.
1392 */
1393 vmR3SetState(pVM, VMSTATE_OFF);
1394 PDMR3PowerOff(pVM);
1395
1396 return VINF_EM_OFF;
1397}
1398
1399
1400/**
1401 * Destroys the VM.
1402 * The VM must be powered off (or never really powered on) to call this function.
1403 * The VM handle is destroyed and can no longer be used up successful return.
1404 *
1405 * @returns VBox status code.
1406 * @param pVM VM which should be destroyed.
1407 * @thread Any thread but the emulation thread.
1408 * @vmstate Off, Created
1409 * @vmstateto N/A
1410 */
1411VMMR3DECL(int) VMR3Destroy(PVM pVM)
1412{
1413 LogFlow(("VMR3Destroy: pVM=%p\n", pVM));
1414
1415 /*
1416 * Validate input.
1417 */
1418 if (!pVM)
1419 return VERR_INVALID_PARAMETER;
1420 AssertPtrReturn(pVM, VERR_INVALID_POINTER);
1421 AssertMsgReturn( pVM->enmVMState == VMSTATE_OFF
1422 || pVM->enmVMState == VMSTATE_CREATED,
1423 ("Invalid VM state %d\n", pVM->enmVMState),
1424 VERR_VM_INVALID_VM_STATE);
1425
1426 /*
1427 * Change VM state to destroying and unlink the VM.
1428 */
1429 vmR3SetState(pVM, VMSTATE_DESTROYING);
1430
1431 /** @todo lock this when we start having multiple machines in a process... */
1432 PUVM pUVM = pVM->pUVM; AssertPtr(pUVM);
1433 if (g_pUVMsHead == pUVM)
1434 g_pUVMsHead = pUVM->pNext;
1435 else
1436 {
1437 PUVM pPrev = g_pUVMsHead;
1438 while (pPrev && pPrev->pNext != pUVM)
1439 pPrev = pPrev->pNext;
1440 AssertMsgReturn(pPrev, ("pUVM=%p / pVM=%p is INVALID!\n", pUVM, pVM), VERR_INVALID_PARAMETER);
1441
1442 pPrev->pNext = pUVM->pNext;
1443 }
1444 pUVM->pNext = NULL;
1445
1446 /*
1447 * Notify registered at destruction listeners.
1448 * (That's the debugger console.)
1449 */
1450 vmR3AtDtor(pVM);
1451
1452 /*
1453 * If we are the EMT we'll delay the cleanup till later.
1454 */
1455 if (VM_IS_EMT(pVM))
1456 {
1457 pUVM->vm.s.fEMTDoesTheCleanup = true;
1458 pUVM->vm.s.fTerminateEMT = true;
1459 VM_FF_SET(pVM, VM_FF_TERMINATE);
1460 }
1461 else
1462 {
1463 /*
1464 * Request EMT to do the larger part of the destruction.
1465 */
1466 PVMREQ pReq = NULL;
1467 int rc = VMR3ReqCallU(pUVM, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)vmR3Destroy, 1, pVM);
1468 if (RT_SUCCESS(rc))
1469 rc = pReq->iStatus;
1470 AssertRC(rc);
1471 VMR3ReqFree(pReq);
1472
1473 /*
1474 * Wait for the EMT thread to terminate.
1475 */
1476 Assert(pUVM->vm.s.fTerminateEMT);
1477 rc = RTThreadWait(pUVM->vm.s.ThreadEMT, 30000, NULL);
1478 AssertMsgRC(rc, ("EMT thread wait failed, rc=%Rrc\n", rc));
1479
1480 /*
1481 * Now do the final bit where the heap and VM structures are freed up.
1482 */
1483 vmR3DestroyUVM(pUVM);
1484 }
1485
1486 LogFlow(("VMR3Destroy: returns VINF_SUCCESS\n"));
1487 return VINF_SUCCESS;
1488}
1489
1490
1491/**
1492 * Internal destruction worker.
1493 *
1494 * This will do nearly all of the job, including sacking the EMT.
1495 *
1496 * @returns VBox status.
1497 * @param pVM VM handle.
1498 */
1499DECLCALLBACK(int) vmR3Destroy(PVM pVM)
1500{
1501 PUVM pUVM = pVM->pUVM;
1502 NOREF(pUVM);
1503 LogFlow(("vmR3Destroy: pVM=%p pUVM=%p\n", pVM, pUVM));
1504 VM_ASSERT_EMT(pVM);
1505
1506 /*
1507 * Dump statistics to the log.
1508 */
1509#if defined(VBOX_WITH_STATISTICS) || defined(LOG_ENABLED)
1510 RTLogFlags(NULL, "nodisabled nobuffered");
1511#endif
1512#ifdef VBOX_WITH_STATISTICS
1513# ifndef DEBUG_dmik
1514 STAMR3Dump(pVM, "*");
1515# endif
1516#else
1517 LogRel(("************************* Statistics *************************\n"));
1518 STAMR3DumpToReleaseLog(pVM, "*");
1519 LogRel(("********************* End of statistics **********************\n"));
1520#endif
1521
1522 /*
1523 * Destroy the VM components.
1524 */
1525 int rc = TMR3Term(pVM);
1526 AssertRC(rc);
1527#ifdef VBOX_WITH_DEBUGGER
1528 rc = DBGCTcpTerminate(pVM, pUVM->vm.s.pvDBGC);
1529 pVM->pUVM->vm.s.pvDBGC = NULL;
1530#endif
1531 AssertRC(rc);
1532 rc = DBGFR3Term(pVM);
1533 AssertRC(rc);
1534 rc = PDMR3Term(pVM);
1535 AssertRC(rc);
1536 rc = EMR3Term(pVM);
1537 AssertRC(rc);
1538 rc = IOMR3Term(pVM);
1539 AssertRC(rc);
1540 rc = CSAMR3Term(pVM);
1541 AssertRC(rc);
1542 rc = PATMR3Term(pVM);
1543 AssertRC(rc);
1544 rc = TRPMR3Term(pVM);
1545 AssertRC(rc);
1546 rc = SELMR3Term(pVM);
1547 AssertRC(rc);
1548 rc = REMR3Term(pVM);
1549 AssertRC(rc);
1550 rc = HWACCMR3Term(pVM);
1551 AssertRC(rc);
1552 rc = PGMR3Term(pVM);
1553 AssertRC(rc);
1554 rc = VMMR3Term(pVM); /* Terminates the ring-0 code! */
1555 AssertRC(rc);
1556 rc = CPUMR3Term(pVM);
1557 AssertRC(rc);
1558 rc = PDMR3CritSectTerm(pVM);
1559 AssertRC(rc);
1560 rc = MMR3Term(pVM);
1561 AssertRC(rc);
1562
1563 /*
1564 * We're done in this thread (EMT).
1565 */
1566 ASMAtomicUoWriteBool(&pVM->pUVM->vm.s.fTerminateEMT, true);
1567 ASMAtomicWriteU32(&pVM->fForcedActions, VM_FF_TERMINATE);
1568 LogFlow(("vmR3Destroy: returning %Vrc\n", VINF_EM_TERMINATE));
1569 return VINF_EM_TERMINATE;
1570}
1571
1572
1573/**
1574 * Destroys the shared VM structure, leaving only UVM behind.
1575 *
1576 * This is called by EMT right before terminating.
1577 *
1578 * @param pUVM The UVM handle.
1579 */
1580void vmR3DestroyFinalBitFromEMT(PUVM pUVM)
1581{
1582 if (pUVM->pVM)
1583 {
1584 /*
1585 * Modify state and then terminate MM.
1586 * (MM must be delayed until this point so we don't destroy the callbacks and the request packet.)
1587 */
1588 vmR3SetState(pUVM->pVM, VMSTATE_TERMINATED);
1589
1590 /*
1591 * Tell GVMM to destroy the VM and free its resources.
1592 */
1593 int rc = SUPCallVMMR0Ex(pUVM->pVM->pVMR0, VMMR0_DO_GVMM_DESTROY_VM, 0, NULL);
1594 AssertRC(rc);
1595 pUVM->pVM = NULL;
1596 }
1597
1598 /*
1599 * Did EMT call VMR3Destroy and have to do it all?
1600 */
1601 if (pUVM->vm.s.fEMTDoesTheCleanup)
1602 vmR3DestroyUVM(pUVM);
1603}
1604
1605
1606/**
1607 * Destroys the UVM portion.
1608 *
1609 * This is called as the final step in the VM destruction or as the cleanup
1610 * in case of a creation failure. If EMT called VMR3Destroy, meaning
1611 * VMINTUSERPERVM::fEMTDoesTheCleanup is true, it will call this as
1612 * vmR3DestroyFinalBitFromEMT completes.
1613 *
1614 * @param pVM VM Handle.
1615 */
1616static void vmR3DestroyUVM(PUVM pUVM)
1617{
1618 /*
1619 * Terminate the EMT if still running (creation failure only).
1620 */
1621 if (!pUVM->vm.s.fTerminateEMT)
1622 {
1623 ASMAtomicUoWriteBool(&pUVM->vm.s.fTerminateEMT, true);
1624 if (pUVM->pVM)
1625 {
1626 VM_FF_SET(pUVM->pVM, VM_FF_TERMINATE);
1627 VMR3NotifyFF(pUVM->pVM, false);
1628 }
1629 RTSemEventSignal(pUVM->vm.s.EventSemWait);
1630
1631 int rc2 = RTThreadWait(pUVM->vm.s.ThreadEMT, 2000, NULL);
1632 AssertRC(rc2);
1633 }
1634 RTSemEventDestroy(pUVM->vm.s.EventSemWait);
1635 pUVM->vm.s.EventSemWait = NIL_RTSEMEVENT;
1636
1637 /*
1638 * Free the event semaphores associated with the request packets.
1639 */
1640 unsigned cReqs = 0;
1641 for (unsigned i = 0; i < RT_ELEMENTS(pUVM->vm.s.apReqFree); i++)
1642 {
1643 PVMREQ pReq = pUVM->vm.s.apReqFree[i];
1644 pUVM->vm.s.apReqFree[i] = NULL;
1645 for (; pReq; pReq = pReq->pNext, cReqs++)
1646 {
1647 pReq->enmState = VMREQSTATE_INVALID;
1648 RTSemEventDestroy(pReq->EventSem);
1649 }
1650 }
1651 Assert(cReqs == pUVM->vm.s.cReqFree); NOREF(cReqs);
1652
1653 /*
1654 * Kill all queued requests. (There really shouldn't be any!)
1655 */
1656 for (unsigned i = 0; i < 10; i++)
1657 {
1658 PVMREQ pReqHead = (PVMREQ)ASMAtomicXchgPtr((void *volatile *)&pUVM->vm.s.pReqs, NULL);
1659 AssertMsg(!pReqHead, ("This isn't supposed to happen! VMR3Destroy caller has to serialize this.\n"));
1660 if (!pReqHead)
1661 break;
1662 for (PVMREQ pReq = pReqHead; pReq; pReq = pReq->pNext)
1663 {
1664 ASMAtomicUoWriteSize(&pReq->iStatus, VERR_INTERNAL_ERROR);
1665 ASMAtomicWriteSize(&pReq->enmState, VMREQSTATE_INVALID);
1666 RTSemEventSignal(pReq->EventSem);
1667 RTThreadSleep(2);
1668 RTSemEventDestroy(pReq->EventSem);
1669 }
1670 /* give them a chance to respond before we free the request memory. */
1671 RTThreadSleep(32);
1672 }
1673
1674 /*
1675 * Make sure the VMMR0.r0 module and whatever else is unloaded.
1676 */
1677 PDMR3TermUVM(pUVM);
1678
1679 /*
1680 * Terminate the support library if initialized.
1681 */
1682 if (pUVM->vm.s.pSession)
1683 {
1684 int rc = SUPTerm();
1685 AssertRC(rc);
1686 pUVM->vm.s.pSession = NIL_RTR0PTR;
1687 }
1688
1689 /*
1690 * Destroy the MM heap and free the UVM structure.
1691 */
1692 MMR3TermUVM(pUVM);
1693 STAMR3TermUVM(pUVM);
1694
1695 ASMAtomicUoWriteU32(&pUVM->u32Magic, UINT32_MAX);
1696 RTMemFree(pUVM);
1697
1698 RTLogFlush(NULL);
1699}
1700
1701
1702/**
1703 * Enumerates the VMs in this process.
1704 *
1705 * @returns Pointer to the next VM.
1706 * @returns NULL when no more VMs.
1707 * @param pVMPrev The previous VM
1708 * Use NULL to start the enumeration.
1709 */
1710VMMR3DECL(PVM) VMR3EnumVMs(PVM pVMPrev)
1711{
1712 /*
1713 * This is quick and dirty. It has issues with VM being
1714 * destroyed during the enumeration.
1715 */
1716 PUVM pNext;
1717 if (pVMPrev)
1718 pNext = pVMPrev->pUVM->pNext;
1719 else
1720 pNext = g_pUVMsHead;
1721 return pNext ? pNext->pVM : NULL;
1722}
1723
1724
1725/**
1726 * Registers an at VM destruction callback.
1727 *
1728 * @returns VBox status code.
1729 * @param pfnAtDtor Pointer to callback.
1730 * @param pvUser User argument.
1731 */
1732VMMR3DECL(int) VMR3AtDtorRegister(PFNVMATDTOR pfnAtDtor, void *pvUser)
1733{
1734 /*
1735 * Check if already registered.
1736 */
1737 VM_ATDTOR_LOCK();
1738 PVMATDTOR pCur = g_pVMAtDtorHead;
1739 while (pCur)
1740 {
1741 if (pfnAtDtor == pCur->pfnAtDtor)
1742 {
1743 VM_ATDTOR_UNLOCK();
1744 AssertMsgFailed(("Already registered at destruction callback %p!\n", pfnAtDtor));
1745 return VERR_INVALID_PARAMETER;
1746 }
1747
1748 /* next */
1749 pCur = pCur->pNext;
1750 }
1751 VM_ATDTOR_UNLOCK();
1752
1753 /*
1754 * Allocate new entry.
1755 */
1756 PVMATDTOR pVMAtDtor = (PVMATDTOR)RTMemAlloc(sizeof(*pVMAtDtor));
1757 if (!pVMAtDtor)
1758 return VERR_NO_MEMORY;
1759
1760 VM_ATDTOR_LOCK();
1761 pVMAtDtor->pfnAtDtor = pfnAtDtor;
1762 pVMAtDtor->pvUser = pvUser;
1763 pVMAtDtor->pNext = g_pVMAtDtorHead;
1764 g_pVMAtDtorHead = pVMAtDtor;
1765 VM_ATDTOR_UNLOCK();
1766
1767 return VINF_SUCCESS;
1768}
1769
1770
1771/**
1772 * Deregisters an at VM destruction callback.
1773 *
1774 * @returns VBox status code.
1775 * @param pfnAtDtor Pointer to callback.
1776 */
1777VMMR3DECL(int) VMR3AtDtorDeregister(PFNVMATDTOR pfnAtDtor)
1778{
1779 /*
1780 * Find it, unlink it and free it.
1781 */
1782 VM_ATDTOR_LOCK();
1783 PVMATDTOR pPrev = NULL;
1784 PVMATDTOR pCur = g_pVMAtDtorHead;
1785 while (pCur)
1786 {
1787 if (pfnAtDtor == pCur->pfnAtDtor)
1788 {
1789 if (pPrev)
1790 pPrev->pNext = pCur->pNext;
1791 else
1792 g_pVMAtDtorHead = pCur->pNext;
1793 pCur->pNext = NULL;
1794 VM_ATDTOR_UNLOCK();
1795
1796 RTMemFree(pCur);
1797 return VINF_SUCCESS;
1798 }
1799
1800 /* next */
1801 pPrev = pCur;
1802 pCur = pCur->pNext;
1803 }
1804 VM_ATDTOR_UNLOCK();
1805
1806 return VERR_INVALID_PARAMETER;
1807}
1808
1809
1810/**
1811 * Walks the list of at VM destructor callbacks.
1812 * @param pVM The VM which is about to be destroyed.
1813 */
1814static void vmR3AtDtor(PVM pVM)
1815{
1816 /*
1817 * Find it, unlink it and free it.
1818 */
1819 VM_ATDTOR_LOCK();
1820 for (PVMATDTOR pCur = g_pVMAtDtorHead; pCur; pCur = pCur->pNext)
1821 pCur->pfnAtDtor(pVM, pCur->pvUser);
1822 VM_ATDTOR_UNLOCK();
1823}
1824
1825
1826/**
1827 * Reset the current VM.
1828 *
1829 * @returns VBox status code.
1830 * @param pVM VM to reset.
1831 */
1832VMMR3DECL(int) VMR3Reset(PVM pVM)
1833{
1834 int rc = VINF_SUCCESS;
1835
1836 /*
1837 * Check the state.
1838 */
1839 if (!pVM)
1840 return VERR_INVALID_PARAMETER;
1841 if ( pVM->enmVMState != VMSTATE_RUNNING
1842 && pVM->enmVMState != VMSTATE_SUSPENDED)
1843 {
1844 AssertMsgFailed(("Invalid VM state %d\n", pVM->enmVMState));
1845 return VERR_VM_INVALID_VM_STATE;
1846 }
1847
1848 /*
1849 * Queue reset request to the emulation thread
1850 * and wait for it to be processed.
1851 */
1852 PVMREQ pReq = NULL;
1853 rc = VMR3ReqCall(pVM, &pReq, 0, (PFNRT)vmR3Reset, 1, pVM);
1854 while (rc == VERR_TIMEOUT)
1855 rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
1856 if (VBOX_SUCCESS(rc))
1857 rc = pReq->iStatus;
1858 VMR3ReqFree(pReq);
1859
1860 return rc;
1861}
1862
1863
1864/**
1865 * Worker which checks integrity of some internal structures.
1866 * This is yet another attempt to track down that AVL tree crash.
1867 */
1868static void vmR3CheckIntegrity(PVM pVM)
1869{
1870#ifdef VBOX_STRICT
1871 int rc = PGMR3CheckIntegrity(pVM);
1872 AssertReleaseRC(rc);
1873#endif
1874}
1875
1876
1877/**
1878 * Reset request processor.
1879 *
1880 * This is called by the emulation thread as a response to the
1881 * reset request issued by VMR3Reset().
1882 *
1883 * @returns VBox status code.
1884 * @param pVM VM to reset.
1885 */
1886static DECLCALLBACK(int) vmR3Reset(PVM pVM)
1887{
1888 /*
1889 * As a safety precaution we temporarily change the state while resetting.
1890 * (If VMR3Reset was not called from EMT we might have change state... let's ignore that fact for now.)
1891 */
1892 VMSTATE enmVMState = pVM->enmVMState;
1893 Assert(enmVMState == VMSTATE_SUSPENDED || enmVMState == VMSTATE_RUNNING);
1894 vmR3SetState(pVM, VMSTATE_RESETTING);
1895 vmR3CheckIntegrity(pVM);
1896
1897
1898 /*
1899 * Reset the VM components.
1900 */
1901 PATMR3Reset(pVM);
1902 CSAMR3Reset(pVM);
1903 PGMR3Reset(pVM); /* We clear VM RAM in PGMR3Reset. It's vital PDMR3Reset is executed
1904 * _afterwards_. E.g. ACPI sets up RAM tables during init/reset. */
1905 MMR3Reset(pVM);
1906 PDMR3Reset(pVM);
1907 SELMR3Reset(pVM);
1908 TRPMR3Reset(pVM);
1909 vmR3AtResetU(pVM->pUVM);
1910 REMR3Reset(pVM);
1911 IOMR3Reset(pVM);
1912 CPUMR3Reset(pVM);
1913 TMR3Reset(pVM);
1914 EMR3Reset(pVM);
1915 HWACCMR3Reset(pVM); /* This must come *after* PATM, CSAM, CPUM, SELM and TRPM. */
1916
1917#ifdef LOG_ENABLED
1918 /*
1919 * Debug logging.
1920 */
1921 RTLogPrintf("\n\nThe VM was reset:\n");
1922 DBGFR3Info(pVM, "cpum", "verbose", NULL);
1923#endif
1924
1925 /*
1926 * Restore the state.
1927 */
1928 vmR3CheckIntegrity(pVM);
1929 Assert(pVM->enmVMState == VMSTATE_RESETTING);
1930 vmR3SetState(pVM, enmVMState);
1931
1932 return VINF_EM_RESET;
1933}
1934
1935
1936/**
1937 * Walks the list of at VM reset callbacks and calls them
1938 *
1939 * @returns VBox status code.
1940 * Any failure is fatal.
1941 * @param pUVM Pointe to the user mode VM structure.
1942 */
1943static int vmR3AtResetU(PUVM pUVM)
1944{
1945 /*
1946 * Walk the list and call them all.
1947 */
1948 int rc = VINF_SUCCESS;
1949 for (PVMATRESET pCur = pUVM->vm.s.pAtReset; pCur; pCur = pCur->pNext)
1950 {
1951 /* do the call */
1952 switch (pCur->enmType)
1953 {
1954 case VMATRESETTYPE_DEV:
1955 rc = pCur->u.Dev.pfnCallback(pCur->u.Dev.pDevIns, pCur->pvUser);
1956 break;
1957 case VMATRESETTYPE_INTERNAL:
1958 rc = pCur->u.Internal.pfnCallback(pUVM->pVM, pCur->pvUser);
1959 break;
1960 case VMATRESETTYPE_EXTERNAL:
1961 pCur->u.External.pfnCallback(pCur->pvUser);
1962 break;
1963 default:
1964 AssertMsgFailed(("Invalid at-reset type %d!\n", pCur->enmType));
1965 return VERR_INTERNAL_ERROR;
1966 }
1967
1968 if (VBOX_FAILURE(rc))
1969 {
1970 AssertMsgFailed(("At-reset handler %s failed with rc=%d\n", pCur->pszDesc, rc));
1971 return rc;
1972 }
1973 }
1974
1975 return VINF_SUCCESS;
1976}
1977
1978
1979/**
1980 * Internal registration function
1981 */
1982static int vmr3AtResetRegisterU(PUVM pUVM, void *pvUser, const char *pszDesc, PVMATRESET *ppNew)
1983{
1984 /*
1985 * Allocate restration structure.
1986 */
1987 PVMATRESET pNew = (PVMATRESET)MMR3HeapAllocU(pUVM, MM_TAG_VM, sizeof(*pNew));
1988 if (pNew)
1989 {
1990 /* fill data. */
1991 pNew->pNext = NULL;
1992 pNew->pszDesc = pszDesc;
1993 pNew->pvUser = pvUser;
1994
1995 /* insert */
1996 *pUVM->vm.s.ppAtResetNext = pNew;
1997 pUVM->vm.s.ppAtResetNext = &pNew->pNext;
1998
1999 *ppNew = pNew;
2000 return VINF_SUCCESS;
2001 }
2002 return VERR_NO_MEMORY;
2003}
2004
2005
2006/**
2007 * Registers an at VM reset callback.
2008 *
2009 * @returns VBox status code.
2010 * @param pVM The VM.
2011 * @param pDevInst Device instance.
2012 * @param pfnCallback Callback function.
2013 * @param pvUser User argument.
2014 * @param pszDesc Description (optional).
2015 */
2016VMMR3DECL(int) VMR3AtResetRegister(PVM pVM, PPDMDEVINS pDevInst, PFNVMATRESET pfnCallback, void *pvUser, const char *pszDesc)
2017{
2018 /*
2019 * Validate.
2020 */
2021 if (!pDevInst)
2022 {
2023 AssertMsgFailed(("pDevIns is NULL!\n"));
2024 return VERR_INVALID_PARAMETER;
2025 }
2026
2027 /*
2028 * Create the new entry.
2029 */
2030 PVMATRESET pNew;
2031 int rc = vmr3AtResetRegisterU(pVM->pUVM, pvUser, pszDesc, &pNew);
2032 if (VBOX_SUCCESS(rc))
2033 {
2034 /*
2035 * Fill in type data.
2036 */
2037 pNew->enmType = VMATRESETTYPE_DEV;
2038 pNew->u.Dev.pfnCallback = pfnCallback;
2039 pNew->u.Dev.pDevIns = pDevInst;
2040 }
2041
2042 return rc;
2043}
2044
2045
2046/**
2047 * Registers an at VM reset internal callback.
2048 *
2049 * @returns VBox status code.
2050 * @param pVM The VM.
2051 * @param pfnCallback Callback function.
2052 * @param pvUser User argument.
2053 * @param pszDesc Description (optional).
2054 */
2055VMMR3DECL(int) VMR3AtResetRegisterInternal(PVM pVM, PFNVMATRESETINT pfnCallback, void *pvUser, const char *pszDesc)
2056{
2057 /*
2058 * Validate.
2059 */
2060 if (!pfnCallback)
2061 {
2062 AssertMsgFailed(("pfnCallback is NULL!\n"));
2063 return VERR_INVALID_PARAMETER;
2064 }
2065
2066 /*
2067 * Create the new entry.
2068 */
2069 PVMATRESET pNew;
2070 int rc = vmr3AtResetRegisterU(pVM->pUVM, pvUser, pszDesc, &pNew);
2071 if (VBOX_SUCCESS(rc))
2072 {
2073 /*
2074 * Fill in type data.
2075 */
2076 pNew->enmType = VMATRESETTYPE_INTERNAL;
2077 pNew->u.Internal.pfnCallback = pfnCallback;
2078 }
2079
2080 return rc;
2081}
2082
2083
2084/**
2085 * Registers an at VM reset external callback.
2086 *
2087 * @returns VBox status code.
2088 * @param pVM The VM.
2089 * @param pfnCallback Callback function.
2090 * @param pvUser User argument.
2091 * @param pszDesc Description (optional).
2092 */
2093VMMR3DECL(int) VMR3AtResetRegisterExternal(PVM pVM, PFNVMATRESETEXT pfnCallback, void *pvUser, const char *pszDesc)
2094{
2095 /*
2096 * Validate.
2097 */
2098 if (!pfnCallback)
2099 {
2100 AssertMsgFailed(("pfnCallback is NULL!\n"));
2101 return VERR_INVALID_PARAMETER;
2102 }
2103
2104 /*
2105 * Create the new entry.
2106 */
2107 PVMATRESET pNew;
2108 int rc = vmr3AtResetRegisterU(pVM->pUVM, pvUser, pszDesc, &pNew);
2109 if (VBOX_SUCCESS(rc))
2110 {
2111 /*
2112 * Fill in type data.
2113 */
2114 pNew->enmType = VMATRESETTYPE_EXTERNAL;
2115 pNew->u.External.pfnCallback = pfnCallback;
2116 }
2117
2118 return rc;
2119}
2120
2121
2122/**
2123 * Unlinks and frees a callback.
2124 *
2125 * @returns Pointer to the next callback structure.
2126 * @param pUVM Pointer to the user mode VM structure.
2127 * @param pCur The one to free.
2128 * @param pPrev The one before pCur.
2129 */
2130static PVMATRESET vmr3AtResetFreeU(PUVM pUVM, PVMATRESET pCur, PVMATRESET pPrev)
2131{
2132 /*
2133 * Unlink it.
2134 */
2135 PVMATRESET pNext = pCur->pNext;
2136 if (pPrev)
2137 {
2138 pPrev->pNext = pNext;
2139 if (!pNext)
2140 pUVM->vm.s.ppAtResetNext = &pPrev->pNext;
2141 }
2142 else
2143 {
2144 pUVM->vm.s.pAtReset = pNext;
2145 if (!pNext)
2146 pUVM->vm.s.ppAtResetNext = &pUVM->vm.s.pAtReset;
2147 }
2148
2149 /*
2150 * Free it.
2151 */
2152 MMR3HeapFree(pCur);
2153
2154 return pNext;
2155}
2156
2157
2158/**
2159 * Deregisters an at VM reset callback.
2160 *
2161 * @returns VBox status code.
2162 * @param pVM The VM.
2163 * @param pDevInst Device instance.
2164 * @param pfnCallback Callback function.
2165 */
2166VMMR3DECL(int) VMR3AtResetDeregister(PVM pVM, PPDMDEVINS pDevInst, PFNVMATRESET pfnCallback)
2167{
2168 int rc = VERR_VM_ATRESET_NOT_FOUND;
2169 PVMATRESET pPrev = NULL;
2170 PVMATRESET pCur = pVM->pUVM->vm.s.pAtReset;
2171 while (pCur)
2172 {
2173 if ( pCur->enmType == VMATRESETTYPE_DEV
2174 && pCur->u.Dev.pDevIns == pDevInst
2175 && (!pfnCallback || pCur->u.Dev.pfnCallback == pfnCallback))
2176 {
2177 pCur = vmr3AtResetFreeU(pVM->pUVM, pCur, pPrev);
2178 rc = VINF_SUCCESS;
2179 }
2180 else
2181 {
2182 pPrev = pCur;
2183 pCur = pCur->pNext;
2184 }
2185 }
2186
2187 AssertRC(rc);
2188 return rc;
2189}
2190
2191
2192/**
2193 * Deregisters an at VM reset internal callback.
2194 *
2195 * @returns VBox status code.
2196 * @param pVM The VM.
2197 * @param pfnCallback Callback function.
2198 */
2199VMMR3DECL(int) VMR3AtResetDeregisterInternal(PVM pVM, PFNVMATRESETINT pfnCallback)
2200{
2201 int rc = VERR_VM_ATRESET_NOT_FOUND;
2202 PVMATRESET pPrev = NULL;
2203 PVMATRESET pCur = pVM->pUVM->vm.s.pAtReset;
2204 while (pCur)
2205 {
2206 if ( pCur->enmType == VMATRESETTYPE_INTERNAL
2207 && pCur->u.Internal.pfnCallback == pfnCallback)
2208 {
2209 pCur = vmr3AtResetFreeU(pVM->pUVM, pCur, pPrev);
2210 rc = VINF_SUCCESS;
2211 }
2212 else
2213 {
2214 pPrev = pCur;
2215 pCur = pCur->pNext;
2216 }
2217 }
2218
2219 AssertRC(rc);
2220 return rc;
2221}
2222
2223
2224/**
2225 * Deregisters an at VM reset external callback.
2226 *
2227 * @returns VBox status code.
2228 * @param pVM The VM.
2229 * @param pfnCallback Callback function.
2230 */
2231VMMR3DECL(int) VMR3AtResetDeregisterExternal(PVM pVM, PFNVMATRESETEXT pfnCallback)
2232{
2233 int rc = VERR_VM_ATRESET_NOT_FOUND;
2234 PVMATRESET pPrev = NULL;
2235 PVMATRESET pCur = pVM->pUVM->vm.s.pAtReset;
2236 while (pCur)
2237 {
2238 if ( pCur->enmType == VMATRESETTYPE_INTERNAL
2239 && pCur->u.External.pfnCallback == pfnCallback)
2240 {
2241 pCur = vmr3AtResetFreeU(pVM->pUVM, pCur, pPrev);
2242 rc = VINF_SUCCESS;
2243 }
2244 else
2245 {
2246 pPrev = pCur;
2247 pCur = pCur->pNext;
2248 }
2249 }
2250
2251 AssertRC(rc);
2252 return rc;
2253}
2254
2255
2256/**
2257 * Gets the current VM state.
2258 *
2259 * @returns The current VM state.
2260 * @param pVM VM handle.
2261 * @thread Any
2262 */
2263VMMR3DECL(VMSTATE) VMR3GetState(PVM pVM)
2264{
2265 return pVM->enmVMState;
2266}
2267
2268
2269/**
2270 * Gets the state name string for a VM state.
2271 *
2272 * @returns Pointer to the state name. (readonly)
2273 * @param enmState The state.
2274 */
2275VMMR3DECL(const char *) VMR3GetStateName(VMSTATE enmState)
2276{
2277 switch (enmState)
2278 {
2279 case VMSTATE_CREATING: return "CREATING";
2280 case VMSTATE_CREATED: return "CREATED";
2281 case VMSTATE_RUNNING: return "RUNNING";
2282 case VMSTATE_LOADING: return "LOADING";
2283 case VMSTATE_LOAD_FAILURE: return "LOAD_FAILURE";
2284 case VMSTATE_SAVING: return "SAVING";
2285 case VMSTATE_SUSPENDED: return "SUSPENDED";
2286 case VMSTATE_RESETTING: return "RESETTING";
2287 case VMSTATE_GURU_MEDITATION: return "GURU_MEDITATION";
2288 case VMSTATE_OFF: return "OFF";
2289 case VMSTATE_DESTROYING: return "DESTROYING";
2290 case VMSTATE_TERMINATED: return "TERMINATED";
2291 default:
2292 AssertMsgFailed(("Unknown state %d\n", enmState));
2293 return "Unknown!\n";
2294 }
2295}
2296
2297
2298/**
2299 * Sets the current VM state.
2300 *
2301 * @returns The current VM state.
2302 * @param pVM VM handle.
2303 * @param enmStateNew The new state.
2304 */
2305void vmR3SetState(PVM pVM, VMSTATE enmStateNew)
2306{
2307 /*
2308 * Validate state machine transitions before doing the actual change.
2309 */
2310 VMSTATE enmStateOld = pVM->enmVMState;
2311 switch (enmStateOld)
2312 {
2313 case VMSTATE_OFF:
2314 Assert(enmStateNew != VMSTATE_GURU_MEDITATION);
2315 break;
2316
2317 default:
2318 /** @todo full validation. */
2319 break;
2320 }
2321
2322 pVM->enmVMState = enmStateNew;
2323 LogRel(("Changing the VM state from '%s' to '%s'.\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)));
2324
2325 /*
2326 * Call the at state change callbacks.
2327 */
2328 for (PVMATSTATE pCur = pVM->pUVM->vm.s.pAtState; pCur; pCur = pCur->pNext)
2329 {
2330 pCur->pfnAtState(pVM, enmStateNew, enmStateOld, pCur->pvUser);
2331 if (pVM->enmVMState == VMSTATE_DESTROYING)
2332 break;
2333 AssertMsg(pVM->enmVMState == enmStateNew,
2334 ("You are not allowed to change the state while in the change callback, except "
2335 "from destroying the VM. There are restrictions in the way the state changes "
2336 "are propagated up to the EM execution loop and it makes the program flow very "
2337 "difficult to follow.\n"));
2338 }
2339}
2340
2341
2342/**
2343 * Registers a VM state change callback.
2344 *
2345 * You are not allowed to call any function which changes the VM state from a
2346 * state callback, except VMR3Destroy().
2347 *
2348 * @returns VBox status code.
2349 * @param pVM VM handle.
2350 * @param pfnAtState Pointer to callback.
2351 * @param pvUser User argument.
2352 * @thread Any.
2353 */
2354VMMR3DECL(int) VMR3AtStateRegister(PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser)
2355{
2356 LogFlow(("VMR3AtStateRegister: pfnAtState=%p pvUser=%p\n", pfnAtState, pvUser));
2357
2358 /*
2359 * Validate input.
2360 */
2361 if (!pfnAtState)
2362 {
2363 AssertMsgFailed(("callback is required\n"));
2364 return VERR_INVALID_PARAMETER;
2365 }
2366
2367 /*
2368 * Make sure we're in EMT (to avoid the logging).
2369 */
2370 PVMREQ pReq;
2371 int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtStateRegisterU, 3, pVM->pUVM, pfnAtState, pvUser);
2372 if (VBOX_FAILURE(rc))
2373 return rc;
2374 rc = pReq->iStatus;
2375 VMR3ReqFree(pReq);
2376
2377 LogFlow(("VMR3AtStateRegister: returns %Vrc\n", rc));
2378 return rc;
2379}
2380
2381
2382/**
2383 * Registers a VM state change callback.
2384 *
2385 * @returns VBox status code.
2386 * @param pUVM Pointer to the user mode VM structure.
2387 * @param pfnAtState Pointer to callback.
2388 * @param pvUser User argument.
2389 * @thread EMT
2390 */
2391static DECLCALLBACK(int) vmR3AtStateRegisterU(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser)
2392{
2393 /*
2394 * Allocate a new record.
2395 */
2396
2397 PVMATSTATE pNew = (PVMATSTATE)MMR3HeapAllocU(pUVM, MM_TAG_VM, sizeof(*pNew));
2398 if (!pNew)
2399 return VERR_NO_MEMORY;
2400
2401 /* fill */
2402 pNew->pfnAtState = pfnAtState;
2403 pNew->pvUser = pvUser;
2404 pNew->pNext = NULL;
2405
2406 /* insert */
2407 *pUVM->vm.s.ppAtStateNext = pNew;
2408 pUVM->vm.s.ppAtStateNext = &pNew->pNext;
2409
2410 return VINF_SUCCESS;
2411}
2412
2413
2414/**
2415 * Deregisters a VM state change callback.
2416 *
2417 * @returns VBox status code.
2418 * @param pVM VM handle.
2419 * @param pfnAtState Pointer to callback.
2420 * @param pvUser User argument.
2421 * @thread Any.
2422 */
2423VMMR3DECL(int) VMR3AtStateDeregister(PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser)
2424{
2425 LogFlow(("VMR3AtStateDeregister: pfnAtState=%p pvUser=%p\n", pfnAtState, pvUser));
2426
2427 /*
2428 * Validate input.
2429 */
2430 if (!pfnAtState)
2431 {
2432 AssertMsgFailed(("callback is required\n"));
2433 return VERR_INVALID_PARAMETER;
2434 }
2435
2436 /*
2437 * Make sure we're in EMT (to avoid the logging).
2438 */
2439 PVMREQ pReq;
2440 int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtStateDeregisterU, 3, pVM->pUVM, pfnAtState, pvUser);
2441 if (VBOX_FAILURE(rc))
2442 return rc;
2443 rc = pReq->iStatus;
2444 VMR3ReqFree(pReq);
2445
2446 LogFlow(("VMR3AtStateDeregister: returns %Vrc\n", rc));
2447 return rc;
2448}
2449
2450
2451/**
2452 * Deregisters a VM state change callback.
2453 *
2454 * @returns VBox status code.
2455 * @param pUVM Pointer to the user mode VM structure.
2456 * @param pfnAtState Pointer to callback.
2457 * @param pvUser User argument.
2458 * @thread EMT
2459 */
2460static DECLCALLBACK(int) vmR3AtStateDeregisterU(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser)
2461{
2462 LogFlow(("vmR3AtStateDeregisterU: pfnAtState=%p pvUser=%p\n", pfnAtState, pvUser));
2463
2464 /*
2465 * Search the list for the entry.
2466 */
2467 PVMATSTATE pPrev = NULL;
2468 PVMATSTATE pCur = pUVM->vm.s.pAtState;
2469 while ( pCur
2470 && pCur->pfnAtState == pfnAtState
2471 && pCur->pvUser == pvUser)
2472 {
2473 pPrev = pCur;
2474 pCur = pCur->pNext;
2475 }
2476 if (!pCur)
2477 {
2478 AssertMsgFailed(("pfnAtState=%p was not found\n", pfnAtState));
2479 return VERR_FILE_NOT_FOUND;
2480 }
2481
2482 /*
2483 * Unlink it.
2484 */
2485 if (pPrev)
2486 {
2487 pPrev->pNext = pCur->pNext;
2488 if (!pCur->pNext)
2489 pUVM->vm.s.ppAtStateNext = &pPrev->pNext;
2490 }
2491 else
2492 {
2493 pUVM->vm.s.pAtState = pCur->pNext;
2494 if (!pCur->pNext)
2495 pUVM->vm.s.ppAtStateNext = &pUVM->vm.s.pAtState;
2496 }
2497
2498 /*
2499 * Free it.
2500 */
2501 pCur->pfnAtState = NULL;
2502 pCur->pNext = NULL;
2503 MMR3HeapFree(pCur);
2504
2505 return VINF_SUCCESS;
2506}
2507
2508
2509/**
2510 * Registers a VM error callback.
2511 *
2512 * @returns VBox status code.
2513 * @param pVM The VM handle.
2514 * @param pfnAtError Pointer to callback.
2515 * @param pvUser User argument.
2516 * @thread Any.
2517 */
2518VMMR3DECL(int) VMR3AtErrorRegister(PVM pVM, PFNVMATERROR pfnAtError, void *pvUser)
2519{
2520 return VMR3AtErrorRegisterU(pVM->pUVM, pfnAtError, pvUser);
2521}
2522
2523
2524/**
2525 * Registers a VM error callback.
2526 *
2527 * @returns VBox status code.
2528 * @param pUVM The VM handle.
2529 * @param pfnAtError Pointer to callback.
2530 * @param pvUser User argument.
2531 * @thread Any.
2532 */
2533VMMR3DECL(int) VMR3AtErrorRegisterU(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser)
2534{
2535 LogFlow(("VMR3AtErrorRegister: pfnAtError=%p pvUser=%p\n", pfnAtError, pvUser));
2536 AssertPtrReturn(pfnAtError, VERR_INVALID_PARAMETER);
2537
2538 /*
2539 * Make sure we're in EMT (to avoid the logging).
2540 */
2541 PVMREQ pReq;
2542 int rc = VMR3ReqCallU(pUVM, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)vmR3AtErrorRegisterU, 3, pUVM, pfnAtError, pvUser);
2543 if (VBOX_FAILURE(rc))
2544 return rc;
2545 rc = pReq->iStatus;
2546 VMR3ReqFree(pReq);
2547
2548 LogFlow(("VMR3AtErrorRegister: returns %Vrc\n", rc));
2549 return rc;
2550}
2551
2552
2553/**
2554 * Registers a VM error callback.
2555 *
2556 * @returns VBox status code.
2557 * @param pUVM Pointer to the user mode VM structure.
2558 * @param pfnAtError Pointer to callback.
2559 * @param pvUser User argument.
2560 * @thread EMT
2561 */
2562static DECLCALLBACK(int) vmR3AtErrorRegisterU(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser)
2563{
2564 /*
2565 * Allocate a new record.
2566 */
2567
2568 PVMATERROR pNew = (PVMATERROR)MMR3HeapAllocU(pUVM, MM_TAG_VM, sizeof(*pNew));
2569 if (!pNew)
2570 return VERR_NO_MEMORY;
2571
2572 /* fill */
2573 pNew->pfnAtError = pfnAtError;
2574 pNew->pvUser = pvUser;
2575 pNew->pNext = NULL;
2576
2577 /* insert */
2578 *pUVM->vm.s.ppAtErrorNext = pNew;
2579 pUVM->vm.s.ppAtErrorNext = &pNew->pNext;
2580
2581 return VINF_SUCCESS;
2582}
2583
2584
2585/**
2586 * Deregisters a VM error callback.
2587 *
2588 * @returns VBox status code.
2589 * @param pVM The VM handle.
2590 * @param pfnAtError Pointer to callback.
2591 * @param pvUser User argument.
2592 * @thread Any.
2593 */
2594VMMR3DECL(int) VMR3AtErrorDeregister(PVM pVM, PFNVMATERROR pfnAtError, void *pvUser)
2595{
2596 LogFlow(("VMR3AtErrorDeregister: pfnAtError=%p pvUser=%p\n", pfnAtError, pvUser));
2597
2598 /*
2599 * Validate input.
2600 */
2601 if (!pfnAtError)
2602 {
2603 AssertMsgFailed(("callback is required\n"));
2604 return VERR_INVALID_PARAMETER;
2605 }
2606
2607 /*
2608 * Make sure we're in EMT (to avoid the logging).
2609 */
2610 PVMREQ pReq;
2611 int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtErrorDeregisterU, 3, pVM->pUVM, pfnAtError, pvUser);
2612 if (VBOX_FAILURE(rc))
2613 return rc;
2614 rc = pReq->iStatus;
2615 VMR3ReqFree(pReq);
2616
2617 LogFlow(("VMR3AtErrorDeregister: returns %Vrc\n", rc));
2618 return rc;
2619}
2620
2621
2622/**
2623 * Deregisters a VM error callback.
2624 *
2625 * @returns VBox status code.
2626 * @param pUVM Pointer to the user mode VM structure.
2627 * @param pfnAtError Pointer to callback.
2628 * @param pvUser User argument.
2629 * @thread EMT
2630 */
2631static DECLCALLBACK(int) vmR3AtErrorDeregisterU(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser)
2632{
2633 LogFlow(("vmR3AtErrorDeregisterU: pfnAtError=%p pvUser=%p\n", pfnAtError, pvUser));
2634
2635 /*
2636 * Search the list for the entry.
2637 */
2638 PVMATERROR pPrev = NULL;
2639 PVMATERROR pCur = pUVM->vm.s.pAtError;
2640 while ( pCur
2641 && pCur->pfnAtError == pfnAtError
2642 && pCur->pvUser == pvUser)
2643 {
2644 pPrev = pCur;
2645 pCur = pCur->pNext;
2646 }
2647 if (!pCur)
2648 {
2649 AssertMsgFailed(("pfnAtError=%p was not found\n", pfnAtError));
2650 return VERR_FILE_NOT_FOUND;
2651 }
2652
2653 /*
2654 * Unlink it.
2655 */
2656 if (pPrev)
2657 {
2658 pPrev->pNext = pCur->pNext;
2659 if (!pCur->pNext)
2660 pUVM->vm.s.ppAtErrorNext = &pPrev->pNext;
2661 }
2662 else
2663 {
2664 pUVM->vm.s.pAtError = pCur->pNext;
2665 if (!pCur->pNext)
2666 pUVM->vm.s.ppAtErrorNext = &pUVM->vm.s.pAtError;
2667 }
2668
2669 /*
2670 * Free it.
2671 */
2672 pCur->pfnAtError = NULL;
2673 pCur->pNext = NULL;
2674 MMR3HeapFree(pCur);
2675
2676 return VINF_SUCCESS;
2677}
2678
2679
2680/**
2681 * Ellipsis to va_list wrapper for calling pfnAtError.
2682 */
2683static void vmR3SetErrorWorkerDoCall(PVM pVM, PVMATERROR pCur, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
2684{
2685 va_list va;
2686 va_start(va, pszFormat);
2687 pCur->pfnAtError(pVM, pCur->pvUser, rc, RT_SRC_POS_ARGS, pszFormat, va);
2688 va_end(va);
2689}
2690
2691
2692/**
2693 * This is a worker function for GC and Ring-0 calls to VMSetError and VMSetErrorV.
2694 * The message is found in VMINT.
2695 *
2696 * @param pVM The VM handle.
2697 * @thread EMT.
2698 */
2699VMMR3DECL(void) VMR3SetErrorWorker(PVM pVM)
2700{
2701 VM_ASSERT_EMT(pVM);
2702 AssertReleaseMsgFailed(("And we have a winner! You get to implement Ring-0 and GC VMSetErrorV! Contrats!\n"));
2703
2704 /*
2705 * Unpack the error (if we managed to format one).
2706 */
2707 PVMERROR pErr = pVM->vm.s.pErrorR3;
2708 const char *pszFile = NULL;
2709 const char *pszFunction = NULL;
2710 uint32_t iLine = 0;
2711 const char *pszMessage;
2712 int32_t rc = VERR_MM_HYPER_NO_MEMORY;
2713 if (pErr)
2714 {
2715 AssertCompile(sizeof(const char) == sizeof(uint8_t));
2716 if (pErr->offFile)
2717 pszFile = (const char *)pErr + pErr->offFile;
2718 iLine = pErr->iLine;
2719 if (pErr->offFunction)
2720 pszFunction = (const char *)pErr + pErr->offFunction;
2721 if (pErr->offMessage)
2722 pszMessage = (const char *)pErr + pErr->offMessage;
2723 else
2724 pszMessage = "No message!";
2725 }
2726 else
2727 pszMessage = "No message! (Failed to allocate memory to put the error message in!)";
2728
2729 /*
2730 * Call the at error callbacks.
2731 */
2732 for (PVMATERROR pCur = pVM->pUVM->vm.s.pAtError; pCur; pCur = pCur->pNext)
2733 vmR3SetErrorWorkerDoCall(pVM, pCur, rc, RT_SRC_POS_ARGS, "%s", pszMessage);
2734}
2735
2736
2737/**
2738 * Creation time wrapper for vmR3SetErrorUV.
2739 *
2740 * @returns rc.
2741 * @param pUVM Pointer to the user mode VM structure.
2742 * @param rc The VBox status code.
2743 * @param RT_SRC_POS_DECL The source position of this error.
2744 * @param pszFormat Format string.
2745 * @param ... The arguments.
2746 * @thread Any thread.
2747 */
2748static int vmR3SetErrorU(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
2749{
2750 va_list va;
2751 va_start(va, pszFormat);
2752 vmR3SetErrorUV(pUVM, rc, pszFile, iLine, pszFunction, pszFormat, &va);
2753 va_end(va);
2754 return rc;
2755}
2756
2757
2758/**
2759 * Worker which calls everyone listening to the VM error messages.
2760 *
2761 * @param pUVM Pointer to the user mode VM structure.
2762 * @param rc The VBox status code.
2763 * @param RT_SRC_POS_DECL The source position of this error.
2764 * @param pszFormat Format string.
2765 * @param pArgs Pointer to the format arguments.
2766 * @thread EMT
2767 */
2768DECLCALLBACK(void) vmR3SetErrorUV(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list *pArgs)
2769{
2770#ifdef LOG_ENABLED
2771 /*
2772 * Log the error.
2773 */
2774 RTLogPrintf("VMSetError: %s(%d) %s\n", pszFile, iLine, pszFunction);
2775 va_list va3;
2776 va_copy(va3, *pArgs);
2777 RTLogPrintfV(pszFormat, va3);
2778 va_end(va3);
2779 RTLogPrintf("\n");
2780#endif
2781
2782 /*
2783 * Make a copy of the message.
2784 */
2785 if (pUVM->pVM)
2786 vmSetErrorCopy(pUVM->pVM, rc, RT_SRC_POS_ARGS, pszFormat, *pArgs);
2787
2788 /*
2789 * Call the at error callbacks.
2790 */
2791 for (PVMATERROR pCur = pUVM->vm.s.pAtError; pCur; pCur = pCur->pNext)
2792 {
2793 va_list va2;
2794 va_copy(va2, *pArgs);
2795 pCur->pfnAtError(pUVM->pVM, pCur->pvUser, rc, RT_SRC_POS_ARGS, pszFormat, va2);
2796 va_end(va2);
2797 }
2798}
2799
2800
2801/**
2802 * Registers a VM runtime error callback.
2803 *
2804 * @returns VBox status code.
2805 * @param pVM The VM handle.
2806 * @param pfnAtRuntimeError Pointer to callback.
2807 * @param pvUser User argument.
2808 * @thread Any.
2809 */
2810VMMR3DECL(int) VMR3AtRuntimeErrorRegister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser)
2811{
2812 LogFlow(("VMR3AtRuntimeErrorRegister: pfnAtRuntimeError=%p pvUser=%p\n", pfnAtRuntimeError, pvUser));
2813
2814 /*
2815 * Validate input.
2816 */
2817 if (!pfnAtRuntimeError)
2818 {
2819 AssertMsgFailed(("callback is required\n"));
2820 return VERR_INVALID_PARAMETER;
2821 }
2822
2823 /*
2824 * Make sure we're in EMT (to avoid the logging).
2825 */
2826 PVMREQ pReq;
2827 int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtRuntimeErrorRegisterU, 3, pVM->pUVM, pfnAtRuntimeError, pvUser);
2828 if (VBOX_FAILURE(rc))
2829 return rc;
2830 rc = pReq->iStatus;
2831 VMR3ReqFree(pReq);
2832
2833 LogFlow(("VMR3AtRuntimeErrorRegister: returns %Vrc\n", rc));
2834 return rc;
2835}
2836
2837
2838/**
2839 * Registers a VM runtime error callback.
2840 *
2841 * @returns VBox status code.
2842 * @param pUVM Pointer to the user mode VM structure.
2843 * @param pfnAtRuntimeError Pointer to callback.
2844 * @param pvUser User argument.
2845 * @thread EMT
2846 */
2847static DECLCALLBACK(int) vmR3AtRuntimeErrorRegisterU(PUVM pUVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser)
2848{
2849 /*
2850 * Allocate a new record.
2851 */
2852
2853 PVMATRUNTIMEERROR pNew = (PVMATRUNTIMEERROR)MMR3HeapAllocU(pUVM, MM_TAG_VM, sizeof(*pNew));
2854 if (!pNew)
2855 return VERR_NO_MEMORY;
2856
2857 /* fill */
2858 pNew->pfnAtRuntimeError = pfnAtRuntimeError;
2859 pNew->pvUser = pvUser;
2860 pNew->pNext = NULL;
2861
2862 /* insert */
2863 *pUVM->vm.s.ppAtRuntimeErrorNext = pNew;
2864 pUVM->vm.s.ppAtRuntimeErrorNext = &pNew->pNext;
2865
2866 return VINF_SUCCESS;
2867}
2868
2869
2870/**
2871 * Deregisters a VM runtime error callback.
2872 *
2873 * @returns VBox status code.
2874 * @param pVM The VM handle.
2875 * @param pfnAtRuntimeError Pointer to callback.
2876 * @param pvUser User argument.
2877 * @thread Any.
2878 */
2879VMMR3DECL(int) VMR3AtRuntimeErrorDeregister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser)
2880{
2881 LogFlow(("VMR3AtRuntimeErrorDeregister: pfnAtRuntimeError=%p pvUser=%p\n", pfnAtRuntimeError, pvUser));
2882
2883 /*
2884 * Validate input.
2885 */
2886 if (!pfnAtRuntimeError)
2887 {
2888 AssertMsgFailed(("callback is required\n"));
2889 return VERR_INVALID_PARAMETER;
2890 }
2891
2892 /*
2893 * Make sure we're in EMT (to avoid the logging).
2894 */
2895 PVMREQ pReq;
2896 int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtRuntimeErrorDeregisterU, 3, pVM->pUVM, pfnAtRuntimeError, pvUser);
2897 if (VBOX_FAILURE(rc))
2898 return rc;
2899 rc = pReq->iStatus;
2900 VMR3ReqFree(pReq);
2901
2902 LogFlow(("VMR3AtRuntimeErrorDeregister: returns %Vrc\n", rc));
2903 return rc;
2904}
2905
2906
2907/**
2908 * Deregisters a VM runtime error callback.
2909 *
2910 * @returns VBox status code.
2911 * @param pUVM Pointer to the user mode VM structure.
2912 * @param pfnAtRuntimeError Pointer to callback.
2913 * @param pvUser User argument.
2914 * @thread EMT
2915 */
2916static DECLCALLBACK(int) vmR3AtRuntimeErrorDeregisterU(PUVM pUVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser)
2917{
2918 LogFlow(("vmR3AtRuntimeErrorDeregisterU: pfnAtRuntimeError=%p pvUser=%p\n", pfnAtRuntimeError, pvUser));
2919
2920 /*
2921 * Search the list for the entry.
2922 */
2923 PVMATRUNTIMEERROR pPrev = NULL;
2924 PVMATRUNTIMEERROR pCur = pUVM->vm.s.pAtRuntimeError;
2925 while ( pCur
2926 && pCur->pfnAtRuntimeError == pfnAtRuntimeError
2927 && pCur->pvUser == pvUser)
2928 {
2929 pPrev = pCur;
2930 pCur = pCur->pNext;
2931 }
2932 if (!pCur)
2933 {
2934 AssertMsgFailed(("pfnAtRuntimeError=%p was not found\n", pfnAtRuntimeError));
2935 return VERR_FILE_NOT_FOUND;
2936 }
2937
2938 /*
2939 * Unlink it.
2940 */
2941 if (pPrev)
2942 {
2943 pPrev->pNext = pCur->pNext;
2944 if (!pCur->pNext)
2945 pUVM->vm.s.ppAtRuntimeErrorNext = &pPrev->pNext;
2946 }
2947 else
2948 {
2949 pUVM->vm.s.pAtRuntimeError = pCur->pNext;
2950 if (!pCur->pNext)
2951 pUVM->vm.s.ppAtRuntimeErrorNext = &pUVM->vm.s.pAtRuntimeError;
2952 }
2953
2954 /*
2955 * Free it.
2956 */
2957 pCur->pfnAtRuntimeError = NULL;
2958 pCur->pNext = NULL;
2959 MMR3HeapFree(pCur);
2960
2961 return VINF_SUCCESS;
2962}
2963
2964
2965/**
2966 * Ellipsis to va_list wrapper for calling pfnAtRuntimeError.
2967 */
2968static void vmR3SetRuntimeErrorWorkerDoCall(PVM pVM, PVMATRUNTIMEERROR pCur, bool fFatal,
2969 const char *pszErrorID,
2970 const char *pszFormat, ...)
2971{
2972 va_list va;
2973 va_start(va, pszFormat);
2974 pCur->pfnAtRuntimeError(pVM, pCur->pvUser, fFatal, pszErrorID, pszFormat, va);
2975 va_end(va);
2976}
2977
2978
2979/**
2980 * This is a worker function for GC and Ring-0 calls to VMSetError and VMSetErrorV.
2981 * The message is found in VMINT.
2982 *
2983 * @param pVM The VM handle.
2984 * @thread EMT.
2985 */
2986VMMR3DECL(void) VMR3SetRuntimeErrorWorker(PVM pVM)
2987{
2988 VM_ASSERT_EMT(pVM);
2989 AssertReleaseMsgFailed(("And we have a winner! You get to implement Ring-0 and GC VMSetRuntimeErrorV! Contrats!\n"));
2990
2991 /*
2992 * Unpack the error (if we managed to format one).
2993 */
2994 PVMRUNTIMEERROR pErr = pVM->vm.s.pRuntimeErrorR3;
2995 const char *pszErrorID = NULL;
2996 const char *pszMessage;
2997 bool fFatal = false;
2998 if (pErr)
2999 {
3000 AssertCompile(sizeof(const char) == sizeof(uint8_t));
3001 if (pErr->offErrorID)
3002 pszErrorID = (const char *)pErr + pErr->offErrorID;
3003 if (pErr->offMessage)
3004 pszMessage = (const char *)pErr + pErr->offMessage;
3005 else
3006 pszMessage = "No message!";
3007 fFatal = pErr->fFatal;
3008 }
3009 else
3010 pszMessage = "No message! (Failed to allocate memory to put the error message in!)";
3011
3012 /*
3013 * Call the at runtime error callbacks.
3014 */
3015 for (PVMATRUNTIMEERROR pCur = pVM->pUVM->vm.s.pAtRuntimeError; pCur; pCur = pCur->pNext)
3016 vmR3SetRuntimeErrorWorkerDoCall(pVM, pCur, fFatal, pszErrorID, "%s", pszMessage);
3017}
3018
3019
3020/**
3021 * Worker which calls everyone listening to the VM runtime error messages.
3022 *
3023 * @param pVM The VM handle.
3024 * @param fFatal Whether it is a fatal error or not.
3025 * @param pszErrorID Error ID string.
3026 * @param pszFormat Format string.
3027 * @param pArgs Pointer to the format arguments.
3028 * @thread EMT
3029 */
3030DECLCALLBACK(void) vmR3SetRuntimeErrorV(PVM pVM, bool fFatal,
3031 const char *pszErrorID,
3032 const char *pszFormat, va_list *pArgs)
3033{
3034 /*
3035 * Make a copy of the message.
3036 */
3037 vmSetRuntimeErrorCopy(pVM, fFatal, pszErrorID, pszFormat, *pArgs);
3038
3039 /*
3040 * Call the at error callbacks.
3041 */
3042 for (PVMATRUNTIMEERROR pCur = pVM->pUVM->vm.s.pAtRuntimeError; pCur; pCur = pCur->pNext)
3043 {
3044 va_list va2;
3045 va_copy(va2, *pArgs);
3046 pCur->pfnAtRuntimeError(pVM, pCur->pvUser, fFatal, pszErrorID, pszFormat, va2);
3047 va_end(va2);
3048 }
3049}
3050
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