TMAllCpu.cpp revision 12c79195f773855bfca3ba75211cb2d3a1568605
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync * TM - Timeout Manager, CPU Time, All Contexts.
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync * Copyright (C) 2006-2012 Oracle Corporation
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync * available from http://www.virtualbox.org. This file is free software;
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync * you can redistribute it and/or modify it under the terms of the GNU
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync * General Public License (GPL) as published by the Free Software
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync/*******************************************************************************
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync* Header Files *
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync*******************************************************************************/
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync#include <iprt/asm-amd64-x86.h> /* for SUPGetCpuHzFromGIP */
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync * Gets the raw cpu tick from current virtual time.
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsyncDECLINLINE(uint64_t) tmCpuTickGetRawVirtual(PVM pVM, bool fCheckTimers)
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync if (u64 != TMCLOCK_FREQ_VIRTUAL) /* what's the use of this test, document! */
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync u64 = ASMMultU64ByU32DivByU32(u64, pVM->tm.s.cTSCTicksPerSecond, TMCLOCK_FREQ_VIRTUAL);
14ebfaa1c57c3239ff757d0034253ff19647b276vboxsync * Resumes the CPU timestamp counter ticking.
14ebfaa1c57c3239ff757d0034253ff19647b276vboxsync * @returns VBox status code.
14ebfaa1c57c3239ff757d0034253ff19647b276vboxsync * @param pVM Pointer to the VM.
14ebfaa1c57c3239ff757d0034253ff19647b276vboxsync * @param pVCpu Pointer to the VMCPU.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @internal
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync /** @todo Test that pausing and resuming doesn't cause lag! (I.e. that we're
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync * unpaused before the virtual time and stopped after it. */
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync pVCpu->tm.s.offTSCRawSrc = ASMReadTSC() - pVCpu->tm.s.u64TSC;
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync pVCpu->tm.s.offTSCRawSrc = tmCpuTickGetRawVirtual(pVM, false /* don't check for pending timers */)
7dfb99974324af3e0dbbae9902d016927e113925vboxsync * Resumes the CPU timestamp counter ticking.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @returns VINF_SUCCESS or VERR_TM_VIRTUAL_TICKING_IPE (asserted).
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @param pVM Pointer to the VM.
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync * @param pVCpu Pointer to the VCPU.
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync /* TSC must be ticking before calling tmCpuTickGetRawVirtual()! */
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync uint32_t c = ASMAtomicIncU32(&pVM->tm.s.cTSCsTicking);
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync AssertMsgReturn(c <= pVM->cCpus, ("%u vs %u\n", c, pVM->cCpus), VERR_TM_VIRTUAL_TICKING_IPE);
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync if (c == 1)
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync /* The first VCPU to resume. */
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync uint64_t offTSCRawSrcOld = pVCpu->tm.s.offTSCRawSrc;
b41f65ee355ae1d4b24473c6d6d70c653497429avboxsync /* When resuming, use the TSC value of the last stopped VCPU to avoid the TSC going back. */
7dfb99974324af3e0dbbae9902d016927e113925vboxsync pVCpu->tm.s.offTSCRawSrc = ASMReadTSC() - pVM->tm.s.u64LastPausedTSC;
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync pVCpu->tm.s.offTSCRawSrc = tmCpuTickGetRawVirtual(pVM, false /* don't check for pending timers */)
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync /* Calculate the offset for other VCPUs to use. */
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync pVM->tm.s.offTSCPause = pVCpu->tm.s.offTSCRawSrc - offTSCRawSrcOld;
7dfb99974324af3e0dbbae9902d016927e113925vboxsync /* All other VCPUs (if any). */
7dfb99974324af3e0dbbae9902d016927e113925vboxsync * Pauses the CPU timestamp counter ticking.
7dfb99974324af3e0dbbae9902d016927e113925vboxsync * @returns VBox status code.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * @param pVCpu Pointer to the VMCPU.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * @internal
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync * Pauses the CPU timestamp counter ticking.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * @returns VBox status code.
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync * @param pVM Pointer to the VM.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * @param pVCpu Pointer to the VMCPU.
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync * @internal
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync uint32_t c = ASMAtomicDecU32(&pVM->tm.s.cTSCsTicking);
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync AssertMsgReturn(c < pVM->cCpus, ("%u vs %u\n", c, pVM->cCpus), VERR_TM_VIRTUAL_TICKING_IPE);
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync if (c == 0)
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync /* When the last TSC stops, remember the value. */
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync * Record why we refused to use offsetted TSC.
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync * Used by TMCpuTickCanUseRealTSC and TMCpuTickGetDeadlineAndTscOffset.
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync * @param pVM Pointer to the VM.
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync * @param pVCpu The current CPU.
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsyncDECLINLINE(void) tmCpuTickRecordOffsettedTscRefusal(PVM pVM, PVMCPU pVCpu)
5f076b675789f7dd23040096fa3fdc636bd4ea10vboxsync /* Sample the reason for refusing. */
bool fParavirtTsc = false;
if (poffRealTSC)
else if (poffRealTSC)
*poffRealTSC = 0;
#ifdef VBOX_WITH_STATISTICS
return cTicks;
VMM_INT_DECL(uint64_t) TMCpuTickGetDeadlineAndTscOffset(PVMCPU pVCpu, bool *pfOffsettedTsc, bool *pfParavirtTsc,
*pfOffsettedTsc = true;
*poffRealTSC = 0;
#ifdef VBOX_WITH_STATISTICS
*pfOffsettedTsc = false;
*poffRealTSC = 0;
return cTicksToDeadline;
return u64;
if (fTSCTicking)
return VINF_SUCCESS;
return VINF_SUCCESS;
return cTSCTicksPerSecond;