VirtualBox

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

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

Action flags breakup.
Fixed PGM saved state loading of 2.2.2 images.
Reduced hacks in PATM state loading (fixups).

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