VirtualBox

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

Last change on this file since 19089 was 19089, checked in by vboxsync, 15 years ago

VMM: Fixed cleanup issue where the EMT was left behind by always waiting for the EMTs in vmR3DestroyUVM.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 102.8 KB
Line 
1/* $Id: VM.cpp 19089 2009-04-21 17:31:47Z 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->fForcedActions, 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, false);
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