VirtualBox

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

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

VMM++: More on poking. Fixed broken R0 stats (wrong way of calling into VMMR0), use NIL_VMCPUID instead of 0 to VMMR0EntryEx when it is supposed to be irrellevant. Use VMCPUID. Allow for and check NIL_VMCPUID. Fixed a few missing/wrong idCpu checks (paranoia mostly).

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