/** * Get the timestamp frequency. * * @returns Number of ticks per second. * @param pVM The cross context VM structure. */ VMMDECL(uint64_t) TMCpuTicksPerSecond(PVM pVM) { if ( pVM->tm.s.enmTSCMode == TMTSCMODE_REAL_TSC_OFFSET && g_pSUPGlobalInfoPage->u32Mode != SUPGIPMODE_INVARIANT_TSC) { #ifdef IN_RING3 uint64_t cTSCTicksPerSecond = SUPGetCpuHzFromGip(g_pSUPGlobalInfoPage); #elif defined(IN_RING0) uint64_t cTSCTicksPerSecond = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, RTMpCpuIdToSetIndex(RTMpCpuId())); #else uint64_t cTSCTicksPerSecond = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, VMMGetCpu(pVM)->iHostCpuSet); #endif if (RT_LIKELY(cTSCTicksPerSecond != ~(uint64_t)0)) return cTSCTicksPerSecond; } return pVM->tm.s.cTSCTicksPerSecond; }
/** * Calculates the number of host CPU ticks till the next virtual sync deadline. * * @note To save work, this function will not bother calculating the accurate * tick count for deadlines that are more than a second ahead. * * @returns The number of host cpu ticks to the next deadline. Max one second. * @param pVCpu The cross context virtual CPU structure of the calling EMT. * @param cNsToDeadline The number of nano seconds to the next virtual * sync deadline. */ DECLINLINE(uint64_t) tmCpuCalcTicksToDeadline(PVMCPU pVCpu, uint64_t cNsToDeadline) { AssertCompile(TMCLOCK_FREQ_VIRTUAL <= _4G); #ifdef IN_RING3 uint64_t uCpuHz = SUPGetCpuHzFromGip(g_pSUPGlobalInfoPage); #else uint64_t uCpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet); #endif if (RT_UNLIKELY(cNsToDeadline >= TMCLOCK_FREQ_VIRTUAL)) return uCpuHz; uint64_t cTicks = ASMMultU64ByU32DivByU32(uCpuHz, cNsToDeadline, TMCLOCK_FREQ_VIRTUAL); if (cTicks > 4000) cTicks -= 4000; /* fudge to account for overhead */ else cTicks >>= 1; return cTicks; }
/** * The GC entry point. * * @returns VBox status code. * @param pVM The cross context VM structure. * @param uOperation Which operation to execute (VMMRCOPERATION). * @param uArg Argument to that operation. */ VMMRCDECL(int) VMMRCEntry(PVM pVM, unsigned uOperation, unsigned uArg, ...) { /** @todo */ switch (uOperation) { /* * Init RC modules. */ case VMMRC_DO_VMMRC_INIT: { /* * Validate the svn revision (uArg) and build type (ellipsis). */ if (uArg != VMMGetSvnRev()) return VERR_VMM_RC_VERSION_MISMATCH; va_list va; va_start(va, uArg); uint32_t uBuildType = va_arg(va, uint32_t); if (uBuildType != vmmGetBuildType()) { va_end(va); return VERR_VMM_RC_VERSION_MISMATCH; } /* * Initialize the runtime. */ uint64_t u64TS = va_arg(va, uint64_t); va_end(va); int rc = RTRCInit(u64TS); Log(("VMMRCEntry: VMMRC_DO_VMMRC_INIT - uArg=%u (svn revision) u64TS=%RX64; rc=%Rrc\n", uArg, u64TS, rc)); AssertRCReturn(rc, rc); rc = PGMRegisterStringFormatTypes(); AssertRCReturn(rc, rc); rc = PGMRCDynMapInit(pVM); AssertRCReturn(rc, rc); return VINF_SUCCESS; } /* * Testcase which is used to test interrupt forwarding. * It spins for a while with interrupts enabled. */ case VMMRC_DO_TESTCASE_HYPER_INTERRUPT: { uint32_t volatile i = 0; ASMIntEnable(); while (i < _2G32) i++; ASMIntDisable(); return 0; } /* * Testcase which simply returns, this is used for * profiling of the switcher. */ case VMMRC_DO_TESTCASE_NOP: return 0; /* * Testcase executes a privileged instruction to force a world switch. (in both SVM & VMX) */ case VMMRC_DO_TESTCASE_HM_NOP: ASMRdMsr_Low(MSR_IA32_SYSENTER_CS); return 0; /* * Delay for ~100us. */ case VMMRC_DO_TESTCASE_INTERRUPT_MASKING: { uint64_t u64MaxTicks = (SUPGetCpuHzFromGip(g_pSUPGlobalInfoPage) != ~(uint64_t)0 ? SUPGetCpuHzFromGip(g_pSUPGlobalInfoPage) : _2G) / 10000; uint64_t u64StartTSC = ASMReadTSC(); uint64_t u64TicksNow; uint32_t volatile i = 0; do { /* waste some time and protect against getting stuck. */ for (uint32_t volatile j = 0; j < 1000; j++, i++) if (i > _2G32) return VERR_GENERAL_FAILURE; /* check if we're done.*/ u64TicksNow = ASMReadTSC() - u64StartTSC; } while (u64TicksNow < u64MaxTicks); return VINF_SUCCESS; } /* * Trap testcases and unknown operations. */ default: if ( uOperation >= VMMRC_DO_TESTCASE_TRAP_FIRST && uOperation < VMMRC_DO_TESTCASE_TRAP_LAST) return vmmGCTest(pVM, uOperation, uArg); return VERR_INVALID_PARAMETER; } }