VirtualBox

Ignore:
Timestamp:
Dec 17, 2009 12:49:43 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
56123
Message:

SUPDrv: Get better GIP values right after resuming it.

Location:
trunk/src/VBox/HostDrivers/Support
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/SUPDrv.c

    r25434 r25459  
    27712771
    27722772/**
     2773 * (Re-)initializes the per-cpu structure prior to starting or resuming the GIP
     2774 * updating.
     2775 *
     2776 * @param   pGipCpu          The per CPU structure for this CPU.
     2777 * @param   u64NanoTS        The current time.
     2778 */
     2779static void supdrvGipReInitCpu(PSUPGIPCPU pGipCpu, uint64_t u64NanoTS)
     2780{
     2781    pGipCpu->u64TSC    = ASMReadTSC() - pGipCpu->u32UpdateIntervalTSC;
     2782    pGipCpu->u64NanoTS = u64NanoTS;
     2783}
     2784
     2785
     2786/**
     2787 * Set the current TSC and NanoTS value for the CPU.
     2788 *
     2789 * @param   idCpu            The CPU ID. Unused - we have to use the APIC ID.
     2790 * @param   pvUser1          Pointer to the ring-0 GIP mapping.
     2791 * @param   pvUser2          Pointer to the variable holding the current time.
     2792 */
     2793static DECLCALLBACK(void) supdrvGipReInitCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2)
     2794{
     2795    PSUPGLOBALINFOPAGE  pGip = (PSUPGLOBALINFOPAGE)pvUser1;
     2796    unsigned            iCpu = ASMGetApicId();
     2797
     2798    if (RT_LIKELY(iCpu < RT_ELEMENTS(pGip->aCPUs)))
     2799        supdrvGipReInitCpu(&pGip->aCPUs[iCpu], *(uint64_t *)pvUser2);
     2800
     2801    NOREF(pvUser2);
     2802    NOREF(idCpu);
     2803}
     2804
     2805
     2806/**
    27732807 * Maps the GIP into userspace and/or get the physical address of the GIP.
    27742808 *
     
    28292863            {
    28302864                PSUPGLOBALINFOPAGE pGipR0 = pDevExt->pGip;
     2865                uint64_t u64NanoTS;
    28312866                unsigned i;
    28322867
    28332868                LogFlow(("SUPR0GipMap: Resumes GIP updating\n"));
    28342869
    2835                 for (i = 0; i < RT_ELEMENTS(pGipR0->aCPUs); i++)
    2836                     ASMAtomicXchgU32(&pGipR0->aCPUs[i].u32TransactionId, pGipR0->aCPUs[i].u32TransactionId & ~(GIP_UPDATEHZ_RECALC_FREQ * 2 - 1));
    2837                 ASMAtomicXchgU64(&pGipR0->u64NanoTSLastUpdateHz, 0);
     2870                if (pGipR0->aCPUs[0].u32TransactionId != 2 /* not the first time */)
     2871                {
     2872                    for (i = 0; i < RT_ELEMENTS(pGipR0->aCPUs); i++)
     2873                        ASMAtomicUoWriteU32(&pGipR0->aCPUs[i].u32TransactionId,
     2874                                            (pGipR0->aCPUs[i].u32TransactionId + GIP_UPDATEHZ_RECALC_FREQ * 2)
     2875                                            & ~(GIP_UPDATEHZ_RECALC_FREQ * 2 - 1));
     2876                    ASMAtomicWriteU64(&pGipR0->u64NanoTSLastUpdateHz, 0);
     2877                }
     2878
     2879                u64NanoTS = RTTimeSystemNanoTS() - pGipR0->u32UpdateIntervalNS;
     2880                if (   pGipR0->u32Mode == SUPGIPMODE_SYNC_TSC
     2881                    || RTMpGetOnlineCount() == 1)
     2882                    supdrvGipReInitCpu(&pGipR0->aCPUs[0], u64NanoTS);
     2883                else
     2884                    RTMpOnAll(supdrvGipReInitCpuCallback, pGipR0, &u64NanoTS);
    28382885
    28392886                rc = RTTimerStart(pDevExt->pGipTimer, 0);
     
    44634510    uint64_t        NanoTS    = RTTimeSystemNanoTS();
    44644511
    4465     supdrvGipUpdate(pDevExt->pGip, NanoTS, u64TSC);
     4512    supdrvGipUpdate(pDevExt->pGip, NanoTS, u64TSC, iTick);
    44664513
    44674514    ASMSetFlags(fOldFlags);
     
    44844531    /** @todo reset the transaction number and whatnot when iTick == 1. */
    44854532    if (pDevExt->idGipMaster == idCpu)
    4486         supdrvGipUpdate(pDevExt->pGip, NanoTS, u64TSC);
     4533        supdrvGipUpdate(pDevExt->pGip, NanoTS, u64TSC, iTick);
    44874534    else
    4488         supdrvGipUpdatePerCpu(pDevExt->pGip, NanoTS, u64TSC, ASMGetApicId());
     4535        supdrvGipUpdatePerCpu(pDevExt->pGip, NanoTS, u64TSC, ASMGetApicId(), iTick);
    44894536
    44904537    ASMSetFlags(fOldFlags);
     
    45774624        /*
    45784625         * We don't know the following values until we've executed updates.
    4579          * So, we'll just insert very high values.
     4626         * So, we'll just pretend it's a 4 GHz CPU and adjust the history it on
     4627         * the 2nd timer callout.
    45804628         */
    4581         pGip->aCPUs[i].u64CpuHz          = _4G + 1;
    4582         pGip->aCPUs[i].u32UpdateIntervalTSC = _2G / 4;
    4583         pGip->aCPUs[i].au32TSCHistory[0] = _2G / 4;
    4584         pGip->aCPUs[i].au32TSCHistory[1] = _2G / 4;
    4585         pGip->aCPUs[i].au32TSCHistory[2] = _2G / 4;
    4586         pGip->aCPUs[i].au32TSCHistory[3] = _2G / 4;
    4587         pGip->aCPUs[i].au32TSCHistory[4] = _2G / 4;
    4588         pGip->aCPUs[i].au32TSCHistory[5] = _2G / 4;
    4589         pGip->aCPUs[i].au32TSCHistory[6] = _2G / 4;
    4590         pGip->aCPUs[i].au32TSCHistory[7] = _2G / 4;
     4629        pGip->aCPUs[i].u64CpuHz          = _4G + 1; /* tstGIP-2 depends on this. */
     4630        pGip->aCPUs[i].u32UpdateIntervalTSC
     4631            = pGip->aCPUs[i].au32TSCHistory[0]
     4632            = pGip->aCPUs[i].au32TSCHistory[1]
     4633            = pGip->aCPUs[i].au32TSCHistory[2]
     4634            = pGip->aCPUs[i].au32TSCHistory[3]
     4635            = pGip->aCPUs[i].au32TSCHistory[4]
     4636            = pGip->aCPUs[i].au32TSCHistory[5]
     4637            = pGip->aCPUs[i].au32TSCHistory[6]
     4638            = pGip->aCPUs[i].au32TSCHistory[7]
     4639            = /*pGip->aCPUs[i].u64CpuHz*/ _4G / uUpdateHz;
    45914640    }
    45924641
     
    47254774 * @param   u64NanoTS       The current time stamp.
    47264775 * @param   u64TSC          The current TSC.
    4727  */
    4728 static void supdrvGipDoUpdateCpu(PSUPGLOBALINFOPAGE pGip, PSUPGIPCPU pGipCpu, uint64_t u64NanoTS, uint64_t u64TSC)
     4776 * @param   iTick           The current timer tick.
     4777 */
     4778static void supdrvGipDoUpdateCpu(PSUPGLOBALINFOPAGE pGip, PSUPGIPCPU pGipCpu, uint64_t u64NanoTS, uint64_t u64TSC, uint64_t iTick)
    47294779{
    47304780    uint64_t    u64TSCDelta;
     
    47334783    unsigned    iTSCHistoryHead;
    47344784    uint64_t    u64CpuHz;
     4785    uint32_t    u32TransactionId;
    47354786
    47364787    /* Delta between this and the previous update. */
    4737     pGipCpu->u32UpdateIntervalNS = (uint32_t)(u64NanoTS - pGipCpu->u64NanoTS);
     4788    ASMAtomicUoWriteU32(&pGipCpu->u32PrevUpdateIntervalNS, (uint32_t)(u64NanoTS - pGipCpu->u64NanoTS));
    47384789
    47394790    /*
     
    47564807
    47574808    /*
     4809     * On the 2nd and 3rd callout, reset the history with the current TSC
     4810     * interval since the values entered by supdrvGipInit are totally off.
     4811     * The interval on the 1st callout completely unreliable, the 2nd is a bit
     4812     * better, while the 3rd should be most reliable.
     4813     */
     4814    u32TransactionId = pGipCpu->u32TransactionId;
     4815    if (RT_UNLIKELY(   (   u32TransactionId == 5
     4816                        || u32TransactionId == 7)
     4817                    && (   iTick == 2
     4818                        || iTick == 3) ))
     4819    {
     4820        unsigned i;
     4821        for (i = 0; i < RT_ELEMENTS(pGipCpu->au32TSCHistory); i++)
     4822            ASMAtomicUoWriteU32(&pGipCpu->au32TSCHistory[i], (uint32_t)u64TSCDelta);
     4823    }
     4824
     4825    /*
    47584826     * TSC History.
    47594827     */
    47604828    Assert(RT_ELEMENTS(pGipCpu->au32TSCHistory) == 8);
    4761 
    47624829    iTSCHistoryHead = (pGipCpu->iTSCHistoryHead + 1) & 7;
    47634830    ASMAtomicXchgU32(&pGipCpu->iTSCHistoryHead, iTSCHistoryHead);
     
    48154882 * Updates the GIP.
    48164883 *
    4817  * @param   pGip        Pointer to the GIP.
    4818  * @param   u64NanoTS   The current nanosecond timesamp.
    4819  * @param   u64TSC      The current TSC timesamp.
    4820  */
    4821 void VBOXCALL supdrvGipUpdate(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC)
     4884 * @param   pGip            Pointer to the GIP.
     4885 * @param   u64NanoTS       The current nanosecond timesamp.
     4886 * @param   u64TSC          The current TSC timesamp.
     4887 * @param   iTick           The current timer tick.
     4888 */
     4889void VBOXCALL supdrvGipUpdate(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, uint64_t iTick)
    48224890{
    48234891    /*
     
    48304898    {
    48314899        unsigned iCpu = ASMGetApicId();
    4832         if (RT_LIKELY(iCpu >= RT_ELEMENTS(pGip->aCPUs)))
     4900        if (RT_UNLIKELY(iCpu >= RT_ELEMENTS(pGip->aCPUs)))
    48334901            return;
    48344902        pGipCpu = &pGip->aCPUs[iCpu];
     
    48704938     * Update the data.
    48714939     */
    4872     supdrvGipDoUpdateCpu(pGip, pGipCpu, u64NanoTS, u64TSC);
     4940    supdrvGipDoUpdateCpu(pGip, pGipCpu, u64NanoTS, u64TSC, iTick);
    48734941
    48744942    /*
     
    48824950 * Updates the per cpu GIP data for the calling cpu.
    48834951 *
    4884  * @param   pGip        Pointer to the GIP.
    4885  * @param   u64NanoTS   The current nanosecond timesamp.
    4886  * @param   u64TSC      The current TSC timesamp.
    4887  * @param   iCpu        The CPU index.
    4888  */
    4889 void VBOXCALL supdrvGipUpdatePerCpu(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, unsigned iCpu)
     4952 * @param   pGip            Pointer to the GIP.
     4953 * @param   u64NanoTS       The current nanosecond timesamp.
     4954 * @param   u64TSC          The current TSC timesamp.
     4955 * @param   iCpu            The CPU index.
     4956 * @param   iTick           The current timer tick.
     4957 */
     4958void VBOXCALL supdrvGipUpdatePerCpu(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, unsigned iCpu, uint64_t iTick)
    48904959{
    48914960    PSUPGIPCPU  pGipCpu;
     
    49094978         * Update the data.
    49104979         */
    4911         supdrvGipDoUpdateCpu(pGip, pGipCpu, u64NanoTS, u64TSC);
     4980        supdrvGipDoUpdateCpu(pGip, pGipCpu, u64NanoTS, u64TSC, iTick);
    49124981
    49134982        /*
  • trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h

    r25336 r25459  
    716716int  VBOXCALL   supdrvGipInit(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, RTHCPHYS HCPhys, uint64_t u64NanoTS, unsigned uUpdateHz);
    717717void VBOXCALL   supdrvGipTerm(PSUPGLOBALINFOPAGE pGip);
    718 void VBOXCALL   supdrvGipUpdate(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC);
    719 void VBOXCALL   supdrvGipUpdatePerCpu(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, unsigned iCpu);
     718void VBOXCALL   supdrvGipUpdate(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, uint64_t iTick);
     719void VBOXCALL   supdrvGipUpdatePerCpu(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, uint64_t u64TSC, unsigned iCpu, uint64_t iTick);
    720720bool VBOXCALL   supdrvDetermineAsyncTsc(uint64_t *pu64DiffCores);
    721721
Note: See TracChangeset for help on using the changeset viewer.

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