VirtualBox

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

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

VMReq,*: Replaced VMREQDEST with VMCPUID because it's a pain to have to cast CPU IDs all the time.

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