VirtualBox

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

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

typo

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