SUPLibAll.cpp revision 44343529c189705249ab88c40c202a2c581d82b5
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/* $Id$ */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/** @file
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * VirtualBox Support Library - All Contexts Code.
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Copyright (C) 2006-2014 Oracle Corporation
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * available from http://www.virtualbox.org. This file is free software;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * you can redistribute it and/or modify it under the terms of the GNU
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * General Public License (GPL) as published by the Free Software
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * The contents of this file may alternatively be used under the terms
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * of the Common Development and Distribution License Version 1.0
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * VirtualBox OSE distribution, in which case the provisions of the
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * CDDL are applicable instead of those of the GPL.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * You may elect to license modified versions of this file under the
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync * terms and conditions of either the GPL or the CDDL or both.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/*******************************************************************************
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync* Header Files *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync*******************************************************************************/
c4b821bf03ae7641a0791e3fd161247e66433b68vboxsync#include <VBox/sup.h>
c4b821bf03ae7641a0791e3fd161247e66433b68vboxsync#ifdef IN_RING0
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync# include <iprt/mp.h>
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync#endif
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync# include <iprt/asm-amd64-x86.h>
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync#endif
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync/**
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync * The slow case for SUPReadTsc where we need to apply deltas.
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync *
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * Must only be called when deltas are applicable, so please do not call it
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * directly.
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync *
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * @returns TSC with delta applied.
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync *
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync * @remarks May be called with interrupts disabled in ring-0! This is why the
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * ring-0 code doesn't attempt to figure the delta.
cd059a6642b11828bd0ad8b3108f5f7f611d144fvboxsync *
cd059a6642b11828bd0ad8b3108f5f7f611d144fvboxsync * @internal
cd059a6642b11828bd0ad8b3108f5f7f611d144fvboxsync */
cd059a6642b11828bd0ad8b3108f5f7f611d144fvboxsyncSUPDECL(uint64_t) SUPReadTscWithDelta(void)
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync{
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync Assert(GIP_ARE_TSC_DELTAS_APPLICABLE(pGip));
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync /** @todo Check out the rdtscp optimization, ASMGetApicId is very expensive. */
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync# ifdef IN_RING3
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync /*
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync * Read the TSC and delta.
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync */
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync uint32_t cTries = 0;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync for (;;)
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync {
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync uint8_t idApic = ASMGetApicId();
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync uint64_t uTsc = ASMReadTSC();
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync int64_t iTscDelta = pGip->aCPUs[pGip->aiCpuFromApicId[idApic]].i64TSCDelta;
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync if (RT_LIKELY( idApic == ASMGetApicId()
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync || cTries >= 10))
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync {
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync /*
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync * If the delta is valid, apply it.
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync */
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync if (RT_LIKELY(iTscDelta != INT64_MAX))
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync return uTsc - iTscDelta;
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync /*
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync * The delta needs calculating, call supdrv to get the TSC.
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync */
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync int rc = SUPR3ReadTsc(&uTsc, NULL);
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync if (RT_SUCCESS(rc))
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync return uTsc;
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync AssertMsgFailed(("SUPR3ReadTsc -> %Rrc\n", rc));
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync /* That didn't work, just return something half useful... */
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync return ASMReadTSC();
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync }
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync cTries++;
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync }
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync# else
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync /*
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * Read the TSC and delta.
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync */
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync RTCCUINTREG uFlags = ASMIntDisableFlags();
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync# ifdef IN_RING0
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync int iCpuSet = RTMpCpuIdToSetIndex(RTMpCpuId());
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync uint16_t iGipCpu = (unsigned)iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync ? pGip->aiCpuFromCpuSetIdx[iCpuSet] : UINT16_MAX;
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync# else
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync uint8_t idApic = ASMGetApicId(); /** @todo this could probably be eliminated in RC if we really wanted to... */
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync uint16_t iGipCpu = (unsigned)idApic < RT_ELEMENTS(pGip->aiCpuFromApicId) /* for the future */
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync ? pGip->aiCpuFromApicId[idApic] : UINT16_MAX;
c740281e4f5e61397e892447aeef2a7bdbbaaf8dvboxsync# endif
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync int64_t iTscDelta = (unsigned)iGipCpu < pGip->cCpus ? pGip->aCPUs[iGipCpu].i64TSCDelta : INT64_MAX;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync uint64_t uTsc = ASMReadTSC();
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync ASMSetFlags(uFlags);
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync /*
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * If the delta is valid, apply it, otherwise ignore it (really shouldn't
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync * happen in these contexts!).
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync */
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync if (RT_LIKELY(iTscDelta != INT64_MAX))
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync return uTsc - iTscDelta;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync# ifdef IN_RING0
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync AssertMsgFailed(("iCpuSet=%d (%#x) iGipCpu=%#x\n", iCpuSet, iCpuSet, iGipCpu));
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync# else
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync AssertMsgFailed(("idApic=%#x iGipCpu=%#x\n", idApic, iGipCpu));
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync# endif
3d33b6a3faf40871bae75119c2569cdc4acb2d46vboxsync return uTsc;
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync# endif
6b9d50a0f466bd5a61458ed53925480ab28a3c17vboxsync}
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync#endif /* RT_ARCH_AMD64 || RT_ARCH_X86 */
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync