VirtualBox

Changeset 57218 in vbox


Ignore:
Timestamp:
Aug 6, 2015 2:53:27 PM (9 years ago)
Author:
vboxsync
Message:

SUPDrv, tstGIP-2: Add support for GIP flags and testing TSC frequency compatibility.

Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/sup.h

    r57108 r57218  
    389389     * can be accessed from ring-3 and raw-mode context. */
    390390    uint32_t            fGetGipCpu;
     391    /** GIP flags, see SUPGIP_FLAGS_XXX. */
     392    volatile uint32_t   fFlags;
    391393
    392394    /** Padding / reserved space for future data. */
    393     uint32_t            au32Padding1[25];
     395    uint32_t            au32Padding1[24];
    394396
    395397    /** Table indexed by the CPU APIC ID to get the CPU table index. */
     
    424426 * Upper 16 bits is the major version. Major version is only changed with
    425427 * incompatible changes in the GIP. */
    426 #define SUPGLOBALINFOPAGE_VERSION   0x00060000
     428#define SUPGLOBALINFOPAGE_VERSION   0x00060001
    427429
    428430/**
     
    491493SUPDECL(PSUPGLOBALINFOPAGE)             SUPGetGIP(void);
    492494
     495/** @name SUPGIP_FLAGS_XXX - SUPR3GipSetFlags flags.
     496 * @{ */
     497/** Enable GIP test mode. */
     498#define SUPGIP_FLAGS_TESTING_ENABLE          RT_BIT_32(0)
     499/** Valid mask of flags that can be set through the ioctl. */
     500#define SUPGIP_FLAGS_VALID_MASK              RT_BIT_32(0)
     501/** GIP test mode needs to be checked (e.g. when enabled or being disabled). */
     502#define SUPGIP_FLAGS_TESTING                 RT_BIT_32(24)
     503/** Prepare to start GIP test mode. */
     504#define SUPGIP_FLAGS_TESTING_START           RT_BIT_32(25)
     505/** Prepare to stop GIP test mode. */
     506#define SUPGIP_FLAGS_TESTING_STOP            RT_BIT_32(26)
     507/** @} */
    493508
    494509/** @internal  */
     
    17081723SUPR3DECL(int) SUPR3TscDeltaMeasure(RTCPUID idCpu, bool fAsync, bool fForce, uint8_t cRetries, uint8_t cMsWaitRetry);
    17091724
     1725
    17101726/**
    17111727 * Reads the delta-adjust TSC value.
     
    17181734SUPR3DECL(int) SUPR3ReadTsc(uint64_t *puTsc, uint16_t *pidApic);
    17191735
     1736
     1737/**
     1738 * Sets the GIP flags.
     1739 *
     1740 * @returns VBox status code.
     1741 * @param   fOrMask         The OR mask of the GIP flags, see SUPGIP_FLAGS_XXX.
     1742 * @param   fAndMask        The AND mask of the GIP flags, see SUPGIP_FLAGS_XXX.
     1743 */
     1744SUPR3DECL(int) SUPR3GipSetFlags(uint32_t fOrMask, uint32_t fAndMask);
    17201745/** @} */
    17211746#endif /* IN_RING3 */
  • trunk/include/VBox/sup.mac

    r54252 r57218  
    8080    .enmUseTscDelta             resd 1
    8181    .fGetGipCpu                 resd 1
    82     .au32Padding1               resd 25
     82    .fFlags                     resd 1
     83    .au32Padding1               resd 24
    8384    .aiCpuFromApicId            resw 256
    8485    .aiCpuFromCpuSetIdx         resw 256
  • trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp

    r57090 r57218  
    22572257        }
    22582258
     2259        case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_GIP_SET_FLAGS):
     2260        {
     2261            /* validate */
     2262            PSUPGIPSETFLAGS pReq = (PSUPGIPSETFLAGS)pReqHdr;
     2263            REQ_CHECK_SIZES(SUP_IOCTL_GIP_SET_FLAGS);
     2264
     2265            pReqHdr->rc = supdrvIOCtl_GipSetFlags(pDevExt, pSession, pReq->u.In.fOrMask, pReq->u.In.fAndMask);
     2266            return 0;
     2267        }
     2268
    22592269        default:
    22602270            Log(("Unknown IOCTL %#lx\n", (long)uIOCtl));
  • trunk/src/VBox/HostDrivers/Support/SUPDrvGip.cpp

    r57174 r57218  
    125125static DECLCALLBACK(void)   supdrvGipSyncAndInvariantTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick);
    126126static DECLCALLBACK(void)   supdrvGipAsyncTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick);
     127static int                  supdrvGipSetFlags(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uint32_t fOrMask, uint32_t fAndMask);
    127128static void                 supdrvGipInitCpu(PSUPGLOBALINFOPAGE pGip, PSUPGIPCPU pCpu, uint64_t u64NanoTS, uint64_t uCpuHz);
    128129static void                 supdrvTscResetSamples(PSUPDRVDEVEXT pDevExt, bool fClearDeltas);
     
    627628    RTSemFastMutexRequest(pDevExt->mtxGip);
    628629#endif
     630
     631    /*
     632     * GIP test-mode session?
     633     */
     634    if (   pSession->fGipTestMode
     635        && pDevExt->pGip)
     636    {
     637        uint32_t fFlags = pDevExt->pGip->fFlags;
     638        fFlags &= ~SUPGIP_FLAGS_TESTING_ENABLE;
     639        supdrvGipSetFlags(pDevExt, pSession, 0, fFlags);
     640        Assert(!pSession->fGipTestMode);
     641    }
    629642
    630643    /*
     
    20922105    uint32_t    u32UpdateIntervalTSCSlack;
    20932106    unsigned    iTSCHistoryHead;
     2107    bool        fUpdateCpuHz;
     2108    uint32_t    fGipFlags;
    20942109    uint64_t    u64CpuHz;
    20952110    uint32_t    u32TransactionId;
     
    21122127    ASMAtomicWriteU64(&pGipCpu->u64TSC, u64TSC);
    21132128
     2129    /* Determine when we need to update the TSC frequency. */
     2130    fUpdateCpuHz = pGip->u32Mode != SUPGIPMODE_INVARIANT_TSC;
     2131
     2132    /*
     2133     * Handle GIP test mode toggle.
     2134     */
     2135    fGipFlags = pGip->fFlags;
     2136    if (!(fGipFlags & SUPGIP_FLAGS_TESTING))
     2137    { /* likely*/ }
     2138    else
     2139    {
     2140        if (fGipFlags & (SUPGIP_FLAGS_TESTING_ENABLE | SUPGIP_FLAGS_TESTING_START))
     2141        {
     2142            if (fGipFlags & SUPGIP_FLAGS_TESTING_START)
     2143            {
     2144                /* Cache the TSC frequency before forcing updates due to test mode. */
     2145                if (!fUpdateCpuHz)
     2146                    pDevExt->uGipTestModeInvariantCpuHz = pGip->aCPUs[0].u64CpuHz;
     2147                fGipFlags &= ~SUPGIP_FLAGS_TESTING_START;
     2148                ASMAtomicWriteU32(&pGip->fFlags, fGipFlags);
     2149            }
     2150            fUpdateCpuHz = true;
     2151        }
     2152        else if (fGipFlags & SUPGIP_FLAGS_TESTING_STOP)
     2153        {
     2154            /* Restore the cached TSC frequency if any. */
     2155            if (!fUpdateCpuHz)
     2156            {
     2157                Assert(pDevExt->uGipTestModeInvariantCpuHz);
     2158                ASMAtomicWriteU64(&pGip->aCPUs[0].u64CpuHz, pDevExt->uGipTestModeInvariantCpuHz);
     2159            }
     2160            fGipFlags &= ~(SUPGIP_FLAGS_TESTING_STOP | SUPGIP_FLAGS_TESTING);
     2161            ASMAtomicWriteU32(&pGip->fFlags, fGipFlags);
     2162        }
     2163    }
     2164
    21142165    /*
    21152166     * We don't need to keep realculating the frequency when it's invariant, so
    21162167     * the remainder of this function is only for the sync and async TSC modes.
    21172168     */
    2118     if (pGip->u32Mode != SUPGIPMODE_INVARIANT_TSC)
     2169    if (fUpdateCpuHz)
    21192170    {
    21202171        if (u64TSCDelta >> 32)
     
    29803031 * eliminate huge deltas when the worker is too early and doesn't by
    29813032 * itself help produce more accurate deltas. We allow two times the
    2982  * computed minimum as an arbibtrary acceptable threshold. Therefore,
     3033 * computed minimum as an arbitrary acceptable threshold. Therefore,
    29833034 * it is still possible to get negative deltas where there are none
    29843035 * when the worker is earlier. As long as these occasional negative
    29853036 * deltas are lower than the time it takes to exit guest-context and
    2986  * the OS to reschedule EMT on a different CPU we won't expose a TSC
    2987  * that jumped backwards. It is because of the existence of the
    2988  * negative deltas we don't recompute the delta with the master and
     3037 * the OS to reschedule EMT on a different CPU, we won't expose a TSC
     3038 * that jumped backwards. It is due to the existence of the negative
     3039 * deltas that we don't recompute the delta with the master and
    29893040 * worker interchanged to eliminate the remaining measurement error.
    29903041 *
     
    47224773}
    47234774
     4775
     4776/**
     4777 * Worker for supdrvIOCtl_GipSetFlags.
     4778 *
     4779 * @returns VBox status code.
     4780 * @param   pDevExt         Pointer to the device instance data.
     4781 * @param   pSession        The support driver session.
     4782 * @param   fOrMask         The OR mask of the GIP flags, see SUPGIP_FLAGS_XXX.
     4783 * @param   fAndMask        The AND mask of the GIP flags, see SUPGIP_FLAGS_XXX.
     4784 *
     4785 * @remarks This function doesn't validate any of the flags.
     4786 */
     4787static int supdrvGipSetFlags(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uint32_t fOrMask, uint32_t fAndMask)
     4788{
     4789    uint32_t           cRefs;
     4790    PSUPGLOBALINFOPAGE pGip = pDevExt->pGip;
     4791
     4792    /*
     4793     * Compute GIP test-mode flags.
     4794     */
     4795    if (fOrMask & SUPGIP_FLAGS_TESTING_ENABLE)
     4796    {
     4797        pSession->fGipTestMode = true;
     4798        cRefs = ASMAtomicIncU32(&pDevExt->cGipTestModeRefs);
     4799        if (cRefs == 1)
     4800            fOrMask |= SUPGIP_FLAGS_TESTING | SUPGIP_FLAGS_TESTING_START;
     4801    }
     4802    else
     4803    {
     4804        cRefs = ASMAtomicDecU32(&pDevExt->cGipTestModeRefs);
     4805        pSession->fGipTestMode = false;
     4806        if (!cRefs)
     4807            fOrMask |= SUPGIP_FLAGS_TESTING_STOP;
     4808    }
     4809
     4810    /*
     4811     * Commit the flags.
     4812     */
     4813    uint32_t fFlags = ASMAtomicUoReadU32(&pGip->fFlags);
     4814    fFlags |= fOrMask;
     4815    fFlags &= fAndMask;
     4816    ASMAtomicWriteU32(&pGip->fFlags, fFlags);
     4817    return VINF_SUCCESS;
     4818}
     4819
     4820
     4821/**
     4822 * Sets GIP test mode parameters.
     4823 *
     4824 * @returns VBox status code.
     4825 * @param   pDevExt         Pointer to the device instance data.
     4826 * @param   pSession        The support driver session.
     4827 * @param   fOrMask         The OR mask of the GIP flags, see SUPGIP_FLAGS_XXX.
     4828 * @param   fAndMask        The AND mask of the GIP flags, see SUPGIP_FLAGS_XXX.
     4829 */
     4830int VBOXCALL supdrvIOCtl_GipSetFlags(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uint32_t fOrMask, uint32_t fAndMask)
     4831{
     4832    PSUPGLOBALINFOPAGE pGip;
     4833
     4834    /*
     4835     * Validate.  We require the client to have mapped GIP (no asserting on
     4836     * ring-3 preconditions).
     4837     */
     4838    AssertPtr(pDevExt); AssertPtr(pSession); /* paranoia^2 */
     4839    if (pSession->GipMapObjR3 == NIL_RTR0MEMOBJ)
     4840        return VERR_WRONG_ORDER;
     4841    pGip = pDevExt->pGip;
     4842    AssertReturn(pGip, VERR_INTERNAL_ERROR_3);
     4843
     4844    if (fOrMask & ~SUPGIP_FLAGS_VALID_MASK)
     4845        return VERR_INVALID_PARAMETER;
     4846    if ((fAndMask & ~SUPGIP_FLAGS_VALID_MASK) != ~SUPGIP_FLAGS_VALID_MASK)
     4847        return VERR_INVALID_PARAMETER;
     4848
     4849    return supdrvGipSetFlags(pDevExt, pSession, fOrMask, fAndMask);
     4850}
     4851
  • trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h

    r57093 r57218  
    15231523/** @} */
    15241524
     1525
    15251526/** @name SUP_IOCTL_TSC_READ
    15261527 * Reads the TSC and apply TSC-delta if applicable, determining the delta if
     
    15591560/** @} */
    15601561
     1562
     1563/** @name SUP_IOCTL_GIP_SET_FLAGS
     1564 * Set GIP flags.
     1565 *
     1566 * @{
     1567 */
     1568#define SUP_IOCTL_GIP_SET_FLAGS                         SUP_CTL_CODE_SIZE(39, SUP_IOCTL_GIP_SET_FLAGS_SIZE)
     1569#define SUP_IOCTL_GIP_SET_FLAGS_SIZE                    sizeof(SUPGIPSETFLAGS)
     1570#define SUP_IOCTL_GIP_SET_FLAGS_SIZE_IN                 sizeof(SUPGIPSETFLAGS)
     1571#define SUP_IOCTL_GIP_SET_FLAGS_SIZE_OUT                sizeof(SUPREQHDR)
     1572typedef struct SUPGIPSETFLAGS
     1573{
     1574    /** The header. */
     1575    SUPREQHDR               Hdr;
     1576    union
     1577    {
     1578        struct
     1579        {
     1580            /** The AND flags mask, see SUPGIP_FLAGS_XXX. */
     1581            uint32_t        fAndMask;
     1582            /** The OR flags mask, see SUPGIP_FLAGS_XXX. */
     1583            uint32_t        fOrMask;
     1584        } In;
     1585    } u;
     1586} SUPGIPSETFLAGS, *PSUPGIPSETFLAGS;
     1587/** @} */
     1588
    15611589#pragma pack()                          /* paranoia */
    15621590
  • trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h

    r56558 r57218  
    545545    /** The user tracepoint module lookup table. */
    546546    struct SUPDRVTRACERUMOD        *apTpLookupTable[32];
     547    /** Whether this is a GIP test-mode client session or not. */
     548    bool                            fGipTestMode;
    547549#ifndef SUPDRV_AGNOSTIC
    548550# if defined(RT_OS_DARWIN)
     
    752754#endif
    753755
     756    /** @name GIP test mode.
     757     *  @{ */
     758    /** Reference counter for GIP test-mode sessions. */
     759    uint32_t volatile               cGipTestModeRefs;
     760    /** Cache of TSC frequency before enabling test-mode on invariant GIP systems. */
     761    uint64_t                        uGipTestModeInvariantCpuHz;
     762    /** @} */
     763
    754764    /*
    755765     * Note! The non-agnostic bits must be at the very end of the structure!
     
    949959int  VBOXCALL   supdrvIOCtl_TscDeltaMeasure(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPTSCDELTAMEASURE pReq);
    950960int  VBOXCALL   supdrvIOCtl_TscRead(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPTSCREAD pReq);
     961int  VBOXCALL   supdrvIOCtl_GipSetFlags(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uint32_t fOrMask, uint32_t fAndMask);
     962
    951963
    952964/* SUPDrvTracer.cpp */
  • trunk/src/VBox/HostDrivers/Support/SUPLib.cpp

    r56293 r57218  
    22482248}
    22492249
     2250
     2251SUPR3DECL(int) SUPR3GipSetFlags(uint32_t fOrMask, uint32_t fAndMask)
     2252{
     2253    AssertMsgReturn(!(fOrMask & ~SUPGIP_FLAGS_VALID_MASK),
     2254                    ("fOrMask=%#x ValidMask=%#x\n", fOrMask, SUPGIP_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER);
     2255    AssertMsgReturn((fAndMask & ~SUPGIP_FLAGS_VALID_MASK) == ~SUPGIP_FLAGS_VALID_MASK,
     2256                    ("fAndMask=%#x ValidMask=%#x\n", fAndMask, SUPGIP_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER);
     2257
     2258    SUPGIPSETFLAGS Req;
     2259    Req.Hdr.u32Cookie        = g_u32Cookie;
     2260    Req.Hdr.u32SessionCookie = g_u32SessionCookie;
     2261    Req.Hdr.cbIn             = SUP_IOCTL_GIP_SET_FLAGS_SIZE_IN;
     2262    Req.Hdr.cbOut            = SUP_IOCTL_GIP_SET_FLAGS_SIZE_OUT;
     2263    Req.Hdr.fFlags           = SUPREQHDR_FLAGS_DEFAULT;
     2264    Req.Hdr.rc               = VERR_INTERNAL_ERROR;
     2265
     2266    Req.u.In.fAndMask        = fAndMask;
     2267    Req.u.In.fOrMask         = fOrMask;
     2268
     2269    int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_GIP_SET_FLAGS, &Req, SUP_IOCTL_GIP_SET_FLAGS_SIZE);
     2270    if (RT_SUCCESS(rc))
     2271        rc = Req.Hdr.rc;
     2272    return rc;
     2273}
     2274
  • trunk/src/VBox/HostDrivers/Support/SUPLibAll.cpp

    r57097 r57218  
    288288        /* Arbitrary tolerance threshold, tweak later if required, perhaps
    289289           more tolerance on lower frequencies and less tolerance on higher. */
    290         uint16_t uThr = !fRelax ? 666 /* 0.15% */ : 125 /* 0.8% */;
    291         uint64_t uLo  = uBaseCpuHz / uThr;
    292         uint64_t uHi  = uBaseCpuHz + (uBaseCpuHz - uLo);
     290        uint16_t uFact = !fRelax ? 666 /* 0.15% */ : 125 /* 0.8% */;
     291        uint64_t uThr  = uBaseCpuHz / uFact;
     292        uint64_t uLo   = uBaseCpuHz - uThr;
     293        uint64_t uHi   = uBaseCpuHz + uThr;
    293294        if (   uCpuHz < uLo
    294295            || uCpuHz > uHi)
  • trunk/src/VBox/HostDrivers/Support/testcase/tstGIP-2.cpp

    r57060 r57218  
    4141#include <iprt/x86.h>
    4242
    43 
    44 /**
    45  * Checks whether the CPU advertises an invariant TSC or not.
    46  *
    47  * @returns true if invariant, false otherwise.
    48  */
    49 bool tstIsInvariantTsc(void)
    50 {
    51     if (ASMHasCpuId())
    52     {
    53         uint32_t uEax, uEbx, uEcx, uEdx;
    54         ASMCpuId(0x80000000, &uEax, &uEbx, &uEcx, &uEdx);
    55         if (uEax >= 0x80000007)
    56         {
    57             ASMCpuId(0x80000007, &uEax, &uEbx, &uEcx, &uEdx);
    58             if (uEdx & X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR)
    59                 return true;
    60         }
    61     }
    62     return false;
    63 }
    64 
    65 
    6643int main(int argc, char **argv)
    6744{
     
    7956        { "--reference",        'r', RTGETOPT_REQ_UINT64 },  /* reference value of CpuHz, display the
    8057                                                              * CpuHz deviation in a separate column. */
     58        { "--notestmode",       't', RTGETOPT_REQ_NOTHING }  /* don't run GIP in test-mode (atm, test-mode
     59                                                              * implies updating GIP CpuHz even when invariant) */
    8160    };
    8261
     
    8564    bool fSpin = false;
    8665    bool fCompat = true;
     66    bool fTestMode = true;
    8767    int ch;
    88     uint64_t uCpuHzRef = 0;
     68    uint64_t uCpuHzRef = UINT64_MAX;
    8969    uint64_t uCpuHzOverallDeviation = 0;
    9070    uint32_t cCpuHzNotCompat = 0;
     
    11898                break;
    11999
     100            case 't':
     101                fTestMode = false;
     102                break;
     103
    120104            default:
    121105                return RTGetOptPrintError(ch, &ValueUnion);
     
    132116        if (g_pSUPGlobalInfoPage)
    133117        {
     118            /* Pick current CpuHz as the reference if none was specified. */
     119            if (uCpuHzRef == UINT64_MAX)
     120                uCpuHzRef = SUPGetCpuHzFromGip(g_pSUPGlobalInfoPage);
     121
     122            if (   fTestMode
     123                && g_pSUPGlobalInfoPage->u32Mode == SUPGIPMODE_INVARIANT_TSC)
     124                SUPR3GipSetFlags(SUPGIP_FLAGS_TESTING_ENABLE, UINT32_MAX);
     125
    134126            RTPrintf("tstGIP-2: cCpus=%d  u32UpdateHz=%RU32  u32UpdateIntervalNS=%RU32  u64NanoTSLastUpdateHz=%RX64  u64CpuHz=%RU64  uCpuHzRef=%RU64  u32Mode=%d (%s) u32Version=%#x\n",
    135127                     g_pSUPGlobalInfoPage->cCpus,
     
    147139                     uCpuHzRef ? "  CpuHz deviation  Compat  " : "");
    148140            static SUPGIPCPU s_aaCPUs[2][256];
     141
    149142            for (uint32_t i = 0; i < cIterations; i++)
    150143            {
     
    170163                            {
    171164                                /* Wait until the history validation code takes effect. */
     165                                bool fCurHzCompat = true;
    172166                                if (pCpu->u32TransactionId > 23 + (8 * 2) + 1)
    173167                                {
     
    176170                                    uCpuHzOverallDeviation += uCpuHzDeviation;
    177171                                    cCpuHzOverallDevCnt++;
     172                                    fCurHzCompat = SUPIsTscFreqCompatibleEx(uCpuHzRef, pCpu->u64CpuHz, false /* fRelax */);
    178173                                }
    179                                 bool fCurHzCompat = SUPIsTscFreqCompatibleEx(uCpuHzRef, pCpu->u64CpuHz, false /* fRelax */);
    180174                                uint32_t uPct = (uint32_t)(uCpuHzDeviation * 100000 / uCpuHzRef + 5);
    181175                                RTStrPrintf(szCpuHzDeviation, sizeof(szCpuHzDeviation), "%10RI64%3d.%02d%%  %RTbool   ",
     
    271265                RTPrintf("tstGIP-2: CpuHz compatibility: %RTbool (incompatible %u of %u times w/ %RU64 Hz)\n", fCompat,
    272266                         cCpuHzNotCompat, cIterations * g_pSUPGlobalInfoPage->cCpus, uCpuHzRef);
     267
     268                if (   !fCompat
     269                    && g_pSUPGlobalInfoPage->u32Mode == SUPGIPMODE_INVARIANT_TSC)
     270                    rc = -1;
    273271            }
     272
     273            /* Disable GIP test mode. */
     274            if (fTestMode)
     275                SUPR3GipSetFlags(0, ~SUPGIP_FLAGS_TESTING_ENABLE);
    274276        }
    275277        else
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette