/** * Sets the new recompile supervisor code flag. * * @returns COM status code * @param aEnable new recompile supervisor code flag */ STDMETHODIMP MachineDebugger::COMSETTER(RecompileSupervisor)(BOOL aEnable) { LogFlowThisFunc(("enable=%d\n", aEnable)); AutoCaller autoCaller(this); HRESULT hrc = autoCaller.rc(); if (SUCCEEDED(hrc)) { AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); if (queueSettings()) mRecompileSupervisorQueued = aEnable; // queue the request else { Console::SafeVMPtr ptrVM(mParent); hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) { int vrc = EMR3SetExecutionPolicy(ptrVM.raw(), EMEXECPOLICY_RECOMPILE_RING0, RT_BOOL(aEnable)); if (RT_FAILURE(vrc)) hrc = setError(VBOX_E_VM_ERROR, tr("EMR3SetExecutionPolicy failed with %Rrc"), vrc); } } } return hrc; }
STDMETHODIMP MachineDebugger::DumpGuestCore(IN_BSTR a_bstrFilename, IN_BSTR a_bstrCompression) { CheckComArgStrNotEmptyOrNull(a_bstrFilename); Utf8Str strFilename(a_bstrFilename); if (a_bstrCompression && *a_bstrCompression) return setError(E_INVALIDARG, tr("The compression parameter must be empty")); AutoCaller autoCaller(this); HRESULT hrc = autoCaller.rc(); if (SUCCEEDED(hrc)) { AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtr ptrVM(mParent); hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) { int vrc = DBGFR3CoreWrite(ptrVM, strFilename.c_str(), false /*fReplaceFile*/); if (RT_SUCCESS(vrc)) hrc = S_OK; else hrc = setError(E_FAIL, tr("DBGFR3CoreWrite failed with %Rrc"), vrc); } } return hrc; }
/** * Sets the new code scanner enabled flag. * * @returns COM status code * @param aEnable new code scanner enabled flag */ HRESULT MachineDebugger::setCSAMEnabled(BOOL aCSAMEnabled) { LogFlowThisFunc(("enable=%d\n", aCSAMEnabled)); #ifdef VBOX_WITH_RAW_MODE AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); if (i_queueSettings()) { // queue the request mCsamEnabledQueued = aCSAMEnabled; return S_OK; } Console::SafeVMPtr ptrVM(mParent); if (FAILED(ptrVM.rc())) return ptrVM.rc(); int vrc = CSAMR3SetScanningEnabled(ptrVM.rawUVM(), aCSAMEnabled != FALSE); if (RT_FAILURE(vrc)) return setError(VBOX_E_VM_ERROR, tr("CSAMR3SetScanningEnabled returned %Rrc"), vrc); #else /* !VBOX_WITH_RAW_MODE */ if (aCSAMEnabled) return setError(VBOX_E_VM_ERROR, tr("CASM not present"), VERR_NOT_SUPPORTED); #endif /* !VBOX_WITH_RAW_MODE */ return S_OK; }
HRESULT MachineDebugger::getOSVersion(com::Utf8Str &aOSVersion) { LogFlowThisFunc(("\n")); AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtr ptrVM(mParent); HRESULT hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) { /* * Do the job and try convert the name. */ char szVersion[256]; int vrc = DBGFR3OSQueryNameAndVersion(ptrVM.rawUVM(), NULL, 0, szVersion, sizeof(szVersion)); if (RT_SUCCESS(vrc)) { try { Bstr bstrVersion(szVersion); aOSVersion = Utf8Str(bstrVersion); } catch (std::bad_alloc) { hrc = E_OUTOFMEMORY; } } else hrc = setError(VBOX_E_VM_ERROR, tr("DBGFR3OSQueryNameAndVersion failed with %Rrc"), vrc); } return hrc; }
/** * Enables or disables logging. * * @returns COM status code * @param aLogEnabled The new code log state. */ HRESULT MachineDebugger::setLogEnabled(BOOL aLogEnabled) { LogFlowThisFunc(("aLogEnabled=%d\n", aLogEnabled)); AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); if (i_queueSettings()) { // queue the request mLogEnabledQueued = aLogEnabled; return S_OK; } Console::SafeVMPtr ptrVM(mParent); if (FAILED(ptrVM.rc())) return ptrVM.rc(); #ifdef LOG_ENABLED int vrc = DBGFR3LogModifyFlags(ptrVM.rawUVM(), aLogEnabled ? "enabled" : "disabled"); if (RT_FAILURE(vrc)) { /** @todo handle error code. */ } #endif return S_OK; }
/** * Returns the current virtual time rate. * * @returns COM status code. * @param aPct Where to store the rate. */ STDMETHODIMP MachineDebugger::COMSETTER(VirtualTimeRate)(ULONG a_uPct) { if (a_uPct < 2 || a_uPct > 20000) return setError(E_INVALIDARG, tr("%u is out of range [2..20000]"), a_uPct); AutoCaller autoCaller(this); HRESULT hrc = autoCaller.rc(); if (SUCCEEDED(hrc)) { AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); if (queueSettings()) mVirtualTimeRateQueued = a_uPct; else { Console::SafeVMPtr ptrVM(mParent); hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) { int vrc = TMR3SetWarpDrive(ptrVM.raw(), a_uPct); if (RT_FAILURE(vrc)) hrc = setError(VBOX_E_VM_ERROR, tr("TMR3SetWarpDrive(, %u) failed with rc=%Rrc"), a_uPct, vrc); } } } return hrc; }
/** * Returns the current virtual time rate. * * @returns COM status code. * @param a_puPct Where to store the rate. */ HRESULT MachineDebugger::getVirtualTimeRate(ULONG *aVirtualTimeRate) { AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtr ptrVM(mParent); HRESULT hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) *aVirtualTimeRate = TMR3GetWarpDrive(ptrVM.rawUVM()); return hrc; }
/** * Get the VM uptime in milliseconds. * * @returns COM status code * @param aUptime Where to store the uptime. */ HRESULT MachineDebugger::getUptime(LONG64 *aUptime) { AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtr ptrVM(mParent); HRESULT hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) *aUptime = (int64_t)TMR3TimeVirtGetMilli(ptrVM.rawUVM()); return hrc; }
/** * Sets the singlestepping flag. * * @returns COM status code * @param a_fEnable The new state. */ HRESULT MachineDebugger::setSingleStep(BOOL aSingleStep) { AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtr ptrVM(mParent); HRESULT hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) { NOREF(aSingleStep); /** @todo */ ReturnComNotImplemented(); } return hrc; }
/** * Returns the current unrestricted execution setting. * * @returns COM status code * @param aEnabled address of result variable */ HRESULT MachineDebugger::getHWVirtExUXEnabled(BOOL *aHWVirtExUXEnabled) { AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtrQuiet ptrVM(mParent); if (ptrVM.isOk()) *aHWVirtExUXEnabled = HMR3IsUXActive(ptrVM.rawUVM()); else *aHWVirtExUXEnabled = false; return S_OK; }
/** * Returns the current patch manager enabled flag. * * @returns COM status code * @param aEnabled address of result variable */ HRESULT MachineDebugger::getPATMEnabled(BOOL *aPATMEnabled) { #ifdef VBOX_WITH_RAW_MODE AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtrQuiet ptrVM(mParent); if (ptrVM.isOk()) *aPATMEnabled = PATMR3IsEnabled(ptrVM.rawUVM()); else #endif *aPATMEnabled = false; return S_OK; }
HRESULT Guest::internalGetStatistics(ULONG *aCpuUser, ULONG *aCpuKernel, ULONG *aCpuIdle, ULONG *aMemTotal, ULONG *aMemFree, ULONG *aMemBalloon, ULONG *aMemShared, ULONG *aMemCache, ULONG *aPageTotal, ULONG *aMemAllocTotal, ULONG *aMemFreeTotal, ULONG *aMemBalloonTotal, ULONG *aMemSharedTotal) { AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); *aCpuUser = mCurrentGuestStat[GUESTSTATTYPE_CPUUSER]; *aCpuKernel = mCurrentGuestStat[GUESTSTATTYPE_CPUKERNEL]; *aCpuIdle = mCurrentGuestStat[GUESTSTATTYPE_CPUIDLE]; *aMemTotal = mCurrentGuestStat[GUESTSTATTYPE_MEMTOTAL] * (_4K/_1K); /* page (4K) -> 1KB units */ *aMemFree = mCurrentGuestStat[GUESTSTATTYPE_MEMFREE] * (_4K/_1K); /* page (4K) -> 1KB units */ *aMemBalloon = mCurrentGuestStat[GUESTSTATTYPE_MEMBALLOON] * (_4K/_1K); /* page (4K) -> 1KB units */ *aMemCache = mCurrentGuestStat[GUESTSTATTYPE_MEMCACHE] * (_4K/_1K); /* page (4K) -> 1KB units */ *aPageTotal = mCurrentGuestStat[GUESTSTATTYPE_PAGETOTAL] * (_4K/_1K); /* page (4K) -> 1KB units */ /* Play safe or smth? */ *aMemAllocTotal = 0; *aMemFreeTotal = 0; *aMemBalloonTotal = 0; *aMemSharedTotal = 0; *aMemShared = 0; /* MUST release all locks before calling any PGM statistics queries, * as they are executed by EMT and that might deadlock us by VMM device * activity which waits for the Guest object lock. */ alock.release(); Console::SafeVMPtr ptrVM(mParent); if (!ptrVM.isOk()) return E_FAIL; uint64_t cbFreeTotal, cbAllocTotal, cbBalloonedTotal, cbSharedTotal; int rc = PGMR3QueryGlobalMemoryStats(ptrVM.rawUVM(), &cbAllocTotal, &cbFreeTotal, &cbBalloonedTotal, &cbSharedTotal); AssertRCReturn(rc, E_FAIL); *aMemAllocTotal = (ULONG)(cbAllocTotal / _1K); /* bytes -> KB */ *aMemFreeTotal = (ULONG)(cbFreeTotal / _1K); *aMemBalloonTotal = (ULONG)(cbBalloonedTotal / _1K); *aMemSharedTotal = (ULONG)(cbSharedTotal / _1K); /* Query the missing per-VM memory statistics. */ uint64_t cbTotalMemIgn, cbPrivateMemIgn, cbSharedMem, cbZeroMemIgn; rc = PGMR3QueryMemoryStats(ptrVM.rawUVM(), &cbTotalMemIgn, &cbPrivateMemIgn, &cbSharedMem, &cbZeroMemIgn); AssertRCReturn(rc, E_FAIL); *aMemShared = (ULONG)(cbSharedMem / _1K); return S_OK; }
HRESULT MachineDebugger::logStringProps(PRTLOGGER pLogger, PFNLOGGETSTR pfnLogGetStr, const char *pszLogGetStr, BSTR *a_pbstrSettings) { /* Make sure the VM is powered up. */ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtr ptrVM(mParent); HRESULT hrc = ptrVM.rc(); if (FAILED(hrc)) return hrc; /* Make sure we've got a logger. */ if (!pLogger) { Bstr bstrEmpty; bstrEmpty.cloneTo(a_pbstrSettings); return S_OK; } /* Do the job. */ size_t cbBuf = _1K; for (;;) { char *pszBuf = (char *)RTMemTmpAlloc(cbBuf); AssertReturn(pszBuf, E_OUTOFMEMORY); int rc = pfnLogGetStr(pLogger, pszBuf, cbBuf); if (RT_SUCCESS(rc)) { try { Bstr bstrRet(pszBuf); bstrRet.detachTo(a_pbstrSettings); hrc = S_OK; } catch (std::bad_alloc) { hrc = E_OUTOFMEMORY; } RTMemTmpFree(pszBuf); return hrc; } RTMemTmpFree(pszBuf); AssertReturn(rc == VERR_BUFFER_OVERFLOW, setError(VBOX_E_IPRT_ERROR, tr("%s returned %Rrc"), pszLogGetStr, rc)); /* try again with a bigger buffer. */ cbBuf *= 2; AssertReturn(cbBuf <= _256K, setError(E_FAIL, tr("%s returns too much data"), pszLogGetStr)); } }
/** * Sets the singlestepping flag. * * @returns COM status code * @param a_fEnable The new state. */ STDMETHODIMP MachineDebugger::COMSETTER(SingleStep)(BOOL a_fEnable) { AutoCaller autoCaller(this); HRESULT hrc = autoCaller.rc(); if (SUCCEEDED(hrc)) { AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtr ptrVM(mParent); hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) { /** @todo */ ReturnComNotImplemented(); } } return hrc; }
/** * Returns the current PAE flag. * * @returns COM status code * @param aEnabled address of result variable */ HRESULT MachineDebugger::getPAEEnabled(BOOL *aPAEEnabled) { AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtrQuiet ptrVM(mParent); if (ptrVM.isOk()) { uint32_t cr4; int rc = DBGFR3RegCpuQueryU32(ptrVM.rawUVM(), 0 /*idCpu*/, DBGFREG_CR4, &cr4); AssertRC(rc); *aPAEEnabled = RT_BOOL(cr4 & X86_CR4_PAE); } else *aPAEEnabled = false; return S_OK; }
/** * Hack for getting the user mode VM handle (UVM). * * This is only temporary (promise) while prototyping the debugger. * * @returns COM status code * @param aVM Where to store the vm handle. Since there is no * uintptr_t in COM, we're using the max integer. * (No, ULONG is not pointer sized!) * @remarks The returned handle must be passed to VMR3ReleaseUVM()! * @remarks Prior to 4.3 this returned PVM. */ HRESULT MachineDebugger::getVM(LONG64 *aVM) { AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtr ptrVM(mParent); HRESULT hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) { VMR3RetainUVM(ptrVM.rawUVM()); *aVM = (intptr_t)ptrVM.rawUVM(); } /* * Note! ptrVM protection provided by SafeVMPtr is no long effective * after we return from this method. */ return hrc; }
/** * Returns the current virtual time rate. * * @returns COM status code. * @param a_puPct Where to store the rate. */ STDMETHODIMP MachineDebugger::COMGETTER(VirtualTimeRate)(ULONG *a_puPct) { CheckComArgOutPointerValid(a_puPct); AutoCaller autoCaller(this); HRESULT hrc = autoCaller.rc(); if (SUCCEEDED(hrc)) { AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtr ptrVM(mParent); hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) *a_puPct = TMGetWarpDrive(ptrVM.raw()); } return hrc; }
HRESULT MachineDebugger::i_logStringProps(PRTLOGGER pLogger, PFNLOGGETSTR pfnLogGetStr, const char *pszLogGetStr, Utf8Str *pstrSettings) { /* Make sure the VM is powered up. */ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtr ptrVM(mParent); HRESULT hrc = ptrVM.rc(); if (FAILED(hrc)) return hrc; /* Make sure we've got a logger. */ if (!pLogger) { *pstrSettings = ""; return S_OK; } /* Do the job. */ size_t cbBuf = _1K; for (;;) { char *pszBuf = (char *)RTMemTmpAlloc(cbBuf); AssertReturn(pszBuf, E_OUTOFMEMORY); int vrc = pstrSettings->reserveNoThrow(cbBuf); if (RT_SUCCESS(vrc)) { vrc = pfnLogGetStr(pLogger, pstrSettings->mutableRaw(), cbBuf); if (RT_SUCCESS(vrc)) { pstrSettings->jolt(); return S_OK; } *pstrSettings = ""; AssertReturn(vrc == VERR_BUFFER_OVERFLOW, setError(VBOX_E_IPRT_ERROR, tr("%s returned %Rrc"), pszLogGetStr, vrc)); } else return E_OUTOFMEMORY; /* try again with a bigger buffer. */ cbBuf *= 2; AssertReturn(cbBuf <= _256K, setError(E_FAIL, tr("%s returns too much data"), pszLogGetStr)); } }
HRESULT MachineDebugger::dumpGuestCore(const com::Utf8Str &aFilename, const com::Utf8Str &aCompression) { if (aCompression.length()) return setError(E_INVALIDARG, tr("The compression parameter must be empty")); AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtr ptrVM(mParent); HRESULT hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) { int vrc = DBGFR3CoreWrite(ptrVM.rawUVM(), aFilename.c_str(), false /*fReplaceFile*/); if (RT_SUCCESS(vrc)) hrc = S_OK; else hrc = setError(E_FAIL, tr("DBGFR3CoreWrite failed with %Rrc"), vrc); } return hrc; }
/** * Returns the current singlestepping flag. * * @returns COM status code * @param a_fEnabled Where to store the result. */ STDMETHODIMP MachineDebugger::COMGETTER(SingleStep)(BOOL *a_fEnabled) { CheckComArgOutPointerValid(a_fEnabled); AutoCaller autoCaller(this); HRESULT hrc = autoCaller.rc(); if (SUCCEEDED(hrc)) { AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtr ptrVM(mParent); hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) { /** @todo */ ReturnComNotImplemented(); } } return hrc; }
/** * Hack for getting the VM handle. * * This is only temporary (promise) while prototyping the debugger. * * @returns COM status code * @param a_u64Vm Where to store the vm handle. Since there is no * uintptr_t in COM, we're using the max integer. * (No, ULONG is not pointer sized!) */ STDMETHODIMP MachineDebugger::COMGETTER(VM)(LONG64 *a_u64Vm) { CheckComArgOutPointerValid(a_u64Vm); AutoCaller autoCaller(this); HRESULT hrc = autoCaller.rc(); if (SUCCEEDED(hrc)) { AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtr ptrVM(mParent); hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) *a_u64Vm = (intptr_t)ptrVM.raw(); /* * Note! pVM protection provided by SafeVMPtr is no long effective * after we return from this method. */ } return hrc; }
/** * Internal worker for getting an EM executable policy setting. * * @returns COM status code. * @param enmPolicy Which EM policy. * @param pfEnforced Where to return the policy setting. */ HRESULT MachineDebugger::i_getEmExecPolicyProperty(EMEXECPOLICY enmPolicy, BOOL *pfEnforced) { CheckComArgOutPointerValid(pfEnforced); AutoCaller autoCaller(this); HRESULT hrc = autoCaller.rc(); if (SUCCEEDED(hrc)) { AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); if (i_queueSettings()) *pfEnforced = maiQueuedEmExecPolicyParams[enmPolicy] == 1; else { bool fEnforced = false; Console::SafeVMPtrQuiet ptrVM(mParent); hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) EMR3QueryExecutionPolicy(ptrVM.rawUVM(), enmPolicy, &fEnforced); *pfEnforced = fEnforced; } } return hrc; }
/** * Internal worker for setting an EM executable policy. * * @returns COM status code. * @param enmPolicy Which policy to change. * @param fEnforce Whether to enforce the policy or not. */ HRESULT MachineDebugger::i_setEmExecPolicyProperty(EMEXECPOLICY enmPolicy, BOOL fEnforce) { AutoCaller autoCaller(this); HRESULT hrc = autoCaller.rc(); if (SUCCEEDED(hrc)) { AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); if (i_queueSettings()) maiQueuedEmExecPolicyParams[enmPolicy] = fEnforce ? 1 : 0; else { Console::SafeVMPtrQuiet ptrVM(mParent); hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) { int vrc = EMR3SetExecutionPolicy(ptrVM.rawUVM(), enmPolicy, fEnforce != FALSE); if (RT_FAILURE(vrc)) hrc = setError(VBOX_E_VM_ERROR, tr("EMR3SetExecutionPolicy failed with %Rrc"), vrc); } } } return hrc; }
STDMETHODIMP MachineDebugger::COMGETTER(OSVersion)(BSTR *a_pbstrVersion) { LogFlowThisFunc(("\n")); CheckComArgNotNull(a_pbstrVersion); AutoCaller autoCaller(this); HRESULT hrc = autoCaller.rc(); if (SUCCEEDED(hrc)) { AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtr ptrVM(mParent); hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) { /* * Do the job and try convert the name. */ char szVersion[256]; int vrc = DBGFR3OSQueryNameAndVersion(ptrVM.raw(), NULL, 0, szVersion, sizeof(szVersion)); if (RT_SUCCESS(vrc)) { try { Bstr bstrVersion(szVersion); bstrVersion.detachTo(a_pbstrVersion); } catch (std::bad_alloc) { hrc = E_OUTOFMEMORY; } } else hrc = setError(VBOX_E_VM_ERROR, tr("DBGFR3OSQueryNameAndVersion failed with %Rrc"), vrc); } } return hrc; }
/** * Returns the current virtual time rate. * * @returns COM status code. * @param aPct Where to store the rate. */ HRESULT MachineDebugger::setVirtualTimeRate(ULONG aVirtualTimeRate) { HRESULT hrc = S_OK; if (aVirtualTimeRate < 2 || aVirtualTimeRate > 20000) return setError(E_INVALIDARG, tr("%u is out of range [2..20000]"), aVirtualTimeRate); AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); if (i_queueSettings()) mVirtualTimeRateQueued = aVirtualTimeRate; else { Console::SafeVMPtr ptrVM(mParent); hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) { int vrc = TMR3SetWarpDrive(ptrVM.rawUVM(), aVirtualTimeRate); if (RT_FAILURE(vrc)) hrc = setError(VBOX_E_VM_ERROR, tr("TMR3SetWarpDrive(, %u) failed with rc=%Rrc"), aVirtualTimeRate, vrc); } } return hrc; }
Console::teleporterSrcThreadWrapper(RTTHREAD hThread, void *pvUser) { TeleporterStateSrc *pState = (TeleporterStateSrc *)pvUser; /* * Console::teleporterSrc does the work, we just grab onto the VM handle * and do the cleanups afterwards. */ SafeVMPtr ptrVM(pState->mptrConsole); HRESULT hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) hrc = pState->mptrConsole->teleporterSrc(pState); /* Close the connection ASAP on so that the other side can complete. */ if (pState->mhSocket != NIL_RTSOCKET) { RTTcpClientClose(pState->mhSocket); pState->mhSocket = NIL_RTSOCKET; } /* Aaarg! setMachineState trashes error info on Windows, so we have to complete things here on failure instead of right before cleanup. */ if (FAILED(hrc)) pState->mptrProgress->notifyComplete(hrc); /* We can no longer be canceled (success), or it doesn't matter any longer (failure). */ pState->mptrProgress->setCancelCallback(NULL, NULL); /* * Write lock the console before resetting mptrCancelableProgress and * fixing the state. */ AutoWriteLock autoLock(pState->mptrConsole COMMA_LOCKVAL_SRC_POS); pState->mptrConsole->mptrCancelableProgress.setNull(); VMSTATE const enmVMState = VMR3GetStateU(pState->mpUVM); MachineState_T const enmMachineState = pState->mptrConsole->mMachineState; if (SUCCEEDED(hrc)) { /* * Automatically shut down the VM on success. * * Note! We have to release the VM caller object or we'll deadlock in * powerDown. */ AssertLogRelMsg(enmVMState == VMSTATE_SUSPENDED, ("%s\n", VMR3GetStateName(enmVMState))); AssertLogRelMsg(enmMachineState == MachineState_TeleportingPausedVM, ("%s\n", Global::stringifyMachineState(enmMachineState))); ptrVM.release(); pState->mptrConsole->mVMIsAlreadyPoweringOff = true; /* (Make sure we stick in the TeleportingPausedVM state.) */ hrc = pState->mptrConsole->powerDown(); pState->mptrConsole->mVMIsAlreadyPoweringOff = false; pState->mptrProgress->notifyComplete(hrc); } else { /* * Work the state machinery on failure. * * If the state is no longer 'Teleporting*', some other operation has * canceled us and there is nothing we need to do here. In all other * cases, we've failed one way or another. */ if ( enmMachineState == MachineState_Teleporting || enmMachineState == MachineState_TeleportingPausedVM ) { if (pState->mfUnlockedMedia) { ErrorInfoKeeper Oak; HRESULT hrc2 = pState->mptrConsole->mControl->LockMedia(); if (FAILED(hrc2)) { uint64_t StartMS = RTTimeMilliTS(); do { RTThreadSleep(2); hrc2 = pState->mptrConsole->mControl->LockMedia(); } while ( FAILED(hrc2) && RTTimeMilliTS() - StartMS < 2000); } if (SUCCEEDED(hrc2)) pState->mfUnlockedMedia = true; else LogRel(("FATAL ERROR: Failed to re-take the media locks. hrc2=%Rhrc\n", hrc2)); } switch (enmVMState) { case VMSTATE_RUNNING: case VMSTATE_RUNNING_LS: case VMSTATE_DEBUGGING: case VMSTATE_DEBUGGING_LS: case VMSTATE_POWERING_OFF: case VMSTATE_POWERING_OFF_LS: case VMSTATE_RESETTING: case VMSTATE_RESETTING_LS: Assert(!pState->mfSuspendedByUs); Assert(!pState->mfUnlockedMedia); pState->mptrConsole->setMachineState(MachineState_Running); break; case VMSTATE_GURU_MEDITATION: case VMSTATE_GURU_MEDITATION_LS: pState->mptrConsole->setMachineState(MachineState_Stuck); break; case VMSTATE_FATAL_ERROR: case VMSTATE_FATAL_ERROR_LS: pState->mptrConsole->setMachineState(MachineState_Paused); break; default: AssertMsgFailed(("%s\n", VMR3GetStateName(enmVMState))); case VMSTATE_SUSPENDED: case VMSTATE_SUSPENDED_LS: case VMSTATE_SUSPENDING: case VMSTATE_SUSPENDING_LS: case VMSTATE_SUSPENDING_EXT_LS: if (!pState->mfUnlockedMedia) { pState->mptrConsole->setMachineState(MachineState_Paused); if (pState->mfSuspendedByUs) { autoLock.release(); int rc = VMR3Resume(VMR3GetVM(pState->mpUVM)); AssertLogRelMsgRC(rc, ("VMR3Resume -> %Rrc\n", rc)); autoLock.acquire(); } } else { /* Faking a guru meditation is the best I can think of doing here... */ pState->mptrConsole->setMachineState(MachineState_Stuck); } break; } } } autoLock.release(); /* * Cleanup. */ Assert(pState->mhSocket == NIL_RTSOCKET); delete pState; return VINF_SUCCESS; /* ignored */ }
void Guest::i_updateStats(uint64_t iTick) { uint64_t cbFreeTotal = 0; uint64_t cbAllocTotal = 0; uint64_t cbBalloonedTotal = 0; uint64_t cbSharedTotal = 0; uint64_t cbSharedMem = 0; ULONG uNetStatRx = 0; ULONG uNetStatTx = 0; ULONG aGuestStats[GUESTSTATTYPE_MAX]; RT_ZERO(aGuestStats); AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); ULONG validStats = mVmValidStats; /* Check if we have anything to report */ if (validStats) { mVmValidStats = pm::VMSTATMASK_NONE; memcpy(aGuestStats, mCurrentGuestStat, sizeof(aGuestStats)); } alock.release(); /* * Calling SessionMachine may take time as the object resides in VBoxSVC * process. This is why we took a snapshot of currently collected stats * and released the lock. */ Console::SafeVMPtrQuiet ptrVM(mParent); if (ptrVM.isOk()) { int rc; /* * There is no point in collecting VM shared memory if other memory * statistics are not available yet. Or is there? */ if (validStats) { /* Query the missing per-VM memory statistics. */ uint64_t cbTotalMemIgn, cbPrivateMemIgn, cbZeroMemIgn; rc = PGMR3QueryMemoryStats(ptrVM.rawUVM(), &cbTotalMemIgn, &cbPrivateMemIgn, &cbSharedMem, &cbZeroMemIgn); if (rc == VINF_SUCCESS) validStats |= pm::VMSTATMASK_GUEST_MEMSHARED; } if (mCollectVMMStats) { rc = PGMR3QueryGlobalMemoryStats(ptrVM.rawUVM(), &cbAllocTotal, &cbFreeTotal, &cbBalloonedTotal, &cbSharedTotal); AssertRC(rc); if (rc == VINF_SUCCESS) validStats |= pm::VMSTATMASK_VMM_ALLOC | pm::VMSTATMASK_VMM_FREE | pm::VMSTATMASK_VMM_BALOON | pm::VMSTATMASK_VMM_SHARED; } uint64_t uRxPrev = mNetStatRx; uint64_t uTxPrev = mNetStatTx; mNetStatRx = mNetStatTx = 0; rc = STAMR3Enum(ptrVM.rawUVM(), "/Public/Net/*/Bytes*", i_staticEnumStatsCallback, this); AssertRC(rc); uint64_t uTsNow = RTTimeNanoTS(); uint64_t cNsPassed = uTsNow - mNetStatLastTs; if (cNsPassed >= 1000) { mNetStatLastTs = uTsNow; uNetStatRx = (ULONG)((mNetStatRx - uRxPrev) * 1000000 / (cNsPassed / 1000)); /* in bytes per second */ uNetStatTx = (ULONG)((mNetStatTx - uTxPrev) * 1000000 / (cNsPassed / 1000)); /* in bytes per second */ validStats |= pm::VMSTATMASK_NET_RX | pm::VMSTATMASK_NET_TX; LogFlowThisFunc(("Net Rx=%llu Tx=%llu Ts=%llu Delta=%llu\n", mNetStatRx, mNetStatTx, uTsNow, cNsPassed)); } else { /* Can happen on resume or if we're using a non-monotonic clock source for the timer and the time is adjusted. */ mNetStatRx = uRxPrev; mNetStatTx = uTxPrev; LogThisFunc(("Net Ts=%llu cNsPassed=%llu - too small interval\n", uTsNow, cNsPassed)); } } mParent->i_reportVmStatistics(validStats, aGuestStats[GUESTSTATTYPE_CPUUSER], aGuestStats[GUESTSTATTYPE_CPUKERNEL], aGuestStats[GUESTSTATTYPE_CPUIDLE], /* Convert the units for RAM usage stats: page (4K) -> 1KB units */ mCurrentGuestStat[GUESTSTATTYPE_MEMTOTAL] * (_4K/_1K), mCurrentGuestStat[GUESTSTATTYPE_MEMFREE] * (_4K/_1K), mCurrentGuestStat[GUESTSTATTYPE_MEMBALLOON] * (_4K/_1K), (ULONG)(cbSharedMem / _1K), /* bytes -> KB */ mCurrentGuestStat[GUESTSTATTYPE_MEMCACHE] * (_4K/_1K), mCurrentGuestStat[GUESTSTATTYPE_PAGETOTAL] * (_4K/_1K), (ULONG)(cbAllocTotal / _1K), /* bytes -> KB */ (ULONG)(cbFreeTotal / _1K), (ULONG)(cbBalloonedTotal / _1K), (ULONG)(cbSharedTotal / _1K), uNetStatRx, uNetStatTx); }