VirtualBox

Changeset 54252 in vbox


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.

Location:
trunk
Files:
8 edited

Legend:

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

    r54224 r54252  
    284284
    285285
     286/**
     287 * The rules concerning the applicability of SUPGIPCPU::i64TscDelta.
     288 */
     289typedef enum SUPGIPUSETSCDELTA
     290{
     291    /** Value for SUPGIPMODE_ASYNC_TSC. */
     292    SUPGIPUSETSCDELTA_NOT_APPLICABLE = 0,
     293    /** The OS specific part of SUPDrv (or the user) claims the TSC is as
     294     * good as zero. */
     295    SUPGIPUSETSCDELTA_ZERO_CLAIMED,
     296    /** The differences in RDTSC output between the CPUs/cores/threads should
     297     * be considered zero for all practical purposes. */
     298    SUPGIPUSETSCDELTA_PRACTICALLY_ZERO,
     299    /** The differences in RDTSC output between the CPUs/cores/threads are a few
     300     * hundred ticks or less.  (Probably not worth calling ASMGetApicId two times
     301     * just to apply deltas.) */
     302    SUPGIPUSETSCDELTA_ROUGHLY_ZERO,
     303    /** Significant differences in RDTSC output between the CPUs/cores/threads,
     304     * deltas must be applied. */
     305    SUPGIPUSETSCDELTA_NOT_ZERO,
     306    /** End of valid values (exclusive). */
     307    SUPGIPUSETSCDELTA_END,
     308    /** Make sure the type is 32-bit sized. */
     309    SUPGIPUSETSCDELTA_32BIT_HACK = 0x7fffffff
     310} SUPGIPUSETSCDELTA;
     311
     312
     313/** @name SUPGIPGETCPU_XXX - methods that aCPUs can be indexed.
     314 * @{
     315 */
     316/** Use ASMGetApicId (or equivalent) and translate the result via
     317 *  aiCpuFromApicId. */
     318#define SUPGIPGETCPU_APIC_ID                        RT_BIT_32(0)
     319/** Use RDTSCP and translate the first RTCPUSET_MAX_CPUS of ECX via
     320 * aiCpuFromCpuSetIdx.
     321 *
     322 * Linux stores the RTMpCpuId() value in ECX[11:0] and NUMA node number in
     323 * ECX[12:31].  Solaris only stores RTMpCpuId() in ECX.  On both systems
     324 * RTMpCpuId() == RTMpCpuIdToSetIndex(RTMpCpuId()).  RTCPUSET_MAX_CPUS is
     325 * currently 64, 256 or 1024 in size, which lower than
     326 * 4096, so there shouldn't be any range issues. */
     327#define SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS       RT_BIT_32(1)
     328/** Subtract the max IDT size from IDTR.LIMIT, extract the
     329 * first RTCPUSET_MAX_CPUS and translate it via aiCpuFromCpuSetIdx.
     330 *
     331 * Darwin stores the RTMpCpuId() (== RTMpCpuIdToSetIndex(RTMpCpuId()))
     332 * value in the IDT limit.  The masking is a precaution against what linux
     333 * does with RDTSCP. */
     334#define SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS   RT_BIT_32(2)
     335/* Linux also offers information via selector 0x78, but we'll settle for
     336   RDTSCP for now. */
     337/** @} */
     338
    286339
    287340/**
     
    329382    /** The max CPU ID (RTMpGetMaxCpuId). */
    330383    RTCPUID             idCpuMax;
    331     /** Whether the host OS has already normalized the hardware TSC deltas across
    332      *  CPUs. */
    333     bool                fOsTscDeltasInSync;
    334     /** Whether the TSC deltas are small enough to not bother applying. */
    335     bool                fTscDeltasRoughlyInSync;
    336     uint8_t             au8Padding0[2];
     384    /** The applicability of SUPGIPCPU::i64TscDelta. */
     385    SUPGIPUSETSCDELTA   enmUseTscDelta;
     386    /** Mask of SUPGIPGETCPU_XXX values that indicates different ways that aCPU
     387     * can be accessed from ring-3 and raw-mode context. */
     388    uint32_t            fGetGipCpu;
    337389
    338390    /** Padding / reserved space for future data. */
    339     uint32_t            au32Padding1[26];
     391    uint32_t            au32Padding1[25];
    340392
    341393    /** Table indexed by the CPU APIC ID to get the CPU table index. */
     
    370422 * Upper 16 bits is the major version. Major version is only changed with
    371423 * incompatible changes in the GIP. */
    372 #define SUPGLOBALINFOPAGE_VERSION   0x00050000
     424#define SUPGLOBALINFOPAGE_VERSION   0x00060000
    373425
    374426/**
     
    436488
    437489/** Whether the application of TSC-deltas is required. */
    438 #define GIP_ARE_TSC_DELTAS_APPLICABLE(a_pGip) \
    439     ((a_pGip)->u32Mode == SUPGIPMODE_INVARIANT_TSC && !((a_pGip)->fOsTscDeltasInSync))
     490#define GIP_ARE_TSC_DELTAS_APPLICABLE(a_pGip)  ((a_pGip)->enmUseTscDelta > SUPGIPUSETSCDELTA_PRACTICALLY_ZERO)
    440491
    441492
     
    15591610DECLINLINE(uint64_t) SUPReadTsc(void)
    15601611{
    1561     if (    GIP_ARE_TSC_DELTAS_APPLICABLE(g_pSUPGlobalInfoPage)
    1562         && !g_pSUPGlobalInfoPage->fTscDeltasRoughlyInSync)
     1612    if (g_pSUPGlobalInfoPage->enmUseTscDelta > SUPGIPUSETSCDELTA_ROUGHLY_ZERO)
    15631613        return SUPReadTscWithDelta();
    15641614    return ASMReadTSC();
  • TabularUnified trunk/include/VBox/sup.mac

    r54214 r54252  
    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
     
    4848endstruc
    4949
     50%define SUPGIPUSETSCDELTA_NOT_APPLICABLE        0
     51%define SUPGIPUSETSCDELTA_ZERO_CLAIMED          1
     52%define SUPGIPUSETSCDELTA_PRACTICALLY_ZERO      2
     53%define SUPGIPUSETSCDELTA_ROUGHLY_ZERO          3
     54%define SUPGIPUSETSCDELTA_NOT_ZERO              4
     55
     56%define SUPGIPGETCPU_APIC_ID                        1
     57%define SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS       2
     58%define SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS   4
     59
     60
    5061%define SUPGLOBALINFOPAGE_MAGIC 0x19590106
    5162struc SUPGLOBALINFOPAGE
     
    6778    .u16Padding0                resw 1
    6879    .idCpuMax                   resd 1
    69     .fOsTscDeltasInSync         resb 1
    70     .fTscDeltasRoughlyInSync    resb 1
    71     .au8Padding0                resb 2
    72     .au32Padding1               resd 26
     80    .enmUseTscDelta             resd 1
     81    .fGetGipCpu                 resd 1
     82    .au32Padding1               resd 25
    7383    .aiCpuFromApicId            resw 256
    7484    .aiCpuFromCpuSetIdx         resw 256
     
    126136endstruc
    127137
    128 ;;
    129 ; Macro to apply per-CPU TSC delta to the TSC value read in through rdtsc.
    130 ;
    131 ; @param   %1    The pSupGipCpu pointer
    132 ; @remarks edx:eax contains the 64-bit TSC value to apply the delta to.
    133 %macro SUPTscDeltaApply 1
    134     ; Check if we have a valid TSC-delta, i.e. != INT64_MAX.
    135     cmp     dword [%1 + SUPGIPCPU.i64TSCDelta], 0xffffffff
    136     jne     %%valid_delta
    137     cmp     dword [%1 + SUPGIPCPU.i64TSCDelta + 4], 0x7fffffff
    138     je      %%done
    139 %%valid_delta:
    140     ; Subtract the delta from edx:eax
    141     sub     eax, dword [%1 + SUPGIPCPU.i64TSCDelta]
    142     sbb     edx, dword [%1 + SUPGIPCPU.i64TSCDelta + 4]
    143 %%done:
    144 %endmacro
    145 
    146138%endif
    147139
  • TabularUnified 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;
  • TabularUnified trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h

    r54224 r54252  
    215215 *          - Fix SUPTSCREAD padding (#if 0 -> #if 1).
    216216 */
    217 #define SUPDRV_IOC_VERSION                              0x001e0000
     217#define SUPDRV_IOC_VERSION                              0x001f0000
    218218
    219219/** SUP_IOCTL_COOKIE. */
     
    14851485 * Measure the TSC-delta between the specified CPU and the master TSC.
    14861486 *
     1487 * To call this I/O control, the client must first have mapped the GIP.
     1488 *
    14871489 * @{
    14881490 */
     
    15111513            /** Whether to do the measurement asynchronously (if possible). */
    15121514            bool            fAsync;
    1513             /** Padding for future. */
    1514             uint64_t        auPadding[3];
    15151515        } In;
    15161516    } u;
    15171517} SUPTSCDELTAMEASURE, *PSUPTSCDELTAMEASURE;
    15181518AssertCompileMemberAlignment(SUPTSCDELTAMEASURE, u, 8);
     1519AssertCompileSize(SUPTSCDELTAMEASURE, 6*4 + 4+1+1+1+1);
    15191520/** @} */
    15201521
     
    15461547            /** The APIC Id of the CPU where the TSC was read. */
    15471548            uint16_t        idApic;
    1548             /** Padding for future. */
    1549 #if 0 /* Not correct for 32-bit gcc. */
    1550             uint16_t        auPadding[3 + 3*4];
    1551 #else
    1552             uint64_t        auPadding[3];
    1553 #endif
     1549            /** Explicit alignment padding. */
     1550            uint16_t        auPadding[3];
    15541551        } Out;
    15551552    } u;
    15561553} SUPTSCREAD, *PSUPTSCREAD;
    15571554AssertCompileMemberAlignment(SUPTSCREAD, u, 8);
    1558 #if 0  /* Not correct for 32-bit gcc. */
    1559 AssertCompileSize(SUPTSCREAD, 6*4 + 5*8);
     1555AssertCompileSize(SUPTSCREAD, 6*4 + 2*8);
     1556/** @} */
     1557
     1558#pragma pack()                          /* paranoia */
     1559
    15601560#endif
    1561 /** @} */
    1562 
    1563 #pragma pack()                          /* paranoia */
    1564 
    1565 #endif
    1566 
     1561
  • TabularUnified trunk/src/VBox/HostDrivers/Support/testcase/tstGIP-2.cpp

    r54214 r54252  
    251251                    RTPrintf("tstGIP-2: offline: %lld\n", g_pSUPGlobalInfoPage->aCPUs[iCpu].i64TSCDelta);
    252252
    253             RTPrintf("fTscDeltasRoughlyInSync: %RTbool\n", g_pSUPGlobalInfoPage->fTscDeltasRoughlyInSync);
    254             RTPrintf("CPUID.Invariant-TSC    : %RTbool\n", tstIsInvariantTsc());
     253            RTPrintf("tstGIP-2: enmUseTscDelta=%d  fGetGipCpu=%#x\n",
     254                     g_pSUPGlobalInfoPage->enmUseTscDelta, g_pSUPGlobalInfoPage->fGetGipCpu);
    255255            if (   uCpuHzRef
    256256                && cCpuHzOverallDevCnt)
    257257            {
    258258                uint32_t uPct    = (uint32_t)(uCpuHzOverallDeviation * 100000 / cCpuHzOverallDevCnt / uCpuHzRef + 5);
     259                RTPrintf("tstGIP-2: Average CpuHz deviation: %d.%02d%%\n",
     260                         uPct / 1000, (uPct % 1000) / 10);
     261
    259262                uint32_t uMaxPct = (uint32_t)(RT_ABS(iCpuHzMaxDeviation) * 100000 / uCpuHzRef + 5);
    260                 RTPrintf("Average CpuHz deviation: %d.%02d%%\n", uPct / 1000, (uPct % 1000) / 10);
    261                 RTPrintf("Maximum CpuHz deviation: %d.%02d%% (%RI64 ticks)\n", uMaxPct / 1000, (uMaxPct % 1000) / 10, iCpuHzMaxDeviation);
     263                RTPrintf("tstGIP-2: Maximum CpuHz deviation: %d.%02d%% (%RI64 ticks)\n",
     264                        uMaxPct / 1000, (uMaxPct % 1000) / 10, iCpuHzMaxDeviation);
    262265            }
    263266        }
  • TabularUnified trunk/src/VBox/Runtime/common/time/timesup.cpp

    r54224 r54252  
    168168        if (ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_SSE2)
    169169            iWorker = pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC
    170                     ? !pGip->fOsTscDeltasInSync && !pGip->fTscDeltasRoughlyInSync
    171                       ? RTTIMENANO_WORKER_LFENCE_INVAR_WITH_DELTA : RTTIMENANO_WORKER_LFENCE_INVAR_NO_DELTA
     170                    ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
     171                      ? RTTIMENANO_WORKER_LFENCE_INVAR_NO_DELTA : RTTIMENANO_WORKER_LFENCE_INVAR_WITH_DELTA
    172172                    : pGip->u32Mode == SUPGIPMODE_SYNC_TSC
    173                     ? false /** @todo !pGip->fOsTscDeltasInSync && !pGip->fTscDeltasRoughlyInSync */
    174                       ? RTTIMENANO_WORKER_LFENCE_SYNC_WITH_DELTA  : RTTIMENANO_WORKER_LFENCE_SYNC_NO_DELTA
     173                    ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
     174                      ? RTTIMENANO_WORKER_LFENCE_SYNC_NO_DELTA  : RTTIMENANO_WORKER_LFENCE_SYNC_WITH_DELTA
    175175                    : RTTIMENANO_WORKER_LFENCE_ASYNC;
    176176        else
    177177            iWorker = pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC
    178                     ? !pGip->fOsTscDeltasInSync && !pGip->fTscDeltasRoughlyInSync
    179                       ? RTTIMENANO_WORKER_LEGACY_INVAR_WITH_DELTA : RTTIMENANO_WORKER_LEGACY_INVAR_NO_DELTA
     178                    ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
     179                      ? RTTIMENANO_WORKER_LEGACY_INVAR_NO_DELTA : RTTIMENANO_WORKER_LEGACY_INVAR_WITH_DELTA
    180180                    : pGip->u32Mode == SUPGIPMODE_SYNC_TSC
    181                     ? false /** @todo !pGip->fOsTscDeltasInSync && !pGip->fTscDeltasRoughlyInSync */
    182                       ? RTTIMENANO_WORKER_LEGACY_SYNC_WITH_DELTA  : RTTIMENANO_WORKER_LEGACY_SYNC_NO_DELTA
     181                    ? pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
     182                      ? RTTIMENANO_WORKER_LEGACY_SYNC_NO_DELTA  : RTTIMENANO_WORKER_LEGACY_SYNC_WITH_DELTA
    183183                    : RTTIMENANO_WORKER_LEGACY_ASYNC;
    184184    }
  • TabularUnified trunk/src/VBox/Runtime/testcase/tstRTTime.cpp

    r48935 r54252  
    9898    else
    9999    {
    100         RTTestValue(hTest, "Total time delta", u64OSElapsedTS - u64RTElapsedTS, RTTESTUNIT_NS);
     100        if (u64OSElapsedTS >= u64RTElapsedTS)
     101            RTTestValue(hTest, "Total time delta", u64OSElapsedTS - u64RTElapsedTS, RTTESTUNIT_NS);
     102        else
     103            RTTestValue(hTest, "Total time delta", u64RTElapsedTS - u64OSElapsedTS, RTTESTUNIT_NS);
    101104        RTTestPrintf(hTest, RTTESTLVL_INFO, "total time difference: u64OSElapsedTS=%#llx u64RTElapsedTS=%#llx delta=%lld\n",
    102105                     u64OSElapsedTS, u64RTElapsedTS, u64OSElapsedTS - u64RTElapsedTS);
  • TabularUnified trunk/src/VBox/VMM/VMMR3/TM.cpp

    r54219 r54252  
    168168*******************************************************************************/
    169169static bool                 tmR3HasFixedTSC(PVM pVM);
    170 static bool                 tmR3ReallyNeedDeltas(PSUPGLOBALINFOPAGE pGip);
    171170static const char *         tmR3GetTSCModeName(PVM pVM);
    172171static uint64_t             tmR3CalibrateTSC(PVM pVM);
     
    231230     * as well and save costly world switches.
    232231     */
    233     pVM->tm.s.pvGIPR3 = (void *)g_pSUPGlobalInfoPage;
     232    PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage;
     233    pVM->tm.s.pvGIPR3 = (void *)pGip;
    234234    AssertMsgReturn(pVM->tm.s.pvGIPR3, ("GIP support is now required!\n"), VERR_TM_GIP_REQUIRED);
    235     AssertMsgReturn((g_pSUPGlobalInfoPage->u32Version >> 16) == (SUPGLOBALINFOPAGE_VERSION >> 16),
    236                     ("Unsupported GIP version!\n"), VERR_TM_GIP_VERSION);
     235    AssertMsgReturn((pGip->u32Version >> 16) == (SUPGLOBALINFOPAGE_VERSION >> 16),
     236                    ("Unsupported GIP version %#x! (expected=%#x)\n", pGip->u32Version, SUPGLOBALINFOPAGE_VERSION),
     237                    VERR_TM_GIP_VERSION);
    237238
    238239    RTHCPHYS HCPhysGIP;
     
    242243    RTGCPTR GCPtr;
    243244#ifdef SUP_WITH_LOTS_OF_CPUS
    244     rc = MMR3HyperMapHCPhys(pVM, pVM->tm.s.pvGIPR3, NIL_RTR0PTR, HCPhysGIP, (size_t)g_pSUPGlobalInfoPage->cPages * PAGE_SIZE,
     245    rc = MMR3HyperMapHCPhys(pVM, pVM->tm.s.pvGIPR3, NIL_RTR0PTR, HCPhysGIP, (size_t)pGip->cPages * PAGE_SIZE,
    245246                            "GIP", &GCPtr);
    246247#else
     
    257258
    258259    /* Check assumptions made in TMAllVirtual.cpp about the GIP update interval. */
    259     if (    g_pSUPGlobalInfoPage->u32Magic == SUPGLOBALINFOPAGE_MAGIC
    260         &&  g_pSUPGlobalInfoPage->u32UpdateIntervalNS >= 250000000 /* 0.25s */)
     260    if (    pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC
     261        &&  pGip->u32UpdateIntervalNS >= 250000000 /* 0.25s */)
    261262        return VMSetError(pVM, VERR_TM_GIP_UPDATE_INTERVAL_TOO_BIG, RT_SRC_POS,
    262263                          N_("The GIP update interval is too big. u32UpdateIntervalNS=%RU32 (u32UpdateHz=%RU32)"),
    263                           g_pSUPGlobalInfoPage->u32UpdateIntervalNS, g_pSUPGlobalInfoPage->u32UpdateHz);
    264     LogRel(("TM: GIP - u32Mode=%d (%s) u32UpdateHz=%u u32UpdateIntervalNS=%u\n", g_pSUPGlobalInfoPage->u32Mode,
    265             SUPGetGIPModeName(g_pSUPGlobalInfoPage), g_pSUPGlobalInfoPage->u32UpdateHz,
    266             g_pSUPGlobalInfoPage->u32UpdateIntervalNS));
    267     LogRel(("TM: GIP - u64CpuHz=%#RX64 (%'RU64)\n", g_pSUPGlobalInfoPage->u64CpuHz, g_pSUPGlobalInfoPage->u64CpuHz));
     264                          pGip->u32UpdateIntervalNS, pGip->u32UpdateHz);
     265    LogRel(("TM: GIP - u32Mode=%d (%s) u32UpdateHz=%u u32UpdateIntervalNS=%u\n", pGip->u32Mode,
     266            SUPGetGIPModeName(pGip), pGip->u32UpdateHz,
     267            pGip->u32UpdateIntervalNS));
     268    LogRel(("TM: GIP - u64CpuHz=%#RX64 (%'RU64)\n", pGip->u64CpuHz, pGip->u64CpuHz));
    268269
    269270    /*
     
    275276    if (ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_SSE2)
    276277    {
    277         if (g_pSUPGlobalInfoPage->u32Mode == SUPGIPMODE_INVARIANT_TSC)
    278             pVM->tm.s.pfnVirtualGetRawR3 = tmR3ReallyNeedDeltas(g_pSUPGlobalInfoPage)
    279                                          ? RTTimeNanoTSLFenceInvariantWithDelta : RTTimeNanoTSLFenceInvariantNoDelta;
    280         else if (g_pSUPGlobalInfoPage->u32Mode == SUPGIPMODE_SYNC_TSC)
    281             pVM->tm.s.pfnVirtualGetRawR3 = false /** @todo tmR3ReallyNeedDeltas(g_pSUPGlobalInfoPage) */
    282                                          ? RTTimeNanoTSLFenceSyncWithDelta      : RTTimeNanoTSLFenceSyncNoDelta;
     278        if (pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC)
     279            pVM->tm.s.pfnVirtualGetRawR3 = pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
     280                                         ? RTTimeNanoTSLFenceInvariantNoDelta : RTTimeNanoTSLFenceInvariantWithDelta;
     281        else if (pGip->u32Mode == SUPGIPMODE_SYNC_TSC)
     282            pVM->tm.s.pfnVirtualGetRawR3 = pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
     283                                         ? RTTimeNanoTSLFenceSyncNoDelta      : RTTimeNanoTSLFenceSyncWithDelta;
    283284        else
    284285            pVM->tm.s.pfnVirtualGetRawR3 = RTTimeNanoTSLFenceAsync;
     
    286287    else
    287288    {
    288         if (g_pSUPGlobalInfoPage->u32Mode == SUPGIPMODE_INVARIANT_TSC)
    289             pVM->tm.s.pfnVirtualGetRawR3 = tmR3ReallyNeedDeltas(g_pSUPGlobalInfoPage)
    290                                          ? RTTimeNanoTSLegacyInvariantWithDelta : RTTimeNanoTSLegacyInvariantNoDelta;
    291         else if (g_pSUPGlobalInfoPage->u32Mode == SUPGIPMODE_SYNC_TSC)
    292             pVM->tm.s.pfnVirtualGetRawR3 = false /** @todo tmR3ReallyNeedDeltas(g_pSUPGlobalInfoPage) */
    293                                          ? RTTimeNanoTSLegacySyncWithDelta      : RTTimeNanoTSLegacySyncNoDelta;
     289        if (pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC)
     290            pVM->tm.s.pfnVirtualGetRawR3 = pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
     291                                         ? RTTimeNanoTSLegacyInvariantNoDelta   : RTTimeNanoTSLegacyInvariantWithDelta;
     292        else if (pGip->u32Mode == SUPGIPMODE_SYNC_TSC)
     293            pVM->tm.s.pfnVirtualGetRawR3 = pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO
     294                                         ? RTTimeNanoTSLegacySyncNoDelta        : RTTimeNanoTSLegacySyncWithDelta;
    294295        else
    295296            pVM->tm.s.pfnVirtualGetRawR3 = RTTimeNanoTSLegacyAsync;
     
    619620     * Dump the GIPCPU TSC-deltas, iterate using the Apic Id to get master at the beginning in most cases.
    620621     */
    621     LogRel(("TM: GIP - fTscDeltasRoughlyInSync=%RTbool\n", g_pSUPGlobalInfoPage->fTscDeltasRoughlyInSync));
    622     unsigned cGipCpus = RT_ELEMENTS(g_pSUPGlobalInfoPage->aiCpuFromApicId);
    623     for (unsigned i = 0; i < cGipCpus; i++)
    624     {
    625         uint16_t iCpu  = g_pSUPGlobalInfoPage->aiCpuFromApicId[i];
     622    LogRel(("TM: GIP - enmUseTscDelta=%d fGetGipCpu=%#x cCpus=%#x\n",
     623            pGip->enmUseTscDelta, pGip->fGetGipCpu, pGip->cCpus));
     624    for (uint32_t i = 0; i < RT_ELEMENTS(pGip->aiCpuFromApicId); i++)
     625    {
     626        uint16_t iCpu = pGip->aiCpuFromApicId[i];
    626627#if 1
    627628        if (iCpu != UINT16_MAX)
    628             LogRel(("TM: GIP - CPU[%d]: idApic=%d i64TSCDelta=%RI64\n", g_pSUPGlobalInfoPage->aCPUs[iCpu].idCpu,
    629                     g_pSUPGlobalInfoPage->aCPUs[iCpu].idApic, g_pSUPGlobalInfoPage->aCPUs[iCpu].i64TSCDelta));
     629            LogRel(("TM: GIP - CPU[%d]: idApic=%d i64TSCDelta=%RI64\n", pGip->aCPUs[iCpu].idCpu,
     630                    pGip->aCPUs[iCpu].idApic, pGip->aCPUs[iCpu].i64TSCDelta));
    630631#else
    631632        /* Dump 2 entries per line, saves vertical space in release log but more dumps bytes due to formatting. */
     
    633634        for (unsigned k = i + 1; k < cGipCpus; k++)
    634635        {
    635             iCpu2 = g_pSUPGlobalInfoPage->aiCpuFromApicId[k];
     636            iCpu2 = pGip->aiCpuFromApicId[k];
    636637            if (iCpu2 != UINT16_MAX)
    637638            {
     
    644645        {
    645646            LogRel(("TM: GIP - CPU[%d]: idApic=%d i64TSCDelta=%-4lld CPU[%d]: idApic=%d i64TSCDelta=%lld\n",
    646                     g_pSUPGlobalInfoPage->aCPUs[iCpu].idCpu, g_pSUPGlobalInfoPage->aCPUs[iCpu].idApic,
    647                     g_pSUPGlobalInfoPage->aCPUs[iCpu].i64TSCDelta, g_pSUPGlobalInfoPage->aCPUs[iCpu2].idCpu,
    648                     g_pSUPGlobalInfoPage->aCPUs[iCpu2].idApic, g_pSUPGlobalInfoPage->aCPUs[iCpu2].i64TSCDelta));
     647                    pGip->aCPUs[iCpu].idCpu, pGip->aCPUs[iCpu].idApic,
     648                    pGip->aCPUs[iCpu].i64TSCDelta, pGip->aCPUs[iCpu2].idCpu,
     649                    pGip->aCPUs[iCpu2].idApic, pGip->aCPUs[iCpu2].i64TSCDelta));
    649650        }
    650651        else if (iCpu != UINT16_MAX)
    651             LogRel(("TM: GIP - CPU[%d]: idApic=%d i64TSCDelta=%lld\n", g_pSUPGlobalInfoPage->aCPUs[iCpu].idCpu,
    652                     g_pSUPGlobalInfoPage->aCPUs[iCpu].idApic));
     652            LogRel(("TM: GIP - CPU[%d]: idApic=%d i64TSCDelta=%lld\n", pGip->aCPUs[iCpu].idCpu,
     653                    pGip->aCPUs[iCpu].idApic));
    653654#endif
    654655    }
     
    941942    }
    942943    return false;
    943 }
    944 
    945 
    946 /**
    947  * Checks if we really need to apply the delta values when calculating time.
    948  *
    949  * Getting the delta for a CPU is _very_ expensive, it more than doubles the
    950  * execution time for RTTimeNanoTS.
    951  *
    952  * @returns true if deltas needs to be applied, false if not.
    953  * @param   pGip                The GIP.
    954  *
    955  * @remarks If you change this, make sure to also change
    956  *          rtTimeNanoTsInternalReallyNeedDeltas().
    957  */
    958 static bool tmR3ReallyNeedDeltas(PSUPGLOBALINFOPAGE pGip)
    959 {
    960     return !pGip->fOsTscDeltasInSync && !pGip->fTscDeltasRoughlyInSync;
    961 #if 0
    962     if (!pGip->fOsTscDeltasInSync)
    963     {
    964         uint32_t i = pGip->cCpus;
    965         while (i-- > 0)
    966             if (   pGip->aCPUs[i].enmState == SUPGIPCPUSTATE_ONLINE
    967                 && (   pGip->aCPUs[i].i64TSCDelta > 384
    968                     || pGip->aCPUs[i].i64TSCDelta < -384) )
    969                 return true;
    970     }
    971     return false;
    972 #endif
    973944}
    974945
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