VirtualBox

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

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

VM::cCPUs -> VM::cCpus so it matches all the other cCpus and aCpus members.

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