VM.cpp revision 70e70d246c1b592db31d93071c48bb43ea61100e
ee29f83d0638dba8e0380d7f594fe2d726d9403cvboxsync * VM - Virtual Machine
613c0d015cbaef93be47fc03f0708744c5c24f79vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * available from http://www.virtualbox.org. This file is free software;
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * you can redistribute it and/or modify it under the terms of the GNU
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * General Public License (GPL) as published by the Free Software
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
613c0d015cbaef93be47fc03f0708744c5c24f79vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * additional information or have any questions.
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync/** @page pg_vm VM API
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * This is the encapsulating bit. It provides the APIs that Main and VBoxBFE
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * use to create a VMM instance for running a guest in. It also provides
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * facilities for queuing request for execution in EMT (serialization purposes
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * mostly) and for reporting error back to the VMM user (Main/VBoxBFE).
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * @section sec_vm_design Design Critique / Things To Do
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * In hindsight this component is a big design mistake, all this stuff really
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * belongs in the VMM component. It just seemed like a kind of ok idea at a
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * time when the VMM bit was a kind of vague. 'VM' also happend to be the name
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * of the per-VM instance structure (see vm.h), so it kind of made sense.
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * However as it turned out, VMM(.cpp) is almost empty all it provides in ring-3
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * is some minor functionally and some "routing" services.
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * Fixing this is just a matter of some more or less straight forward
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * refactoring, the question is just when someone will get to it. Moving the EMT
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync * would be a good start.
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync/*******************************************************************************
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync* Header Files *
7bff28e0cedd8656acd24b420759649184d8cf00vboxsync*******************************************************************************/
#include "VMInternal.h"
typedef struct VMATDTOR
void *pvUser;
} VMATDTOR;
#define VM_ATDTOR_LOCK() do { } while (0)
#define VM_ATDTOR_UNLOCK() do { } while (0)
static int vmR3CreateU(PUVM pUVM, uint32_t cCpus, PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUserCFGM);
static DECLCALLBACK(size_t) vmR3LogPrefixCallback(PRTLOGGER pLogger, char *pchBuf, size_t cchBuf, void *pvUser);
static bool volatile s_fDone = false;
if (s_fDone)
return VINF_SUCCESS;
s_fDone = true;
return VINF_SUCCESS;
* @param pfnCFGMConstructor Pointer to callback function for constructing the VM configuration tree.
VMMR3DECL(int) VMR3Create(uint32_t cCpus, PFNVMATERROR pfnVMAtError, void *pvUserVM, PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUserCFGM, PVM *ppVM)
LogFlow(("VMR3Create: cCpus=%RU32 pfnVMAtError=%p pvUserVM=%p pfnCFGMConstructor=%p pvUserCFGM=%p ppVM=%p\n",
static bool fGlobalInitDone = false;
if (!fGlobalInitDone)
return rc;
fGlobalInitDone = true;
AssertLogRelMsgReturn(cCpus > 0 && cCpus <= VMM_MAX_CPU_COUNT, ("%RU32\n", cCpus), VERR_TOO_MANY_CPUS);
return rc;
if (pfnVMAtError)
return VINF_SUCCESS;
switch (rc)
#ifdef RT_OS_LINUX
pszError = N_("VirtualBox can't operate in VMX root mode. Please close all other virtualization programs.");
case VERR_SVM_IN_USE:
#ifdef RT_OS_LINUX
pszError = N_("VirtualBox can't enable the AMD-V extension. Please close all other virtualization programs.");
case VERR_VERSION_MISMATCH:
#ifdef RT_OS_LINUX
#ifdef RT_OS_LINUX
const char *pszError;
switch (rc)
#ifdef RT_OS_LINUX
#ifdef VBOX_WITH_HARDENING
# if defined(RT_OS_DARWIN)
#ifdef RT_OS_LINUX
case VERR_NO_MEMORY:
case VERR_VERSION_MISMATCH:
return rc;
uint32_t i;
for (i = 0; i < cCpus; i++)
for (i = 0; i < cCpus; i++)
for (i = 0; i < cCpus; i++)
for (i = 0; i < cCpus; i++)
return VINF_SUCCESS;
for (i = 0; i < cCpus; i++)
return rc;
static int vmR3CreateU(PUVM pUVM, uint32_t cCpus, PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUserCFGM)
AssertLogRelMsgRC(rc, ("Configuration error: Querying \"NumCPUs\" as integer failed, rc=%Rrc\n", rc));
AssertLogRelMsgFailed(("Configuration error: \"NumCPUs\"=%RU32 and VMR3CreateVM::cCpus=%RU32 does not match!\n",
#ifdef VBOX_WITH_DEBUGGER
#ifdef LOG_ENABLED
return VINF_SUCCESS;
#ifdef VBOX_WITH_DEBUGGER
return rc;
return rc;
int rc;
return rc;
STAM_REG(pVM, &pVM->StatTotalInGC, STAMTYPE_PROFILE_ADV, "/PROF/VM/InGC", STAMUNIT_TICKS_PER_CALL, "Profiling the total time spent in GC.");
STAM_REG(pVM, &pVM->StatSwitcherToGC, STAMTYPE_PROFILE_ADV, "/PROF/VM/SwitchToGC", STAMUNIT_TICKS_PER_CALL, "Profiling switching to GC.");
STAM_REG(pVM, &pVM->StatSwitcherToHC, STAMTYPE_PROFILE_ADV, "/PROF/VM/SwitchToHC", STAMUNIT_TICKS_PER_CALL, "Profiling switching to HC.");
STAM_REG(pVM, &pVM->StatSwitcherSaveRegs, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/SaveRegs", STAMUNIT_TICKS_PER_CALL,"Profiling switching to GC.");
STAM_REG(pVM, &pVM->StatSwitcherSysEnter, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/SysEnter", STAMUNIT_TICKS_PER_CALL,"Profiling switching to GC.");
STAM_REG(pVM, &pVM->StatSwitcherDebug, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/Debug", STAMUNIT_TICKS_PER_CALL,"Profiling switching to GC.");
STAM_REG(pVM, &pVM->StatSwitcherCR0, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/CR0", STAMUNIT_TICKS_PER_CALL, "Profiling switching to GC.");
STAM_REG(pVM, &pVM->StatSwitcherCR4, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/CR4", STAMUNIT_TICKS_PER_CALL, "Profiling switching to GC.");
STAM_REG(pVM, &pVM->StatSwitcherLgdt, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/Lgdt", STAMUNIT_TICKS_PER_CALL, "Profiling switching to GC.");
STAM_REG(pVM, &pVM->StatSwitcherLidt, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/Lidt", STAMUNIT_TICKS_PER_CALL, "Profiling switching to GC.");
STAM_REG(pVM, &pVM->StatSwitcherLldt, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/Lldt", STAMUNIT_TICKS_PER_CALL, "Profiling switching to GC.");
STAM_REG(pVM, &pVM->StatSwitcherTSS, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/TSS", STAMUNIT_TICKS_PER_CALL, "Profiling switching to GC.");
STAM_REG(pVM, &pVM->StatSwitcherJmpCR3, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/JmpCR3", STAMUNIT_TICKS_PER_CALL,"Profiling switching to GC.");
STAM_REG(pVM, &pVM->StatSwitcherRstrRegs, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/RstrRegs", STAMUNIT_TICKS_PER_CALL,"Profiling switching to GC.");
rc = STAMR3RegisterF(pVM, &pUVM->aCpus[idCpu].vm.s.StatHaltYield, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling halted state yielding.", "/PROF/VM/CPU%d/Halt/Yield", idCpu);
rc = STAMR3RegisterF(pVM, &pUVM->aCpus[idCpu].vm.s.StatHaltBlock, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling halted state blocking.", "/PROF/VM/CPU%d/Halt/Block", idCpu);
rc = STAMR3RegisterF(pVM, &pUVM->aCpus[idCpu].vm.s.StatHaltTimers, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling halted state timer tasks.", "/PROF/VM/CPU%d/Halt/Timers", idCpu);
STAM_REG(pVM, &pUVM->vm.s.StatReqAllocNew, STAMTYPE_COUNTER, "/VM/Req/AllocNew", STAMUNIT_OCCURENCES, "Number of VMR3ReqAlloc returning a new packet.");
STAM_REG(pVM, &pUVM->vm.s.StatReqAllocRaces, STAMTYPE_COUNTER, "/VM/Req/AllocRaces", STAMUNIT_OCCURENCES, "Number of VMR3ReqAlloc causing races.");
STAM_REG(pVM, &pUVM->vm.s.StatReqAllocRecycled, STAMTYPE_COUNTER, "/VM/Req/AllocRecycled", STAMUNIT_OCCURENCES, "Number of VMR3ReqAlloc returning a recycled packet.");
STAM_REG(pVM, &pUVM->vm.s.StatReqFree, STAMTYPE_COUNTER, "/VM/Req/Free", STAMUNIT_OCCURENCES, "Number of VMR3ReqFree calls.");
STAM_REG(pVM, &pUVM->vm.s.StatReqFreeOverflow, STAMTYPE_COUNTER, "/VM/Req/FreeOverflow", STAMUNIT_OCCURENCES, "Number of times the request was actually freed.");
STAM_REG(pVM, &pUVM->vm.s.StatReqProcessed, STAMTYPE_COUNTER, "/VM/Req/Processed", STAMUNIT_OCCURENCES, "Number of processed requests (any queue).");
STAM_REG(pVM, &pUVM->vm.s.StatReqMoreThan1, STAMTYPE_COUNTER, "/VM/Req/MoreThan1", STAMUNIT_OCCURENCES, "Number of times there are more than one request on the queue when processing it.");
STAM_REG(pVM, &pUVM->vm.s.StatReqPushBackRaces, STAMTYPE_COUNTER, "/VM/Req/PushBackRaces", STAMUNIT_OCCURENCES, "Number of push back races.");
#ifdef VBOX_WITH_VMI
return VINF_SUCCESS;
#ifdef VBOX_WITH_VMI
return rc;
int rc2;
return VINF_SUCCESS;
return rc;
return rc;
return rc;
return VINF_SUCCESS;
static DECLCALLBACK(size_t) vmR3LogPrefixCallback(PRTLOGGER pLogger, char *pchBuf, size_t cchBuf, void *pvUser)
if (pUVCpu)
return rc;
return VINF_SUCCESS;
int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR,
return rc;
return rc;
return VERR_INTERNAL_ERROR_3;
return VINF_EM_SUSPEND;
int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR,
return rc;
return rc;
return VINF_EM_RESUME;
int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR,
return rc;
int rc;
switch (enmVMState)
case VMSTATE_RUNNING_LS:
case VMSTATE_SUSPENDED_EXT_LS:
case VMSTATE_DEBUGGING_LS:
case VMSTATE_OFF_LS:
case VMSTATE_FATAL_ERROR_LS:
case VMSTATE_POWERING_OFF_LS:
case VMSTATE_RESETTING_LS:
return rc;
return VERR_INTERNAL_ERROR_3;
*pfSuspended = true;
return VINF_EM_SUSPEND;
*pfSuspended = true;
else if (rc > 0)
return rc;
return rc;
static DECLCALLBACK(int) vmR3Save(PVM pVM, uint32_t cMsMaxDowntime, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
LogFlow(("vmR3Save: pVM=%p cMsMaxDowntime=%u pszFilename=%p:{%s} pStreamOps=%p pvStreamOpsUser=%p enmAfter=%d pfnProgress=%p pvProgressUser=%p ppSSM=%p\n",
pVM, cMsMaxDowntime, pszFilename, pszFilename, pStreamOps, pvStreamOpsUser, enmAfter, pfnProgress, pvProgressUser, ppSSM));
return rc;
&& pSSM)
rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR,
RTThreadSleep(250); /** @todo Live Migration: fix this polling wait by some smart use of multiple release event semaphores.. */
rc2 = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, vmR3LiveDoStep1Cleanup, pfSuspended);
return rc;
LogFlow(("VMR3Save: pVM=%p pszFilename=%p:{%s} fContinueAfterwards=%RTbool pfnProgress=%p pvUser=%p pfSuspended=%p\n",
*pfSuspended = false;
return rc;
VMMR3DECL(int) VMR3Teleport(PVM pVM, uint32_t cMsMaxDowntime, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
LogFlow(("VMR3Teleport: pVM=%p cMsMaxDowntime=%u pStreamOps=%p pvStreamOps=%p pfnProgress=%p pvProgressUser=%p\n",
*pfSuspended = false;
return rc;
static DECLCALLBACK(int) vmR3Load(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
LogFlow(("vmR3Load: pVM=%p pszFilename=%p:{%s} pStreamOps=%p pvStreamOpsUser=%p pfnProgress=%p pvProgressUser=%p fTeleporting=%RTbool\n",
pVM, pszFilename, pszFilename, pStreamOps, pvStreamOpsUser, pfnProgress, pvProgressUser, fTeleporting));
return rc;
rc = SSMR3Load(pVM, pszFilename, pStreamOps, pvStreamOpsUser, SSMAFTER_RESUME, pfnProgress, pvProgressUser);
return rc;
VMMR3DECL(int) VMR3LoadFromFile(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser)
pVM, pszFilename, (uintptr_t)NULL /*pStreamOps*/, (uintptr_t)NULL /*pvStreamOpsUser*/, pfnProgress, pvUser,
return rc;
LogFlow(("VMR3LoadFromStream: pVM=%p pStreamOps=%p pvStreamOpsUser=%p pfnProgress=%p pvProgressUser=%p\n",
return rc;
return rc;
return VINF_EM_OFF;
int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR,
return rc;
if (!pVM)
return VERR_INVALID_PARAMETER;
return rc;
return VINF_SUCCESS;
#ifdef VBOX_WITH_STATISTICS
#ifdef VBOX_WITH_DEBUGGER
return VINF_EM_TERMINATE;
if (idCpu != 0)
NULL);
unsigned cReqs = 0;
AssertMsg(!pReqHead, ("This isn't supposed to happen! VMR3Destroy caller has to serialize this.\n"));
if (!pReqHead)
AssertMsg(!pReqHead, ("This isn't supposed to happen! VMR3Destroy caller has to serialize this.\n"));
if (!pReqHead)
#ifdef LOG_ENABLED
if (pVMPrev)
while (pCur)
return VERR_INVALID_PARAMETER;
if (!pVMAtDtor)
return VERR_NO_MEMORY;
return VINF_SUCCESS;
while (pCur)
if (pPrev)
return VINF_SUCCESS;
return VERR_INVALID_PARAMETER;
#ifdef VBOX_STRICT
return rc;
#ifdef LOG_ENABLED
: VINF_EM_SUSPEND; /** @todo VINF_EM_SUSPEND has lower priority than VINF_EM_RESET, so fix races. Perhaps add a new code for this combined case. */
int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR,
return rc;
switch (enmState)
#ifdef VBOX_STRICT
switch (enmStateOld)
case VMSTATE_CREATING:
AssertMsgReturn(enmStateNew == VMSTATE_CREATED, ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
case VMSTATE_CREATED:
case VMSTATE_LOADING:
case VMSTATE_POWERING_ON:
case VMSTATE_RESUMING:
case VMSTATE_RUNNING:
case VMSTATE_RUNNING_LS:
case VMSTATE_RESETTING:
AssertMsgReturn(enmStateNew == VMSTATE_RUNNING, ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
case VMSTATE_RESETTING_LS:
case VMSTATE_SUSPENDING:
AssertMsgReturn(enmStateNew == VMSTATE_SUSPENDED, ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
case VMSTATE_SUSPENDING_LS:
case VMSTATE_SUSPENDED:
case VMSTATE_SUSPENDED_LS:
case VMSTATE_SUSPENDED_EXT_LS:
case VMSTATE_SAVING:
AssertMsgReturn(enmStateNew == VMSTATE_SUSPENDED, ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
case VMSTATE_DEBUGGING:
case VMSTATE_DEBUGGING_LS:
case VMSTATE_POWERING_OFF:
AssertMsgReturn(enmStateNew == VMSTATE_OFF, ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
case VMSTATE_POWERING_OFF_LS:
case VMSTATE_OFF:
AssertMsgReturn(enmStateNew == VMSTATE_DESTROYING, ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
case VMSTATE_OFF_LS:
AssertMsgReturn(enmStateNew == VMSTATE_OFF, ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
case VMSTATE_FATAL_ERROR:
AssertMsgReturn(enmStateNew == VMSTATE_POWERING_OFF, ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
case VMSTATE_FATAL_ERROR_LS:
case VMSTATE_GURU_MEDITATION:
case VMSTATE_LOAD_FAILURE:
AssertMsgReturn(enmStateNew == VMSTATE_POWERING_OFF, ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
case VMSTATE_DESTROYING:
AssertMsgReturn(enmStateNew == VMSTATE_TERMINATED, ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
case VMSTATE_TERMINATED:
AssertMsgFailedReturn(("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
LogRel(("Changing the VM state from '%s' to '%s'.\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)));
#ifdef VBOX_STRICT
for (unsigned i = 0; i < cTransitions; i++)
for (unsigned i = 0; i < cTransitions; i++)
pszWho, VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew), VMR3GetStateName(enmStateCur)));
for (unsigned i = 0; i < cTransitions; i++)
pszWho, VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew), VMR3GetStateName(enmStateCur)));
return rc;
* immediately by the VMM and not by VMEmt.cpp when it's all over.
if (!pNew)
return VERR_NO_MEMORY;
return VINF_SUCCESS;
while ( pCur
if (!pCur)
return VERR_FILE_NOT_FOUND;
if (pPrev)
return VINF_SUCCESS;
if (!pNew)
return VERR_NO_MEMORY;
return VINF_SUCCESS;
while ( pCur
if (!pCur)
return VERR_FILE_NOT_FOUND;
if (pPrev)
return VINF_SUCCESS;
static void vmR3SetErrorWorkerDoCall(PVM pVM, PVMATERROR pCur, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
AssertReleaseMsgFailed(("And we have a winner! You get to implement Ring-0 and GC VMSetErrorV! Contrats!\n"));
const char *pszMessage;
if (pErr)
return rc;
DECLCALLBACK(void) vmR3SetErrorUV(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list *pArgs)
RTLogRelPrintf("VMSetError: %s(%d) %s\nVMSetError: %N\n", pszFile, iLine, pszFunction, pszFormat, &va3);
#ifdef LOG_ENABLED
bool fCalledSomeone = false;
fCalledSomeone = true;
VMMR3DECL(int) VMR3AtRuntimeErrorRegister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser)
LogFlow(("VMR3AtRuntimeErrorRegister: pfnAtRuntimeError=%p pvUser=%p\n", pfnAtRuntimeError, pvUser));
if (!pNew)
return VERR_NO_MEMORY;
return VINF_SUCCESS;
VMMR3DECL(int) VMR3AtRuntimeErrorDeregister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser)
LogFlow(("VMR3AtRuntimeErrorDeregister: pfnAtRuntimeError=%p pvUser=%p\n", pfnAtRuntimeError, pvUser));
while ( pCur
if (!pCur)
return VERR_FILE_NOT_FOUND;
if (pPrev)
return VINF_SUCCESS;
static DECLCALLBACK(VBOXSTRICTRC) vmR3SetRuntimeErrorChangeState(PVM pVM, PVMCPU pVCpu, void *pvUser)
static int vmR3SetRuntimeErrorCommon(PVM pVM, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list *pVa)
int rc;
rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, vmR3SetRuntimeErrorChangeState, NULL);
return rc;
static int vmR3SetRuntimeErrorCommonF(PVM pVM, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
return rc;
AssertReleaseMsgFailed(("And we have a winner! You get to implement Ring-0 and GC VMSetRuntimeErrorV! Congrats!\n"));
if (pErr)
DECLCALLBACK(int) vmR3SetRuntimeError(PVM pVM, uint32_t fFlags, const char *pszErrorId, char *pszMessage)
return rc;
DECLCALLBACK(int) vmR3SetRuntimeErrorV(PVM pVM, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list *pVa)
return pUVCpu
: NIL_VMCPUID;
if (!pUVCpu)
return NIL_RTNATIVETHREAD;
if (!pUVCpu)
return NIL_RTNATIVETHREAD;
if (!pUVCpu)
return NIL_RTTHREAD;
if (!pUVCpu)
return NIL_RTTHREAD;
VMMR3DECL(int) VMR3GetCpuCoreAndPackageIdFromCpuId(PVM pVM, VMCPUID idCpu, uint32_t *pidCpuCore, uint32_t *pidCpuPackage)
return VERR_INVALID_CPU_ID;
#ifdef VBOX_WITH_MULTI_CORE
*pidCpuPackage = 0;
*pidCpuCore = 0;
return VINF_SUCCESS;
return VINF_EM_WAIT_SIPI;
return VINF_SUCCESS;