VirtualBox

Changeset 9621 in vbox for trunk/src/VBox/HostDrivers


Ignore:
Timestamp:
Jun 11, 2008 4:42:07 PM (16 years ago)
Author:
vboxsync
Message:

The TSC checks are now fully done in the generic code.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/SUPDRV.h

    r9470 r9621  
    712712    /** GIP timer interval (ms). */
    713713    ULONG                   ulGipTimerInterval;
    714     /** Flag to force async GIP timer mode. */
    715     BOOLEAN                 fForceAsyncTsc;
    716714    /** Current CPU affinity mask. */
    717715    KAFFINITY               uAffinityMask;
  • trunk/src/VBox/HostDrivers/Support/SUPDRVShared.c

    r9607 r9621  
    39993999static DECLCALLBACK(void) supdrvDetermineAsyncTscWorker(RTCPUID idCpu, void *pvUser1, void *pvUser2)
    40004000{
     4001#if 1
     4002    ASMAtomicWriteU64((uint64_t volatile *)pvUser1, ASMReadTSC());
     4003#else
    40014004    *(uint64_t *)pvUser1 = ASMReadTSC();
     4005#endif
    40024006}
    40034007
     
    40124016 * case we have to choose the asynchronous timer mode.
    40134017 *
    4014  * @param   pu64Diff    pointer to the determined difference between different cores.
     4018 * @param   poffMin     Pointer to the determined difference between different cores.
    40154019 * @return  false if the time stamp counters appear to be synchron, true otherwise.
    40164020 */
    4017 bool VBOXCALL supdrvDetermineAsyncTsc(uint64_t *pu64DiffCores)
    4018 {
    4019     static uint64_t s_aTsc[8][RTCPUSET_MAX_CPUS];
    4020     uint64_t u64Diff, u64DiffMin, u64DiffMax, u64TscLast;
    4021     int iSlot, iCpu, cCpus;
    4022     bool fBackwards;
    4023     RTCPUSET OnlineCpus;
    4024     int rc;
    4025 
    4026     *pu64DiffCores = 1;
    4027 
    4028     RTMpGetOnlineSet(&OnlineCpus);
    4029     cCpus = RTCpuSetCount(&OnlineCpus);
    4030     if (cCpus < 2)
    4031         return false;
    4032     Assert(cCpus <= RT_ELEMENTS(s_aTsc[0]));
    4033 
    4034     /*
    4035      * Collect data from the online CPUs.
    4036      */
    4037     for (iSlot = 0; iSlot < RT_ELEMENTS(s_aTsc); iSlot++)
    4038     {
    4039         RTCPUID iCpuSet = 0;
    4040         for (iCpu = 0; iCpu < cCpus; iCpu++)
    4041         {
    4042             while (!RTCpuSetIsMemberByIndex(&OnlineCpus, iCpuSet))
     4021bool VBOXCALL supdrvDetermineAsyncTsc(uint64_t *poffMin)
     4022{
     4023    /*
     4024     * Just iterate all the cpus 8 times and make sure that the TSC is
     4025     * ever increasing. We don't bother taking TSC rollover into account.
     4026     */
     4027    RTCPUSET    CpuSet;
     4028    int         iLastCpu = RTCpuLastIndex(RTMpGetSet(&CpuSet));
     4029    int         iCpu;
     4030    int         cLoops = 8;
     4031    bool        fAsync = false;
     4032    int         rc;
     4033    uint64_t    offMax = 0;
     4034    uint64_t    offMin = ~(uint64_t)0;
     4035    uint64_t    PrevTsc = ASMReadTSC();
     4036
     4037    while (cLoops-- > 0)
     4038    {
     4039        for (iCpu = 0; iCpu <= iLastCpu; iCpu++)
     4040        {
     4041            uint64_t CurTsc;
     4042            rc = RTMpOnSpecific(RTMpCpuIdFromSetIndex(iCpu), supdrvDetermineAsyncTscWorker, &CurTsc, NULL);
     4043            if (RT_SUCCESS(rc))
    40434044            {
    4044                 iCpuSet++; /* skip offline CPU */
    4045                 dprintf2(("skipping %d\n", iCpuSet));
     4045                if (CurTsc <= PrevTsc)
     4046                {
     4047                    fAsync = true;
     4048                    offMin = offMax = PrevTsc - CurTsc;
     4049                    dprintf(("supdrvDetermineAsyncTsc: iCpu=%d cLoops=%d CurTsc=%llx PrevTsc=%llx\n",
     4050                             iCpu, cLoops, CurTsc, PrevTsc));
     4051                    break;
     4052                }
     4053
     4054                /* Gather statistics (except the first time). */
     4055                if (iCpu != 0 || cLoops != 7)
     4056                {
     4057                    uint64_t off = CurTsc - PrevTsc;
     4058                    if (off < offMin)
     4059                        offMin = off;
     4060                    if (off > offMax)
     4061                        offMax = off;
     4062                    dprintf2(("%d/%d: off=%llx\n", cLoops, iCpu, off));
     4063                }
     4064
     4065                /* Next */
     4066                PrevTsc = CurTsc;
    40464067            }
    4047             rc = RTMpOnSpecific(RTMpCpuIdFromSetIndex(iCpuSet), supdrvDetermineAsyncTscWorker, &s_aTsc[iSlot][iCpu], NULL);
    4048             if (rc == VERR_NOT_SUPPORTED)
    4049                 return false;
    4050             iCpuSet++;
    4051         }
    4052     }
    4053 
    4054     /*
    4055      * Check that the TSC reads are strictly ascending.
    4056      */
    4057     /** @todo This doesn't work if a CPU is offline. Make these loops ignore
    4058      *        offline CPUs. */
    4059     fBackwards = false;
    4060     u64DiffMin = (uint64_t)~0;
    4061     u64TscLast = 0;
    4062     for (iSlot = 0; iSlot < RT_ELEMENTS(s_aTsc); iSlot++)
    4063     {
    4064         uint64_t u64Tsc0 = s_aTsc[iSlot][0];
    4065         u64DiffMax = 0;
    4066         if (u64Tsc0 <= u64TscLast)
    4067         {
    4068             dprintf2(("iSlot=%d u64Tsc0=%#x%#08x u64TscLast=%#x%#08x\n", iSlot,
    4069                       (long)(u64Tsc0 >> 32), (long)u64Tsc0, (long)(u64TscLast >> 32), (long)u64TscLast));
    4070             fBackwards = true;
    4071         }
    4072         u64TscLast = u64Tsc0;
    4073         for (iCpu = 1; iCpu < cCpus; iCpu++)
    4074         {
    4075             uint64_t u64TscN = s_aTsc[iSlot][iCpu];
    4076             if (u64TscN <= u64TscLast)
    4077             {
    4078                 dprintf2(("iSlot=%d iCpu=%d u64TscN=%#x%#08x u64TscLast=%#x%#08x\n", iSlot, iCpu,
    4079                           (long)(u64TscN >> 32), (long)u64TscN, (long)(u64TscLast >> 32), (long)u64TscLast));
    4080                 fBackwards = true;
    4081             }
    4082             u64TscLast = u64TscN;
    4083 
    4084             u64Diff = u64TscN > u64Tsc0 ? u64TscN - u64Tsc0 : u64Tsc0 - u64TscN;
    4085             if (u64DiffMax < u64Diff)
    4086                 u64DiffMax = u64Diff;
    4087         }
    4088         if (u64DiffMin > u64DiffMax)
    4089             u64DiffMin = u64DiffMax;
    4090     }
    4091     /* informational */
    4092     *pu64DiffCores = u64DiffMin;
    4093 
    4094     return fBackwards;
     4068            else if (rc == VERR_NOT_SUPPORTED)
     4069                break;
     4070            else
     4071                AssertMsg(rc == VERR_CPU_NOT_FOUND || rc == VERR_CPU_OFFLINE, ("%d\n", rc));
     4072        }
     4073
     4074        /* broke out of the loop. */
     4075        if (iCpu <= iLastCpu)
     4076            break;
     4077    }
     4078
     4079    *poffMin = offMin; /* Almost RTMpOnSpecific profiling. */
     4080    dprintf(("supdrvDetermineAsyncTsc: returns %d; iLastCpu=%d rc=%d offMin=%llx offMax=%llx\n",
     4081             fAsync, iLastCpu, rc, offMin, offMax));
     4082#if !defined(RT_OS_SOLARIS) && !defined(RT_OS_OS2) && !defined(RT_OS_WINDOWS)
     4083    OSDBGPRINT(("vboxdrv: fAsync=%d offMin=%#lx offMax=%#lx\n", fAsync, (long)offMin, (long)offMax));
     4084#endif
     4085    return fAsync;
    40954086}
    40964087
     
    41064097    /*
    41074098     * On SMP we're faced with two problems:
    4108      *      (1) There might be a skew between the CPU, so that cpu0 
    4109      *          returns a TSC that is sligtly different from cpu1. 
     4099     *      (1) There might be a skew between the CPU, so that cpu0
     4100     *          returns a TSC that is sligtly different from cpu1.
    41104101     *      (2) Power management (and other things) may cause the TSC
    41114102     *          to run at a non-constant speed, and cause the speed
    41124103     *          to be different on the cpus. This will result in (1).
    4113      * 
     4104     *
    41144105     * So, on SMP systems we'll have to select the ASYNC update method
    41154106     * if there are symphoms of these problems.
  • trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c

    r9602 r9621  
    478478{
    479479    int       rc;
    480     bool      fAsync;
    481     uint64_t  u64DiffCores;
    482480
    483481    dprintf(("VBoxDrv::ModuleInit\n"));
     
    603601     */
    604602    printk(KERN_DEBUG DEVICE_NAME ": Found %u processor cores.\n", (unsigned)RTMpGetOnlineCount());
    605     fAsync = supdrvDetermineAsyncTsc(&u64DiffCores);
    606     /* no 64-bit arithmetics here, we assume that the TSC difference between the cores is < 2^32 */
    607     printk(KERN_DEBUG DEVICE_NAME ": fAsync=%d u64DiffCores=%u.\n", fAsync, (uint32_t)u64DiffCores);
    608     if (fAsync)
    609         force_async_tsc = 1;
    610 
    611603#ifdef CONFIG_VBOXDRV_AS_MISC
    612604    rc = misc_register(&gMiscDevice);
  • trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp

    r9587 r9621  
    136136                {
    137137#ifndef USE_NEW_OS_INTERFACE_FOR_GIP
    138                     /* Make sure the tsc is consistent across cpus/cores. */
    139                     uint64_t    u64DiffCores;
    140                     pDevExt->fForceAsyncTsc = supdrvDetermineAsyncTsc(&u64DiffCores);
    141                     dprintf(("supdrvDetermineAsyncTsc: fAsync=%d u64DiffCores=%u.\n", pDevExt->fForceAsyncTsc, (uint32_t)u64DiffCores));
    142 
    143138                    /*
    144139                     * Inititalize the GIP.
     
    802797bool VBOXCALL  supdrvOSGetForcedAsyncTscMode(PSUPDRVDEVEXT pDevExt)
    803798{
    804 #ifdef USE_NEW_OS_INTERFACE_FOR_GIP
    805799    return false;
    806 #else
    807     return pDevExt->fForceAsyncTsc != 0;
    808 #endif
    809800}
    810801
Note: See TracChangeset for help on using the changeset viewer.

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