VirtualBox

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

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

disable VT-x on Linux < 2.6.13

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