VirtualBox

Ignore:
Timestamp:
Feb 16, 2015 10:41:32 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
98289
Message:

SUP,IPRT: Started as a build fix ended up as a cleanup (mostly untested as I'm windows). We'll keep SUP_IOCTL_TSC_READ for the purpose of dealing with the i64TSCDelta == INT64_MAX in SUPReadTsc/SUPReadTscWithDelta. Moved the excessive inline code from sup.h to SUPLibAll.cpp (new file) and SUPDrv.c (apply delta). Don't bother too much about trying to share code between SUPLibAll.cpp and SUPDrv.c/++ as the SUPReadTsc[WithDelta] scenario does not care about knowing when things goes bad, it just needs a TSC that is as good as we can get. The SUPDrv.c code on the other hand probably needs other kind of status codes, assertions and whatnot to be better off with its own version of the code. Remove the now unused assembly macro for applying the delta - the way the delta is applied will not change, period, so better just document it instead.

File:
1 edited

Legend:

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

    r54214 r54224  
    164164static int                  supdrvIOCtl_MsrProber(PSUPDRVDEVEXT pDevExt, PSUPMSRPROBER pReq);
    165165static int                  supdrvIOCtl_TscDeltaMeasure(PSUPDRVDEVEXT pDevExt, PSUPTSCDELTAMEASURE pReq);
    166 static int                  supdrvIOCtl_TscRead(PSUPDRVDEVEXT pDevExt, PSUPTSCREAD pReq);
     166static int                  supdrvIOCtl_TscRead(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPTSCREAD pReq);
    167167static int                  supdrvGipCreate(PSUPDRVDEVEXT pDevExt);
    168168static void                 supdrvGipDestroy(PSUPDRVDEVEXT pDevExt);
     
    22622262            REQ_CHECK_SIZES(SUP_IOCTL_TSC_READ);
    22632263
    2264             pReqHdr->rc = supdrvIOCtl_TscRead(pDevExt, pReq);
     2264            pReqHdr->rc = supdrvIOCtl_TscRead(pDevExt, pSession, pReq);
    22652265            return 0;
    22662266        }
     
    61406140
    61416141/**
     6142 * Applies the TSC delta to the supplied raw TSC value.
     6143 *
     6144 * @returns VBox status code. (Ignored by all users, just FYI.)
     6145 * @param   pGip            Pointer to the GIP.
     6146 * @param   puTsc           Pointer to a valid TSC value before the TSC delta has been applied.
     6147 * @param   idApic          The APIC ID of the CPU @c puTsc corresponds to.
     6148 * @param   fDeltaApplied   Where to store whether the TSC delta was succesfully
     6149 *                          applied or not (optional, can be NULL).
     6150 *
     6151 * @remarks Maybe called with interrupts disabled in ring-0!
     6152 *
     6153 * @note    Don't you dare change the delta calculation.  If you really do, make
     6154 *          sure you update all places where it's used (IPRT, SUPLibAll.cpp,
     6155 *          SUPDrv.c, supdrvGipMpEvent, and more).
     6156 */
     6157DECLINLINE(int) supdrvTscDeltaApply(PSUPGLOBALINFOPAGE pGip, uint64_t *puTsc, uint16_t idApic, bool *pfDeltaApplied)
     6158{
     6159    int rc;
     6160
     6161    /*
     6162     * Validate input.
     6163     */
     6164    AssertPtr(puTsc);
     6165    AssertPtr(pGip);
     6166    Assert(GIP_ARE_TSC_DELTAS_APPLICABLE(pGip));
     6167
     6168    /*
     6169     * Carefully convert the idApic into a GIPCPU entry.
     6170     */
     6171    if (RT_LIKELY(idApic < RT_ELEMENTS(pGip->aiCpuFromApicId)))
     6172    {
     6173        uint16_t iCpu = pGip->aiCpuFromApicId[idApic];
     6174        if (RT_LIKELY(iCpu < pGip->cCpus))
     6175        {
     6176            PSUPGIPCPU pGipCpu = &pGip->aCPUs[iCpu];
     6177
     6178            /*
     6179             * Apply the delta if valid.
     6180             */
     6181            if (RT_LIKELY(pGipCpu->i64TSCDelta != INT64_MAX))
     6182            {
     6183                *puTsc -= pGipCpu->i64TSCDelta;
     6184                if (pfDeltaApplied)
     6185                    *pfDeltaApplied = true;
     6186                return VINF_SUCCESS;
     6187            }
     6188
     6189            rc = VINF_SUCCESS;
     6190        }
     6191        else
     6192        {
     6193            AssertMsgFailed(("iCpu=%u cCpus=%u\n", iCpu, pGip->cCpus));
     6194            rc = VERR_INVALID_CPU_INDEX;
     6195        }
     6196    }
     6197    else
     6198    {
     6199        AssertMsgFailed(("idApic=%u\n", idApic));
     6200        rc = VERR_INVALID_CPU_ID;
     6201    }
     6202    if (pfDeltaApplied)
     6203        *pfDeltaApplied = false;
     6204    return rc;
     6205}
     6206
     6207
     6208/**
    61426209 * Measures the TSC frequency of the system.
    61436210 *
     
    62226289            bool fAppliedBefore;
    62236290            bool fAppliedAfter;
    6224             rc = SUPTscDeltaApply(pGip, &u64TscBefore, idApicBefore, &fAppliedBefore);   AssertRCReturn(rc, rc);
    6225             rc = SUPTscDeltaApply(pGip, &u64TscAfter,  idApicAfter,  &fAppliedAfter);    AssertRCReturn(rc, rc);
     6291            rc = supdrvTscDeltaApply(pGip, &u64TscBefore, idApicBefore, &fAppliedBefore);   AssertRCReturn(rc, rc);
     6292            rc = supdrvTscDeltaApply(pGip, &u64TscAfter,  idApicAfter,  &fAppliedAfter);    AssertRCReturn(rc, rc);
    62266293
    62276294            if (   !fAppliedBefore
     
    62966363    ASMSetFlags(uFlags);
    62976364    if (GIP_ARE_TSC_DELTAS_APPLICABLE(pGip))
    6298         SUPTscDeltaApply(pGip, &u64Tsc, idApic, &fDeltaApplied);
     6365        supdrvTscDeltaApply(pGip, &u64Tsc, idApic, &fDeltaApplied);
    62996366    u64DeltaNanoTS = u64NanoTS - pDevExt->u64NanoTSAnchor;
    63006367    u64DeltaTsc = u64Tsc - pDevExt->u64TscAnchor;
     
    63716438    ASMSetFlags(uFlags);
    63726439    if (GIP_ARE_TSC_DELTAS_APPLICABLE(pGip))
    6373         SUPTscDeltaApply(pGip, &pDevExt->u64TscAnchor, idApic, &fDeltaApplied);
     6440        supdrvTscDeltaApply(pGip, &pDevExt->u64TscAnchor, idApic, &fDeltaApplied);
    63746441
    63756442#ifdef SUPDRV_USE_TSC_DELTA_THREAD
     
    66846751         */
    66856752        Assert(!ASMIntAreEnabled());
    6686         SUPTscDeltaApply(pGip, &u64TSC, ASMGetApicId(), NULL /* pfDeltaApplied */);
     6753        supdrvTscDeltaApply(pGip, &u64TSC, ASMGetApicId(), NULL /* pfDeltaApplied */);
    66876754    }
    66886755
     
    80778144
    80788145/**
    8079  * Reads the TSC and TSC-delta atomically, applies the TSC delta.
     8146 * Reads TSC with delta applied.
     8147 *
     8148 * Will try to resolve delta value INT64_MAX before applying it.  This is the
     8149 * main purpose of this function, to handle the case where the delta needs to be
     8150 * determined.
    80808151 *
    80818152 * @returns VBox status code.
    80828153 * @param   pDevExt         Pointer to the device instance data.
     8154 * @param   pSession        The support driver session.
    80838155 * @param   pReq            Pointer to the TSC-read request.
    80848156 */
    8085 static int supdrvIOCtl_TscRead(PSUPDRVDEVEXT pDevExt, PSUPTSCREAD pReq)
    8086 {
    8087     uint64_t uTsc;
    8088     uint16_t idApic;
    8089     int16_t  cTries;
     8157static int supdrvIOCtl_TscRead(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPTSCREAD pReq)
     8158{
    80908159    PSUPGLOBALINFOPAGE pGip;
    80918160    int rc;
    80928161
    80938162    /*
    8094      * Validate.
    8095      */
    8096     AssertReturn(pDevExt, VERR_INVALID_PARAMETER);
    8097     AssertReturn(pReq, VERR_INVALID_PARAMETER);
    8098     AssertReturn(pDevExt->pGip, VERR_INVALID_PARAMETER);
    8099 
     8163     * Validate.  We require the client to have mapped GIP (no asserting on
     8164     * ring-3 preconditions).
     8165     */
     8166    AssertPtr(pDevExt); AssertPtr(pReq); AssertPtr(pSession); /* paranoia^2 */
     8167    if (pSession->GipMapObjR3 == NIL_RTR0MEMOBJ)
     8168        return VERR_WRONG_ORDER;
    81008169    pGip = pDevExt->pGip;
    8101     Assert(GIP_ARE_TSC_DELTAS_APPLICABLE(pGip));
    8102 
    8103     cTries = 4;
    8104     while (cTries-- > 0)
    8105     {
    8106         int rc2;
    8107         uint16_t iCpu;
    8108 
    8109         rc = SUPGetTsc(&uTsc, &idApic);
    8110         if (RT_SUCCESS(rc))
    8111         {
    8112             pReq->u.Out.u64AdjustedTsc = uTsc;
    8113             pReq->u.Out.idApic = idApic;
    8114             return VINF_SUCCESS;
    8115         }
    8116 
    8117         /* If we failed to have a TSC-delta, measurement the TSC-delta and retry. */
    8118         AssertMsgReturn(idApic < RT_ELEMENTS(pGip->aiCpuFromApicId),
    8119                         ("idApic=%u ArraySize=%u\n", idApic, RT_ELEMENTS(pGip->aiCpuFromApicId)), VERR_INVALID_CPU_INDEX);
    8120         iCpu = pGip->aiCpuFromApicId[idApic];
    8121         AssertMsgReturn(iCpu < pGip->cCpus, ("iCpu=%u cCpus=%u\n", iCpu, pGip->cCpus), VERR_INVALID_CPU_INDEX);
    8122 
    8123         rc2 = supdrvMeasureTscDeltaOne(pDevExt, iCpu);
    8124         if (RT_SUCCESS(rc2))
    8125             AssertReturn(pGip->aCPUs[iCpu].i64TSCDelta != INT64_MAX, VERR_INTERNAL_ERROR_2);
     8170    AssertReturn(pGip, VERR_INTERNAL_ERROR_2);
     8171
     8172    /*
     8173     * We're usually here because we need to apply delta, but we shouldn't be
     8174     * upset if the GIP is some different mode.
     8175     */
     8176    if (GIP_ARE_TSC_DELTAS_APPLICABLE(pGip))
     8177    {
     8178        uint32_t cTries = 0;
     8179        for (;;)
     8180        {
     8181            /*
     8182             * Start by gathering the data, using CLI for disabling preemption
     8183             * while we do that.
     8184             */
     8185            RTCCUINTREG uFlags  = ASMIntDisableFlags();
     8186            int         iCpuSet = RTMpCpuIdToSetIndex(RTMpCpuId());
     8187            int         iGipCpu;
     8188            if (RT_LIKELY(   (unsigned)iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)
     8189                          && (iGipCpu = pGip->aiCpuFromCpuSetIdx[iCpuSet]) < pGip->cCpus ))
     8190            {
     8191                int64_t i64Delta   = pGip->aCPUs[iGipCpu].i64TSCDelta;
     8192                pReq->u.Out.idApic = pGip->aCPUs[iGipCpu].idApic;
     8193                pReq->u.Out.u64AdjustedTsc = ASMReadTSC();
     8194                ASMSetFlags(uFlags);
     8195
     8196                /*
     8197                 * If we're lucky we've got a delta, but no predicitions here
     8198                 * as this I/O control is normally only used when the TSC delta
     8199                 * is set to INT64_MAX.
     8200                 */
     8201                if (i64Delta != INT64_MAX)
     8202                {
     8203                    pReq->u.Out.u64AdjustedTsc -= i64Delta;
     8204                    rc = VINF_SUCCESS;
     8205                    break;
     8206                }
     8207
     8208                /* Give up after a few times. */
     8209                if (cTries >= 4)
     8210                {
     8211                    rc = VERR_INTERNAL_ERROR_3; /** @todo change to warning. */
     8212                    break;
     8213                }
     8214
     8215                /* Need to measure the delta an try again. */
     8216                rc = supdrvMeasureTscDeltaOne(pDevExt, iGipCpu);
     8217                Assert(pGip->aCPUs[iGipCpu].i64TSCDelta != INT64_MAX || RT_FAILURE_NP(rc));
     8218            }
     8219            else
     8220            {
     8221                /* This really shouldn't happen. */
     8222                AssertMsgFailed(("idCpu=%#x iCpuSet=%#x (%d)\n", RTMpCpuId(), iCpuSet, iCpuSet));
     8223                pReq->u.Out.idApic = ASMGetApicId();
     8224                pReq->u.Out.u64AdjustedTsc = ASMReadTSC();
     8225                ASMSetFlags(uFlags);
     8226                rc = VERR_INTERNAL_ERROR_5; /** @todo change to warning. */
     8227                break;
     8228            }
     8229        }
     8230    }
     8231    else
     8232    {
     8233        /*
     8234         * No delta to apply. Easy. Deal with preemption the lazy way.
     8235         */
     8236        RTCCUINTREG uFlags  = ASMIntDisableFlags();
     8237        int         iCpuSet = RTMpCpuIdToSetIndex(RTMpCpuId());
     8238        int         iGipCpu;
     8239        if (RT_LIKELY(   (unsigned)iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)
     8240                      && (iGipCpu = pGip->aiCpuFromCpuSetIdx[iCpuSet]) < pGip->cCpus ))
     8241            pReq->u.Out.idApic = pGip->aCPUs[iGipCpu].idApic;
     8242        else
     8243            pReq->u.Out.idApic = ASMGetApicId();
     8244        pReq->u.Out.u64AdjustedTsc = ASMReadTSC();
     8245        ASMSetFlags(uFlags);
     8246        rc = VINF_SUCCESS;
    81268247    }
    81278248
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