VirtualBox

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

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

VM.cpp: Fixed three copy&past errors in the state, error and runtime-error deregistration code.

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