VirtualBox

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

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

VMM: correct report cores count, also expose more CPUID leaves by default

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