VirtualBox

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

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

Send power on requests to all VCPUs.

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