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.

Location:
trunk/src/VBox/HostDrivers/Support
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/Makefile.kmk

    r54046 r54224  
    4343  LIBRARIES += SUPR0
    4444 endif
     45endif
     46if !defined(VBOX_ONLY_BUILD) && defined(VBOX_WITH_RAW_MODE)
     47 LIBRARIES += SUPRC
    4548endif
    4649if  !defined(VBOX_ONLY_DOCS) \
     
    152155        SUPLibSem.cpp \
    153156        SUPLibTracerA.asm \
     157        SUPLibAll.cpp \
    154158        SUPR3HardenedIPRT.cpp \
    155159        SUPR3HardenedVerify.cpp \
     
    460464
    461465#
     466# SUPRC - The raw-mode context library.
     467#
     468SUPRC_TEMPLATE      = VBoxRc
     469SUPRC_SOURCES       = SUPLibAll.cpp
     470
     471
     472#
    462473# SUPR0IdcClient - The Ring-0 IDC client driver library.
    463474#
     
    507518        os2/SUPDrv-os2.cpp \
    508519        SUPDrv.c \
    509         SUPDrvSem.c
     520        SUPDrvSem.c \
     521        SUPLibAll.cpp
    510522
    511523endif # os2
     
    523535        $(PATH_SUB_CURRENT)/$(KBUILD_TARGET)/SUPDrv-$(KBUILD_TARGET).def \
    524536        SUPDrv.c \
    525         SUPDrvSem.c
     537        SUPDrvSem.c \
     538        SUPLibAll.cpp
    526539## @todo the SUPDrv-freebsd.def is most probably gonna break it and require build system hacking...
    527540
     
    644657        SUPDrv.c \
    645658        SUPDrvSem.c \
    646         SUPDrvTracer.cpp
     659        SUPDrvTracer.cpp \
     660        SUPLibAll.cpp
    647661 ifdef VBOX_WITH_NATIVE_DTRACE
    648662  VBoxDrv_SOURCES        += \
  • 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
  • trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h

    r54208 r54224  
    55
    66/*
    7  * Copyright (C) 2006-2014 Oracle Corporation
     7 * Copyright (C) 2006-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    213213 *
    214214 * @todo Pending work on next major version change:
    215  *          - (none).
     215 *          - Fix SUPTSCREAD padding (#if 0 -> #if 1).
    216216 */
    217217#define SUPDRV_IOC_VERSION                              0x001e0000
     
    15201520
    15211521/** @name SUP_IOCTL_TSC_READ
    1522  * Reads the TSC and TSC-delta atomically and returns the delta-adjusted TSC
    1523  * value.
     1522 * Reads the TSC and apply TSC-delta if applicable, determining the delta if
     1523 * necessary (i64TSCDelta = INT64_MAX).
     1524 *
     1525 * This latter function is the primary use case of this I/O control.  To call
     1526 * this I/O control, the client must first have mapped the GIP.
    15241527 *
    15251528 * @{
     
    15441547            uint16_t        idApic;
    15451548            /** Padding for future. */
     1549#if 0 /* Not correct for 32-bit gcc. */
     1550            uint16_t        auPadding[3 + 3*4];
     1551#else
    15461552            uint64_t        auPadding[3];
     1553#endif
    15471554        } Out;
    15481555    } u;
    15491556} SUPTSCREAD, *PSUPTSCREAD;
    15501557AssertCompileMemberAlignment(SUPTSCREAD, u, 8);
     1558#if 0  /* Not correct for 32-bit gcc. */
     1559AssertCompileSize(SUPTSCREAD, 6*4 + 5*8);
     1560#endif
    15511561/** @} */
    15521562
  • trunk/src/VBox/HostDrivers/Support/freebsd/Makefile

    r43435 r54224  
    55
    66#
    7 #
    8 # Copyright (C) 2006-2012 Oracle Corporation
     7# Copyright (C) 2006-2015 Oracle Corporation
    98#
    109# This file is part of VirtualBox Open Source Edition (OSE), as
     
    4039        SUPDrvSem.c \
    4140        SUPDrvTracer.c \
     41        SUPLibAll.c \
    4242
    4343# Include needed interface headers so they are created during build
  • trunk/src/VBox/HostDrivers/Support/freebsd/files_vboxdrv

    r53480 r54224  
    66
    77#
    8 # Copyright (C) 2007-2010 Oracle Corporation
     8# Copyright (C) 2007-2015 Oracle Corporation
    99#
    1010# This file is part of VirtualBox Open Source Edition (OSE), as
     
    9292    ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPDrvIOC.h=>SUPDrvIOC.h \
    9393    ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPDrvInternal.h=>SUPDrvInternal.h \
     94    ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPLibAll.cpp=>SUPLibAll.c \
    9495    ${PATH_ROOT}/src/VBox/Runtime/common/alloc/heapsimple.cpp=>alloc/heapsimple.c \
    9596    ${PATH_ROOT}/src/VBox/Runtime/common/alloc/alloc.cpp=>alloc/alloc.c \
  • trunk/src/VBox/HostDrivers/Support/linux/files_vboxdrv

    r53476 r54224  
    66
    77#
    8 # Copyright (C) 2007-2012 Oracle Corporation
     8# Copyright (C) 2007-2015 Oracle Corporation
    99#
    1010# This file is part of VirtualBox Open Source Edition (OSE), as
     
    8787    ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPDrvIOC.h=>SUPDrvIOC.h \
    8888    ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPDrvInternal.h=>SUPDrvInternal.h \
     89    ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPLibAll.cpp=>SUPLibAll.c \
    8990    ${PATH_ROOT}/src/VBox/Runtime/common/alloc/alloc.cpp=>common/alloc/alloc.c \
    9091    ${PATH_ROOT}/src/VBox/Runtime/common/alloc/heapsimple.cpp=>common/alloc/heapsimple.c \
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