VirtualBox

Ignore:
Timestamp:
Feb 17, 2015 7:24:45 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
98319
Message:

SUPDrv,GIP,TM: Combined fOsTscDeltasInSync and fTscDeltasRoughlyInSync into enmUseTscDelta and added fGetGipCpu. Bumped GIP and support driver versions.

File:
1 edited

Legend:

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

    r54224 r54252  
    124124/** The TSC-refinement interval in seconds. */
    125125#define GIP_TSC_REFINE_INTERVAL             5
    126 /** The TSC-delta threshold (in ticks) for whether it's worth applying them or
    127  *  not for performance reasons, see @bugref{6710} comment #124. */
    128 #define GIP_TSC_DELTA_APPLY_THRESHOLD       384
     126/** The TSC-delta threshold for the SUPGIPUSETSCDELTA_PRACTICALLY_ZERO rating */
     127#define GIP_TSC_DELTA_THRESHOLD_PRACTICALLY_ZERO    24
     128/** The TSC-delta threshold for the SUPGIPUSETSCDELTA_ROUGHLY_ZERO rating */
     129#define GIP_TSC_DELTA_THRESHOLD_ROUGHLY_ZERO        384
    129130
    130131AssertCompile(GIP_TSC_DELTA_PRIMER_LOOPS < GIP_TSC_DELTA_READ_TIME_LOOPS);
     
    163164static int                  supdrvIOCtl_LoggerSettings(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPLOGGERSETTINGS pReq);
    164165static int                  supdrvIOCtl_MsrProber(PSUPDRVDEVEXT pDevExt, PSUPMSRPROBER pReq);
    165 static int                  supdrvIOCtl_TscDeltaMeasure(PSUPDRVDEVEXT pDevExt, PSUPTSCDELTAMEASURE pReq);
     166static int                  supdrvIOCtl_TscDeltaMeasure(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPTSCDELTAMEASURE pReq);
    166167static int                  supdrvIOCtl_TscRead(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPTSCREAD pReq);
    167168static int                  supdrvGipCreate(PSUPDRVDEVEXT pDevExt);
    168169static void                 supdrvGipDestroy(PSUPDRVDEVEXT pDevExt);
    169 static DECLCALLBACK(void)   supdrvGipSyncTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick);
     170static DECLCALLBACK(void)   supdrvGipSyncAndInvariantTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick);
    170171static DECLCALLBACK(void)   supdrvGipAsyncTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick);
    171172static DECLCALLBACK(void)   supdrvGipMpEvent(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvUser);
     
    22522253            REQ_CHECK_SIZES(SUP_IOCTL_TSC_DELTA_MEASURE);
    22532254
    2254             pReqHdr->rc = supdrvIOCtl_TscDeltaMeasure(pDevExt, pReq);
     2255            pReqHdr->rc = supdrvIOCtl_TscDeltaMeasure(pDevExt, pSession, pReq);
    22552256            return 0;
    22562257        }
     
    40314032
    40324033/**
     4034 * State structure for supdrvGipDetectGetGipCpuCallback.
     4035 */
     4036typedef struct SUPDRVGIPDETECTGETCPU
     4037{
     4038    /** Bitmap of APIC IDs that has been seen (initialized to zero).
     4039     *  Used to detect duplicate APIC IDs (paranoia). */
     4040    uint8_t volatile    bmApicId[256 / 8];
     4041    /** Mask of supported GIP CPU getter methods (SUPGIPGETCPU_XXX) (all bits set
     4042     *  initially). The callback clears the methods not detected. */
     4043    uint32_t volatile   fSupported;
     4044    /** The first callback detecting any kind of range issues (initializsed to
     4045     * NIL_RTCPUID). */
     4046    RTCPUID volatile    idCpuProblem;
     4047} SUPDRVGIPDETECTGETCPU;
     4048/** Pointer to state structure for supdrvGipDetectGetGipCpuCallback. */
     4049typedef SUPDRVGIPDETECTGETCPU *PSUPDRVGIPDETECTGETCPU;
     4050
     4051
     4052/**
     4053 * Checks for alternative ways of getting the CPU ID.
     4054 *
     4055 * This also checks the APIC ID, CPU ID and CPU set index values against the
     4056 * GIP tables.
     4057 *
     4058 * @param   idCpu            The CPU ID. Unused - we have to use the APIC ID.
     4059 * @param   pvUser1          Pointer to the state structure.
     4060 * @param   pvUser2          Pointer to the GIP.
     4061 */
     4062static DECLCALLBACK(void) supdrvGipDetectGetGipCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2)
     4063{
     4064    PSUPDRVGIPDETECTGETCPU  pState = (PSUPDRVGIPDETECTGETCPU)pvUser1;
     4065    PSUPGLOBALINFOPAGE      pGip   = (PSUPGLOBALINFOPAGE)pvUser2;
     4066    uint32_t                fSupported = 0;
     4067    uint16_t                idApic;
     4068    int                     iCpuSet;
     4069
     4070    AssertMsg(idCpu == RTMpCpuId(), ("idCpu=%#x RTMpCpuId()=%#x\n", idCpu, RTMpCpuId())); /* paranoia^3 */
     4071
     4072    /*
     4073     * Check that the CPU ID and CPU set index are interchangable.
     4074     */
     4075    iCpuSet = RTMpCpuIdToSetIndex(idCpu);
     4076    if ((RTCPUID)iCpuSet == idCpu)
     4077    {
     4078        AssertCompile(RT_IS_POWER_OF_TWO(RTCPUSET_MAX_CPUS));
     4079        if (   iCpuSet >= 0
     4080            && iCpuSet < RTCPUSET_MAX_CPUS
     4081            && RT_IS_POWER_OF_TWO(RTCPUSET_MAX_CPUS))
     4082        {
     4083            /*
     4084             * Check whether the IDTR.LIMIT contains a CPU number.
     4085             */
     4086#ifdef RT_ARCH_X86
     4087            uint16_t const  cbIdt = sizeof(X86DESC64SYSTEM);
     4088#else
     4089            uint16_t const  cbIdt = sizeof(X86DESCGATE);
     4090#endif
     4091            RTIDTR          Idtr;
     4092            ASMGetIDTR(&Idtr);
     4093            if (Idtr.cbIdt >= cbIdt)
     4094            {
     4095                uint32_t uTmp = Idtr.cbIdt - cbIdt;
     4096                uTmp &= RTCPUSET_MAX_CPUS - 1;
     4097                if (uTmp == idCpu)
     4098                {
     4099                    RTIDTR Idtr2;
     4100                    ASMGetIDTR(&Idtr2);
     4101                    if (Idtr2.cbIdt == Idtr.cbIdt)
     4102                        fSupported |= SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS;
     4103                }
     4104            }
     4105
     4106            /*
     4107             * Check whether RDTSCP is an option.
     4108             */
     4109            if (ASMHasCpuId())
     4110            {
     4111                if (   ASMIsValidExtRange(ASMCpuId_EAX(UINT32_C(0x80000000)))
     4112                    && (ASMCpuId_EDX(UINT32_C(0x80000001)) & X86_CPUID_EXT_FEATURE_EDX_RDTSCP) )
     4113                {
     4114                    uint32_t uAux;
     4115                    ASMReadTscWithAux(&uAux);
     4116                    if ((uAux & (RTCPUSET_MAX_CPUS - 1)) == idCpu)
     4117                    {
     4118                        ASMNopPause();
     4119                        ASMReadTscWithAux(&uAux);
     4120                        if ((uAux & (RTCPUSET_MAX_CPUS - 1)) == idCpu)
     4121                            fSupported |= SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS;
     4122                    }
     4123                }
     4124            }
     4125        }
     4126    }
     4127
     4128    /*
     4129     * Check that the APIC ID is unique.
     4130     */
     4131    idApic = ASMGetApicId();
     4132    if (RT_LIKELY(   idApic < RT_ELEMENTS(pGip->aiCpuFromApicId)
     4133                  && !ASMAtomicBitTestAndSet(pState->bmApicId, idApic)))
     4134        fSupported |= SUPGIPGETCPU_APIC_ID;
     4135    else
     4136    {
     4137        AssertCompile(sizeof(pState->bmApicId) * 8 == RT_ELEMENTS(pGip->aiCpuFromApicId));
     4138        ASMAtomicCmpXchgU32(&pState->idCpuProblem, idCpu, NIL_RTCPUID);
     4139        LogRel(("supdrvGipDetectGetGipCpuCallback: idCpu=%#x iCpuSet=%d idApic=%#x - duplicate APIC ID.\n",
     4140                idCpu, iCpuSet, idApic));
     4141    }
     4142
     4143    /*
     4144     * Check that the iCpuSet is within the expected range.
     4145     */
     4146    if (RT_UNLIKELY(   iCpuSet < 0
     4147                    || iCpuSet >= RTCPUSET_MAX_CPUS
     4148                    || iCpuSet >= RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)))
     4149    {
     4150        ASMAtomicCmpXchgU32(&pState->idCpuProblem, idCpu, NIL_RTCPUID);
     4151        LogRel(("supdrvGipDetectGetGipCpuCallback: idCpu=%#x iCpuSet=%d idApic=%#x - CPU set index is out of range.\n",
     4152                idCpu, iCpuSet, idApic));
     4153    }
     4154    else
     4155    {
     4156        RTCPUID idCpu2 = RTMpCpuIdFromSetIndex(iCpuSet);
     4157        if (RT_UNLIKELY(idCpu2 != idCpu))
     4158        {
     4159            ASMAtomicCmpXchgU32(&pState->idCpuProblem, idCpu, NIL_RTCPUID);
     4160            LogRel(("supdrvGipDetectGetGipCpuCallback: idCpu=%#x iCpuSet=%d idApic=%#x - CPU id/index roundtrip problem: %#x\n",
     4161                    idCpu, iCpuSet, idApic, idCpu2));
     4162        }
     4163    }
     4164
     4165    /*
     4166     * Update the supported feature mask before we return.
     4167     */
     4168    ASMAtomicAndU32(&pState->fSupported, fSupported);
     4169
     4170    NOREF(pvUser2);
     4171}
     4172
     4173
     4174/**
    40334175 * Increase the timer freqency on hosts where this is possible (NT).
    40344176 *
     
    41384280                uint64_t u64NanoTS;
    41394281
     4282                /*
     4283                 * GIP starts/resumes updating again.  On windows we bump the
     4284                 * host timer frequency to make sure we don't get stuck in guest
     4285                 * mode and to get better timer (and possibly clock) accuracy.
     4286                 */
    41404287                LogFlow(("SUPR0GipMap: Resumes GIP updating\n"));
    41414288
    41424289                supdrvGipRequestHigherTimerFrequencyFromSystem(pDevExt);
    41434290
     4291                /*
     4292                 * document me
     4293                 */
    41444294                if (pGipR0->aCPUs[0].u32TransactionId != 2 /* not the first time */)
    41454295                {
     
    41524302                }
    41534303
     4304                /*
     4305                 * document me
     4306                 */
    41544307                u64NanoTS = RTTimeSystemNanoTS() - pGipR0->u32UpdateIntervalNS;
    41554308                if (   pGipR0->u32Mode == SUPGIPMODE_INVARIANT_TSC
     
    41604313                    RTMpOnAll(supdrvGipReInitCpuCallback, pGipR0, &u64NanoTS);
    41614314
     4315                /*
     4316                 * Detect alternative ways to figure the CPU ID in ring-3 and
     4317                 * raw-mode context.  Check the sanity of the APIC IDs, CPU IDs,
     4318                 * and CPU set indexes while we're at it.
     4319                 */
     4320                if (RT_SUCCESS(rc))
     4321                {
     4322                    SUPDRVGIPDETECTGETCPU DetectState;
     4323                    RT_ZERO(DetectState.bmApicId);
     4324                    DetectState.fSupported   = UINT32_MAX;
     4325                    DetectState.idCpuProblem = NIL_RTCPUID;
     4326                    rc = RTMpOnAll(supdrvGipDetectGetGipCpuCallback, &DetectState, pGipR0);
     4327                    if (DetectState.idCpuProblem == NIL_RTCPUID)
     4328                    {
     4329                        if (   DetectState.fSupported != UINT32_MAX
     4330                            && DetectState.fSupported != 0)
     4331                        {
     4332                            if (pGipR0->fGetGipCpu != DetectState.fSupported)
     4333                            {
     4334                                pGipR0->fGetGipCpu = DetectState.fSupported;
     4335                                LogRel(("SUPR0GipMap: fGetGipCpu=%#x\n", DetectState.fSupported));
     4336                            }
     4337                        }
     4338                        else
     4339                        {
     4340                            LogRel(("SUPR0GipMap: No supported ways of getting the APIC ID or CPU number in ring-3! (%#x)\n",
     4341                                    DetectState.fSupported));
     4342                            rc = VERR_UNSUPPORTED_CPU;
     4343                        }
     4344                    }
     4345                    else
     4346                    {
     4347                        LogRel(("SUPR0GipMap: APIC ID, CPU ID or CPU set index problem detected on CPU #%u (%#x)!\n",
     4348                                DetectState.idCpuProblem, DetectState.idCpuProblem));
     4349                        rc = VERR_INVALID_CPU_ID;
     4350                    }
     4351                }
     4352
     4353                /*
     4354                 * Start the GIP timer if all is well..
     4355                 */
     4356                if (RT_SUCCESS(rc))
     4357                {
    41624358#ifndef DO_NOT_START_GIP
    4163                 rc = RTTimerStart(pDevExt->pGipTimer, 0 /* fire ASAP */); AssertRC(rc);
     4359                    rc = RTTimerStart(pDevExt->pGipTimer, 0 /* fire ASAP */); AssertRC(rc);
    41644360#endif
    4165                 rc = VINF_SUCCESS;
     4361                    rc = VINF_SUCCESS;
     4362                }
     4363
     4364                /*
     4365                 * Bail out on error.
     4366                 */
     4367                if (RT_FAILURE(rc))
     4368                {
     4369                    LogRel(("SUPR0GipMap: failed rc=%Rrc\n", rc));
     4370                    pDevExt->cGipUsers = 0;
     4371                    pSession->fGipReferenced = 0;
     4372                    if (pSession->GipMapObjR3 != NIL_RTR0MEMOBJ)
     4373                    {
     4374                        int rc2 = RTR0MemObjFree(pSession->GipMapObjR3, false); AssertRC(rc2);
     4375                        if (RT_SUCCESS(rc2))
     4376                            pSession->GipMapObjR3 = NIL_RTR0MEMOBJ;
     4377                    }
     4378                    HCPhys = NIL_RTHCPHYS;
     4379                    pGipR3 = NIL_RTR3PTR;
     4380                }
    41664381            }
    41674382        }
     
    57815996}
    57825997
    5783 
    57845998#ifdef SUPDRV_USE_TSC_DELTA_THREAD
     5999
    57856000/**
    57866001 * Switches the TSC-delta measurement thread into the butchered state.
     
    60356250static int supdrvTscDeltaThreadInit(PSUPDRVDEVEXT pDevExt)
    60366251{
    6037     Assert(GIP_ARE_TSC_DELTAS_APPLICABLE(pDevExt->pGip));
     6252    Assert(pDevExt->pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED);
    60386253
    60396254    int rc = RTSpinlockCreate(&pDevExt->hTscDeltaSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE, "VBoxTscSpnLck");
     
    61366351    return VERR_TIMEOUT;
    61376352}
     6353
    61386354#endif /* SUPDRV_USE_TSC_DELTA_THREAD */
    6139 
    61406355
    61416356/**
     
    61646379    AssertPtr(puTsc);
    61656380    AssertPtr(pGip);
    6166     Assert(GIP_ARE_TSC_DELTAS_APPLICABLE(pGip));
     6381    Assert(pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED);
    61676382
    61686383    /*
     
    62846499        ASMSetFlags(uFlags);
    62856500
    6286         if (GIP_ARE_TSC_DELTAS_APPLICABLE(pGip))
     6501        if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_PRACTICALLY_ZERO)
    62876502        {
    62886503            int rc;
     
    63626577    u64NanoTS = RTTimeSystemNanoTS();
    63636578    ASMSetFlags(uFlags);
    6364     if (GIP_ARE_TSC_DELTAS_APPLICABLE(pGip))
     6579    if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_PRACTICALLY_ZERO)
    63656580        supdrvTscDeltaApply(pGip, &u64Tsc, idApic, &fDeltaApplied);
    63666581    u64DeltaNanoTS = u64NanoTS - pDevExt->u64NanoTSAnchor;
     
    63816596    else
    63826597    {
    6383 #if 1
    63846598        RTUINT128U CpuHz, Tmp, Divisor;
    63856599        CpuHz.s.Lo = CpuHz.s.Hi = 0;
     
    63876601        RTUInt128Div(&CpuHz, &Tmp, RTUInt128AssignU64(&Divisor, u64DeltaNanoTS));
    63886602        pGip->u64CpuHz = CpuHz.s.Lo;
    6389 #else
    6390         /** @todo remove later */
    6391         /* Try not to lose precision, the larger the interval the more likely we overflow. */
    6392         if (   u64DeltaTsc < UINT64_MAX / RT_NS_100MS
    6393             && u64DeltaNanoTS / 10 < UINT32_MAX)
    6394             pGip->u64CpuHz = ASMMultU64ByU32DivByU32(u64DeltaTsc, RT_NS_100MS, (uint32_t)(u64DeltaNanoTS / 10));
    6395         else if (   u64DeltaTsc < UINT64_MAX / RT_NS_10MS
    6396                  && u64DeltaNanoTS / 100 < UINT32_MAX)
    6397             pGip->u64CpuHz = ASMMultU64ByU32DivByU32(u64DeltaTsc, RT_NS_10MS, (uint32_t)(u64DeltaNanoTS / 100));
    6398         else if (   u64DeltaTsc < UINT64_MAX / RT_NS_1MS
    6399                  && u64DeltaNanoTS / 1000 < UINT32_MAX)
    6400             pGip->u64CpuHz = ASMMultU64ByU32DivByU32(u64DeltaTsc, RT_NS_1MS, (uint32_t)(u64DeltaNanoTS / 1000));
    6401         else /* Screw it. */
    6402             pGip->u64CpuHz = u64DeltaTsc / (u64DeltaNanoTS / RT_NS_1SEC_64);
    6403 #endif
    64046603    }
    64056604
     
    64286627    Assert(pDevExt->pGip);
    64296628
     6629    /*
     6630     * <Insert missing comment [it's not "Validate.", I think...]>
     6631     */
    64306632    pGip = pDevExt->pGip;
    64316633    u64NanoTS = RTTimeSystemNanoTS();
     
    64376639    pDevExt->u64NanoTSAnchor = RTTimeSystemNanoTS();
    64386640    ASMSetFlags(uFlags);
    6439     if (GIP_ARE_TSC_DELTAS_APPLICABLE(pGip))
     6641    if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_PRACTICALLY_ZERO)
    64406642        supdrvTscDeltaApply(pGip, &pDevExt->u64TscAnchor, idApic, &fDeltaApplied);
    64416643
    64426644#ifdef SUPDRV_USE_TSC_DELTA_THREAD
     6645    /*
     6646     * <Explain yourself>
     6647     */
     6648    /** @todo r=bird: This is (and was) bogus on systems where we don't need to
     6649     *        apply any delta (not used on windows doesn't stick without comments).
     6650     *        What is the logic you want here exactly? */
    64436651    if (   pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC
    64446652        && !fDeltaApplied)
     
    65416749    supdrvGipInit(pDevExt, pGip, HCPhysGip, RTTimeSystemNanoTS(), RT_NS_1SEC / u32Interval /*=Hz*/, u32Interval, cCpus);
    65426750
    6543     if (RT_UNLIKELY(   pGip->fOsTscDeltasInSync
     6751    if (RT_UNLIKELY(   pGip->enmUseTscDelta == SUPGIPUSETSCDELTA_ZERO_CLAIMED
    65446752                    && pGip->u32Mode == SUPGIPMODE_ASYNC_TSC
    65456753                    && !supdrvOSGetForcedAsyncTscMode(pDevExt)))
     
    65516759
    65526760#ifdef SUPDRV_USE_TSC_DELTA_THREAD
    6553     if (GIP_ARE_TSC_DELTAS_APPLICABLE(pGip))
     6761    if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED)
    65546762    {
    65556763        /* Initialize TSC-delta measurement thread before executing any Mp event callbacks. */
     
    65676775                uint16_t iCpu;
    65686776#ifndef SUPDRV_USE_TSC_DELTA_THREAD
    6569                 if (GIP_ARE_TSC_DELTAS_APPLICABLE(pGip))
     6777                if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED)
    65706778                {
    65716779                    /*
     
    66086816                        }
    66096817                        if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC)
    6610                             rc = RTTimerCreateEx(&pDevExt->pGipTimer, u32Interval, 0 /* fFlags */, supdrvGipSyncTimer, pDevExt);
     6818                            rc = RTTimerCreateEx(&pDevExt->pGipTimer, u32Interval, 0 /* fFlags */,
     6819                                                 supdrvGipSyncAndInvariantTimer, pDevExt);
    66116820                        if (RT_SUCCESS(rc))
    66126821                        {
     
    67226931
    67236932/**
    6724  * Timer callback function sync GIP mode.
     6933 * Timer callback function for the sync and invariant  GIP modes.
     6934 * 
    67256935 * @param   pTimer      The timer.
    67266936 * @param   pvUser      Opaque pointer to the device extension.
    67276937 * @param   iTick       The timer tick.
    67286938 */
    6729 static DECLCALLBACK(void) supdrvGipSyncTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
     6939static DECLCALLBACK(void) supdrvGipSyncAndInvariantTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
    67306940{
    67316941    RTCCUINTREG        uFlags;
     
    67396949    u64NanoTS = RTTimeSystemNanoTS();
    67406950
    6741     if (GIP_ARE_TSC_DELTAS_APPLICABLE(pGip))
     6951    if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_PRACTICALLY_ZERO)
    67426952    {
    67436953        /*
     
    67476957         * rescheduling the tick to be delivered on the right CPU or missing the tick entirely.
    67486958         *
    6749          * The likely hood of this happening is really low. On Windows, Linux timers
    6750          * fire on the CPU they were registered/started on. Darwin, Solaris need verification.
     6959         * The likely hood of this happening is really low. On Windows, Linux, and Solaris
     6960         * timers fire on the CPU they were registered/started on.  Darwin timers doesn't
     6961         * necessarily (they are high priority threads waiting).
    67516962         */
    67526963        Assert(!ASMIntAreEnabled());
     
    68847095     * update the state and it'll get serviced when the thread's listening interval times out.
    68857096     */
    6886     if (GIP_ARE_TSC_DELTAS_APPLICABLE(pGip))
     7097    if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED)
    68877098    {
    68887099        RTSpinlockAcquire(pDevExt->hTscDeltaSpinlock);
     
    69437154
    69447155    /* Reset the TSC delta, we will recalculate it lazily. */
    6945     if (GIP_ARE_TSC_DELTAS_APPLICABLE(pGip))
     7156    if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED)
    69467157        ASMAtomicWriteS64(&pGip->aCPUs[i].i64TSCDelta, INT64_MAX);
    69477158
     
    71727383
    71737384                while (ASMAtomicReadU32(&pDevExt->pTscDeltaSync->u) == GIP_TSC_DELTA_SYNC_START)
    7174                     ;
     7385                { /* nothing */ }
    71757386
    71767387                do
     
    71837394
    71847395                while (ASMAtomicReadU32(&pDevExt->pTscDeltaSync->u) != GIP_TSC_DELTA_SYNC_WORKER_DONE)
    7185                     ;
     7396                { /* nothing */ }
    71867397
    71877398                if (i > GIP_TSC_DELTA_PRIMER_LOOPS + GIP_TSC_DELTA_READ_TIME_LOOPS)
     
    72097420                ASMAtomicReadU64(&pGipCpuMaster->u64TSCSample);     /* Warm the cache line. */
    72107421                while (ASMAtomicReadU32(&pDevExt->pTscDeltaSync->u) != GIP_TSC_DELTA_SYNC_START)
    7211                     ;
     7422                { /* nothing */ }
    72127423                Assert(pGipCpuMaster->u64TSCSample == GIP_TSC_DELTA_RSVD);
    72137424                ASMAtomicWriteU32(&pDevExt->pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_WORKER_READY);
     
    73077518    pGipCpuWorker = &pGip->aCPUs[idxWorker];
    73087519
    7309     Assert(GIP_ARE_TSC_DELTAS_APPLICABLE(pGip));
     7520    Assert(pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED);
    73107521
    73117522    if (pGipCpuWorker->idCpu == idMaster)
     
    73167527
    73177528    /* Set the master TSC as the initiator. */
    7318     while (ASMAtomicCmpXchgU32(&pDevExt->idTscDeltaInitiator, idMaster, NIL_RTCPUID) == false)
     7529    while (!ASMAtomicCmpXchgU32(&pDevExt->idTscDeltaInitiator, idMaster, NIL_RTCPUID))
    73197530    {
    73207531        /*
     
    73337544        if (RT_SUCCESS(rc))
    73347545        {
    7335             if (RT_UNLIKELY(pGipCpuWorker->i64TSCDelta == INT64_MAX))
     7546            if (RT_LIKELY(pGipCpuWorker->i64TSCDelta != INT64_MAX))
     7547            {
     7548                /*
     7549                 * Work the TSC delta applicability rating.  It starts
     7550                 * optimistic in supdrvGipInit, we downgrade it here.
     7551                 */
     7552                SUPGIPUSETSCDELTA enmRating;
     7553                if (   pGipCpuWorker->i64TSCDelta >  GIP_TSC_DELTA_THRESHOLD_ROUGHLY_ZERO
     7554                    || pGipCpuWorker->i64TSCDelta < -GIP_TSC_DELTA_THRESHOLD_ROUGHLY_ZERO)
     7555                    enmRating = SUPGIPUSETSCDELTA_NOT_ZERO;
     7556                else if (   pGipCpuWorker->i64TSCDelta >  GIP_TSC_DELTA_THRESHOLD_PRACTICALLY_ZERO
     7557                         || pGipCpuWorker->i64TSCDelta < -GIP_TSC_DELTA_THRESHOLD_PRACTICALLY_ZERO)
     7558                    enmRating = SUPGIPUSETSCDELTA_ROUGHLY_ZERO;
     7559                else
     7560                    enmRating = SUPGIPUSETSCDELTA_PRACTICALLY_ZERO;
     7561                if (pGip->enmUseTscDelta < enmRating)
     7562                {
     7563                    AssertCompile(sizeof(pGip->enmUseTscDelta) == sizeof(uint32_t));
     7564                    ASMAtomicWriteU32((uint32_t volatile *)&pGip->enmUseTscDelta, enmRating);
     7565                }
     7566            }
     7567            else
    73367568                rc = VERR_SUPDRV_TSC_DELTA_MEASUREMENT_FAILED;
    7337             else if (   pGipCpuWorker->i64TSCDelta >  GIP_TSC_DELTA_APPLY_THRESHOLD
    7338                      || pGipCpuWorker->i64TSCDelta < -GIP_TSC_DELTA_APPLY_THRESHOLD)
    7339             {
    7340                 pGip->fTscDeltasRoughlyInSync = false;
    7341             }
    73427569        }
    73437570    }
     
    73737600    uint32_t   cOnlineCpus    = pGip->cOnlineCpus;
    73747601
    7375     Assert(GIP_ARE_TSC_DELTAS_APPLICABLE(pGip));
     7602    Assert(pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED);
    73767603
    73777604    /*
     
    76217848    pCpu->u64TSC             = ASMReadTSC();
    76227849    pCpu->u64TSCSample       = GIP_TSC_DELTA_RSVD;
    7623     pCpu->i64TSCDelta        = GIP_ARE_TSC_DELTAS_APPLICABLE(pGip) ? INT64_MAX : 0;
     7850    pCpu->i64TSCDelta        = pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED ? INT64_MAX : 0;
    76247851
    76257852    ASMAtomicWriteSize(&pCpu->enmState, SUPGIPCPUSTATE_INVALID);
     
    76747901    memset(pGip, 0, cbGip);
    76757902
    7676     /*
    7677      * Record whether the host OS has already normalized inter-CPU deltas for the hardware TSC.
    7678      * We only bother with TSC-deltas on invariant CPUs for now.
    7679      */
    7680     pGip->fOsTscDeltasInSync = supdrvIsInvariantTsc() && supdrvOSAreTscDeltasInSync();
    7681 
    7682     pGip->fTscDeltasRoughlyInSync = true;
    76837903    pGip->u32Magic                = SUPGLOBALINFOPAGE_MAGIC;
    76847904    pGip->u32Version              = SUPGLOBALINFOPAGE_VERSION;
    76857905    pGip->u32Mode                 = supdrvGipDetermineTscMode(pDevExt);
     7906    if (   pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC
     7907        /*|| pGip->u32Mode == SUPGIPMODE_SYNC_TSC */)
     7908        pGip->enmUseTscDelta      = supdrvIsInvariantTsc() && supdrvOSAreTscDeltasInSync() /* Allow OS override (windows). */
     7909                                  ? SUPGIPUSETSCDELTA_ZERO_CLAIMED : SUPGIPUSETSCDELTA_PRACTICALLY_ZERO /* downgrade later */;
     7910    else
     7911        pGip->enmUseTscDelta      = SUPGIPUSETSCDELTA_NOT_APPLICABLE;
    76867912    pGip->cCpus                   = (uint16_t)cCpus;
    76877913    pGip->cPages                  = (uint16_t)(cbGip / PAGE_SIZE);
    76887914    pGip->u32UpdateHz             = uUpdateHz;
    76897915    pGip->u32UpdateIntervalNS     = uUpdateIntervalNS;
     7916    pGip->fGetGipCpu              = SUPGIPGETCPU_APIC_ID;
    76907917    RTCpuSetEmpty(&pGip->OnlineCpuSet);
    76917918    RTCpuSetEmpty(&pGip->PresentCpuSet);
     
    76997926    for (i = 0; i < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx); i++)
    77007927        pGip->aiCpuFromCpuSetIdx[i] = UINT16_MAX;
    7701 
    77027928    for (i = 0; i < cCpus; i++)
    77037929        supdrvGipInitCpu(pDevExt, pGip, &pGip->aCPUs[i], u64NanoTS);
     
    80668292 *
    80678293 * @returns VBox status code.
    8068  * @param   pDevExt             Pointer to the device instance data.
    8069  * @param   pReq                Pointer to the TSC-delta measurement request.
    8070  */
    8071 static int supdrvIOCtl_TscDeltaMeasure(PSUPDRVDEVEXT pDevExt, PSUPTSCDELTAMEASURE pReq)
     8294 * @param   pDevExt         Pointer to the device instance data.
     8295 * @param   pSession        The support driver session.
     8296 * @param   pReq            Pointer to the TSC-delta measurement request.
     8297 */
     8298static int supdrvIOCtl_TscDeltaMeasure(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPTSCDELTAMEASURE pReq)
    80728299{
    80738300    PSUPGLOBALINFOPAGE pGip;
    80748301    RTCPUID            idCpuWorker;
    8075     int                rc = VERR_CPU_NOT_FOUND;
     8302    int                rc;
    80768303    int16_t            cTries;
    80778304    RTMSINTERVAL       cMsWaitRetry;
     
    80818308     * Validate.
    80828309     */
    8083     AssertReturn(pDevExt, VERR_INVALID_PARAMETER);
    8084     AssertReturn(pReq, VERR_INVALID_PARAMETER);
    8085     AssertReturn(pDevExt->pGip, VERR_INVALID_PARAMETER);
     8310    AssertPtr(pDevExt); AssertPtr(pSession); AssertPtr(pReq); /* paranoia^2 */
     8311    if (pSession->GipMapObjR3 == NIL_RTR0MEMOBJ)
     8312        return VERR_WRONG_ORDER;
     8313    pGip = pDevExt->pGip;
     8314    AssertReturn(pGip, VERR_INTERNAL_ERROR_2);
     8315
    80868316    idCpuWorker = pReq->u.In.idCpu;
    80878317    if (idCpuWorker == NIL_RTCPUID)
    80888318        return VERR_INVALID_CPU_ID;
    8089 
    80908319    cTries       = RT_MAX(pReq->u.In.cRetries + 1, 10);
    80918320    cMsWaitRetry = RT_MAX(pReq->u.In.cMsWaitRetry, 5);
     8321
     8322    /*
     8323     * The request is a noop if the TSC delta isn't being used.
     8324     */
    80928325    pGip = pDevExt->pGip;
    8093 
    8094     if (!GIP_ARE_TSC_DELTAS_APPLICABLE(pGip))
     8326    if (pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ZERO_CLAIMED)
    80958327        return VINF_SUCCESS;
    80968328
     8329    rc = VERR_CPU_NOT_FOUND;
    80978330    for (iCpu = 0; iCpu < pGip->cCpus; iCpu++)
    80988331    {
     
    81748407     * upset if the GIP is some different mode.
    81758408     */
    8176     if (GIP_ARE_TSC_DELTAS_APPLICABLE(pGip))
     8409    if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED)
    81778410    {
    81788411        uint32_t cTries = 0;
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