VirtualBox

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


Ignore:
Timestamp:
Feb 22, 2007 8:29:35 PM (18 years ago)
Author:
vboxsync
Message:

Initial GIP change. Missing detection of SMP systems with TSC drift.

Location:
trunk/src/VBox/HostDrivers/Support
Files:
1 deleted
7 edited

Legend:

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

    r679 r1027  
    617617    /** The GIP DPC object associated with GipTimer. */
    618618    KDPC                    GipDpc;
     619    /** The GIP DPC objects for updating per-cpu data. */
     620    KDPC                    aGipCpuDpcs[32];
    619621    /** Pointer to the MDL for the pGip page. */
    620622    PMDL                    pGipMdl;
     
    626628    unsigned long           ulLastJiffies;
    627629    /** The last mono time stamp. */
    628     uint64_t                u64LastMonotime;
     630    uint64_t volatile       u64LastMonotime;
    629631#endif
    630632} SUPDRVDEVEXT;
     
    652654void  VBOXCALL  supdrvOSGipResume(PSUPDRVDEVEXT pDevExt);
    653655void  VBOXCALL  supdrvOSGipSuspend(PSUPDRVDEVEXT pDevExt);
     656unsigned VBOXCALL supdrvOSGetCPUCount(void);
    654657#endif
    655658
     
    671674void VBOXCALL   supdrvGipTerm(PSUPGLOBALINFOPAGE pGip);
    672675void VBOXCALL   supdrvGipUpdate(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS);
     676void VBOXCALL   supdrvGipUpdatePerCpu(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, unsigned iCpu);
    673677
    674678__END_DECLS
  • trunk/src/VBox/HostDrivers/Support/SUPDRVIOC.h

    r914 r1027  
    176176#define SUPCOOKIE_MAGIC             "The Magic Word!"
    177177/** Current interface version. */
    178 #define SUPDRVIOC_VERSION           0x00030002
     178#define SUPDRVIOC_VERSION           0x00040000
    179179
    180180/** SUP_IOCTL_COOKIE Output. */
  • trunk/src/VBox/HostDrivers/Support/SUPDRVShared.c

    r982 r1027  
    22882288            if (pDevExt->cGipUsers == 1)
    22892289            {
     2290                PSUPGLOBALINFOPAGE pGip = pDevExt->pGip;
     2291                unsigned i;
     2292
    22902293                dprintf(("SUPR0GipMap: Resumes GIP updating\n"));
    2291                 ASMAtomicXchgU32(&pDevExt->pGip->u32TransactionId,
    2292                                  pDevExt->pGip->u32TransactionId & ~(GIP_UPDATEHZ_RECALC_FREQ * 2 - 1));
    2293                 ASMAtomicXchgU64(&pDevExt->pGip->u64NanoTSLastUpdateHz, 0);
     2294
     2295                for (i = 0; i < RT_ELEMENTS(pGip->aCPUs); i++)
     2296                    ASMAtomicXchgU32(&pGip->aCPUs[i].u32TransactionId, pGip->aCPUs[i].u32TransactionId & ~(GIP_UPDATEHZ_RECALC_FREQ * 2 - 1));
     2297                ASMAtomicXchgU64(&pGip->u64NanoTSLastUpdateHz, 0);
     2298
    22942299#ifdef USE_NEW_OS_INTERFACE
    2295                 rc = RTTimerStart(pDevExt->pGipTimer, 0); AssertRC(rc); rc = 0;
     2300                rc = RTTimerStart(pDevExt->pGipTimer, 0);
     2301                AssertRC(rc); rc = 0;
    22962302#else
    22972303                supdrvOSGipResume(pDevExt);
     
    40054011int VBOXCALL supdrvGipInit(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, RTHCPHYS HCPhys, uint64_t u64NanoTS, unsigned uUpdateHz)
    40064012{
     4013    unsigned i;
    40074014    dprintf(("supdrvGipInit: pGip=%p HCPhys=%lx u64NanoTS=%llu uUpdateHz=%d\n", pGip, (long)HCPhys, u64NanoTS, uUpdateHz));
    40084015
     4016    /*
     4017     * Initialize the structure.
     4018     */
    40094019    memset(pGip, 0, PAGE_SIZE);
    40104020    pGip->u32Magic          = SUPGLOBALINFOPAGE_MAGIC;
     4021    pGip->u32Mode           = SUPGIPMODE_SYNC_TSC;
    40114022    pGip->u32UpdateHz       = uUpdateHz;
    40124023    pGip->u32UpdateIntervalNS = 1000000000 / uUpdateHz;
    4013     pGip->u32TransactionId  = 2;
    4014     pGip->u64NanoTS         = u64NanoTS;
    40154024    pGip->u64NanoTSLastUpdateHz = u64NanoTS;
    4016     pGip->u64TSC            = ASMReadTSC();
    4017 
    4018     /*
    4019      * We don't know the following values until we've executed updates.
    4020      * So, we'll just insert very high values.
    4021      */
    4022     pGip->u64CpuHz          = _4G + 1;
    4023     pGip->u32UpdateIntervalTSC = _2G / 4;
    4024     pGip->au32TSCHistory[0] = _2G / 4;
    4025     pGip->au32TSCHistory[1] = _2G / 4;
    4026     pGip->au32TSCHistory[2] = _2G / 4;
    4027     pGip->au32TSCHistory[3] = _2G / 4;
    4028     pGip->au32TSCHistory[4] = _2G / 4;
    4029     pGip->au32TSCHistory[5] = _2G / 4;
    4030     pGip->au32TSCHistory[6] = _2G / 4;
    4031     pGip->au32TSCHistory[7] = _2G / 4;
     4025
     4026    for (i = 0; i < RT_ELEMENTS(pGip->aCPUs); i++)
     4027    {
     4028        pGip->aCPUs[i].u32TransactionId  = 2;
     4029        pGip->aCPUs[i].u64NanoTS         = u64NanoTS;
     4030        pGip->aCPUs[i].u64TSC            = ASMReadTSC();
     4031   
     4032        /*
     4033         * We don't know the following values until we've executed updates.
     4034         * So, we'll just insert very high values.
     4035         */
     4036        pGip->aCPUs[i].u64CpuHz          = _4G + 1;
     4037        pGip->aCPUs[i].u32UpdateIntervalTSC = _2G / 4;
     4038        pGip->aCPUs[i].au32TSCHistory[0] = _2G / 4;
     4039        pGip->aCPUs[i].au32TSCHistory[1] = _2G / 4;
     4040        pGip->aCPUs[i].au32TSCHistory[2] = _2G / 4;
     4041        pGip->aCPUs[i].au32TSCHistory[3] = _2G / 4;
     4042        pGip->aCPUs[i].au32TSCHistory[4] = _2G / 4;
     4043        pGip->aCPUs[i].au32TSCHistory[5] = _2G / 4;
     4044        pGip->aCPUs[i].au32TSCHistory[6] = _2G / 4;
     4045        pGip->aCPUs[i].au32TSCHistory[7] = _2G / 4;
     4046    }
    40324047
    40334048    /*
     
    40384053    pDevExt->cGipUsers = 0;
    40394054
     4055    /*
     4056     * Check if we should switch to async TSC mode.
     4057     */
     4058#if 0
     4059    if (supdrvOSGetCPUCount() > 1)
     4060    {
     4061        ASMCpuId(0,
     4062    }
     4063#endif
     4064
    40404065    return 0;
    40414066}
     
    40494074void VBOXCALL supdrvGipTerm(PSUPGLOBALINFOPAGE pGip)
    40504075{
    4051     pGip->iTSCHistoryHead = ~0;
    4052     pGip->u64NanoTS = 0;
    4053     pGip->u64TSC = 0;
     4076    unsigned i;
    40544077    pGip->u32Magic = 0;
    4055     pGip->iTSCHistoryHead = 0;
    4056 }
    4057 
    4058 
    4059 /**
    4060  * Updates the GIP.
    4061  *
    4062  * @param   pGip        Pointer to the GIP.
    4063  * @param   u64NanoTS   The current nanosecond timesamp.
    4064  */
    4065 void VBOXCALL   supdrvGipUpdate(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS)
     4078    for (i = 0; i < RT_ELEMENTS(pGip->aCPUs); i++)
     4079    {
     4080        pGip->aCPUs[i].u64NanoTS = 0;
     4081        pGip->aCPUs[i].u64TSC = 0;
     4082        pGip->aCPUs[i].iTSCHistoryHead = 0;
     4083    }
     4084}
     4085
     4086
     4087/**
     4088 * Worker routine for supdrvGipUpdate and supdrvGipUpdatePerCpu that
     4089 * updates all the per cpu data except the transaction id.
     4090 *
     4091 * @param   pGip            The GIP.
     4092 * @param   pGipCpu         Pointer to the per cpu data.
     4093 * @param   u64NanoTS       The current time stamp.
     4094 */
     4095static void supdrvGipDoUpdateCpu(PSUPGLOBALINFOPAGE pGip, PSUPGIPCPU pGipCpu, uint64_t u64NanoTS)
    40664096{
    40674097    uint64_t    u64TSC;
     
    40734103
    40744104    /*
     4105     * Update the NanoTS.
     4106     */
     4107    ASMAtomicXchgU64(&pGipCpu->u64NanoTS, u64NanoTS);
     4108
     4109    /*
     4110     * Calc TSC delta.
     4111     */
     4112    /** @todo validate the NanoTS delta, don't trust the OS to call us when it should... */
     4113    u64TSC = ASMReadTSC();
     4114    u64TSCDelta = u64TSC - pGipCpu->u64TSC;
     4115    ASMAtomicXchgU64(&pGipCpu->u64TSC, u64TSC);
     4116
     4117    if (u64TSCDelta >> 32)
     4118    {
     4119        u64TSCDelta = pGipCpu->u32UpdateIntervalTSC;
     4120        pGipCpu->cErrors++;
     4121    }
     4122
     4123    /*
     4124     * TSC History.
     4125     */
     4126    Assert(ELEMENTS(pGipCpu->au32TSCHistory) == 8);
     4127
     4128    iTSCHistoryHead = (pGipCpu->iTSCHistoryHead + 1) & 7;
     4129    ASMAtomicXchgU32(&pGipCpu->iTSCHistoryHead, iTSCHistoryHead);
     4130    ASMAtomicXchgU32(&pGipCpu->au32TSCHistory[iTSCHistoryHead], (uint32_t)u64TSCDelta);
     4131
     4132    /*
     4133     * UpdateIntervalTSC = average of last 8,2,1 intervals depending on update HZ.
     4134     */
     4135    if (pGip->u32UpdateHz >= 1000)
     4136    {
     4137        uint32_t u32;
     4138        u32  = pGipCpu->au32TSCHistory[0];
     4139        u32 += pGipCpu->au32TSCHistory[1];
     4140        u32 += pGipCpu->au32TSCHistory[2];
     4141        u32 += pGipCpu->au32TSCHistory[3];
     4142        u32 >>= 2;
     4143        u32UpdateIntervalTSC  = pGipCpu->au32TSCHistory[4];
     4144        u32UpdateIntervalTSC += pGipCpu->au32TSCHistory[5];
     4145        u32UpdateIntervalTSC += pGipCpu->au32TSCHistory[6];
     4146        u32UpdateIntervalTSC += pGipCpu->au32TSCHistory[7];
     4147        u32UpdateIntervalTSC >>= 2;
     4148        u32UpdateIntervalTSC += u32;
     4149        u32UpdateIntervalTSC >>= 1;
     4150
     4151        /* Value choosen for a 2GHz Athlon64 running linux 2.6.10/11, . */
     4152        u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 14;
     4153    }
     4154    else if (pGip->u32UpdateHz >= 90)
     4155    {
     4156        u32UpdateIntervalTSC  = (uint32_t)u64TSCDelta;
     4157        u32UpdateIntervalTSC += pGipCpu->au32TSCHistory[(iTSCHistoryHead - 1) & 7];
     4158        u32UpdateIntervalTSC >>= 1;
     4159
     4160        /* value choosen on a 2GHz thinkpad running windows */
     4161        u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 7;
     4162    }
     4163    else
     4164    {
     4165        u32UpdateIntervalTSC  = (uint32_t)u64TSCDelta;
     4166
     4167        /* This value hasn't be checked yet.. waiting for OS/2 and 33Hz timers.. :-) */
     4168        u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 6;
     4169    }
     4170    ASMAtomicXchgU32(&pGipCpu->u32UpdateIntervalTSC, u32UpdateIntervalTSC + u32UpdateIntervalTSCSlack);
     4171
     4172    /*
     4173     * CpuHz.
     4174     */
     4175    u64CpuHz = ASMMult2xU32RetU64(u32UpdateIntervalTSC, pGip->u32UpdateHz);
     4176    ASMAtomicXchgU64(&pGipCpu->u64CpuHz, u64CpuHz);
     4177}
     4178
     4179
     4180/**
     4181 * Updates the GIP.
     4182 *
     4183 * @param   pGip        Pointer to the GIP.
     4184 * @param   u64NanoTS   The current nanosecond timesamp.
     4185 */
     4186void VBOXCALL   supdrvGipUpdate(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS)
     4187{
     4188    /*
     4189     * Determin the relevant CPU data.
     4190     */
     4191    PSUPGIPCPU pGipCpu;
     4192    if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC)
     4193        pGipCpu = &pGip->aCPUs[0];
     4194    else
     4195    {
     4196        unsigned iCpu = ASMGetApicId();
     4197        if (RT_LIKELY(iCpu >= RT_ELEMENTS(pGip->aCPUs)))
     4198            return;
     4199        pGipCpu = &pGip->aCPUs[iCpu];
     4200    }
     4201
     4202    /*
    40754203     * Start update transaction.
    40764204     */
    4077     if (!(ASMAtomicIncU32(&pGip->u32TransactionId) & 1))
     4205    if (!(ASMAtomicIncU32(&pGipCpu->u32TransactionId) & 1))
    40784206    {
    40794207        /* this can happen on win32 if we're taking to long and there are more CPUs around. shouldn't happen though. */
    4080         AssertMsgFailed(("Invalid transaction id, %#x, not odd!\n", pGip->u32TransactionId));
    4081         ASMAtomicIncU32(&pGip->u32TransactionId);
    4082         pGip->cErrors++;
     4208        AssertMsgFailed(("Invalid transaction id, %#x, not odd!\n", pGipCpu->u32TransactionId));
     4209        ASMAtomicIncU32(&pGipCpu->u32TransactionId);
     4210        pGipCpu->cErrors++;
    40834211        return;
    40844212    }
    40854213
    4086     ASMAtomicXchgU64(&pGip->u64NanoTS, u64NanoTS);
    4087 
    40884214    /*
    40894215     * Recalc the update frequency every 0x800th time.
    40904216     */
    4091     if (!(pGip->u32TransactionId & (GIP_UPDATEHZ_RECALC_FREQ * 2 - 2)))
     4217    if (!(pGipCpu->u32TransactionId & (GIP_UPDATEHZ_RECALC_FREQ * 2 - 2)))
    40924218    {
    40934219        if (pGip->u64NanoTSLastUpdateHz)
     
    41074233
    41084234    /*
    4109      * Calc TSC delta.
    4110      */
    4111     /** @todo validate the NanoTS delta, don't trust the OS to call us when it should... */
    4112     u64TSC = ASMReadTSC();
    4113     u64TSCDelta = u64TSC - pGip->u64TSC;
    4114     ASMAtomicXchgU64(&pGip->u64TSC, u64TSC);
    4115 
    4116     if (u64TSCDelta >> 32)
    4117     {
    4118         u64TSCDelta = pGip->u32UpdateIntervalTSC;
    4119         pGip->cErrors++;
    4120     }
    4121 
    4122     /*
    4123      * TSC History.
    4124      */
    4125     Assert(ELEMENTS(pGip->au32TSCHistory) == 8);
    4126 
    4127     iTSCHistoryHead = (pGip->iTSCHistoryHead + 1) & 7;
    4128     ASMAtomicXchgU32(&pGip->iTSCHistoryHead, iTSCHistoryHead);
    4129     ASMAtomicXchgU32(&pGip->au32TSCHistory[iTSCHistoryHead], (uint32_t)u64TSCDelta);
    4130 
    4131     /*
    4132      * UpdateIntervalTSC = average of last 8,2,1 intervals depending on update HZ.
    4133      */
    4134     if (pGip->u32UpdateHz >= 1000)
    4135     {
    4136         uint32_t u32;
    4137         u32  = pGip->au32TSCHistory[0];
    4138         u32 += pGip->au32TSCHistory[1];
    4139         u32 += pGip->au32TSCHistory[2];
    4140         u32 += pGip->au32TSCHistory[3];
    4141         u32 >>= 2;
    4142         u32UpdateIntervalTSC  = pGip->au32TSCHistory[4];
    4143         u32UpdateIntervalTSC += pGip->au32TSCHistory[5];
    4144         u32UpdateIntervalTSC += pGip->au32TSCHistory[6];
    4145         u32UpdateIntervalTSC += pGip->au32TSCHistory[7];
    4146         u32UpdateIntervalTSC >>= 2;
    4147         u32UpdateIntervalTSC += u32;
    4148         u32UpdateIntervalTSC >>= 1;
    4149 
    4150         /* Value choosen for a 2GHz Athlon64 running linux 2.6.10/11, . */
    4151         u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 14;
    4152     }
    4153     else if (pGip->u32UpdateHz >= 90)
    4154     {
    4155         u32UpdateIntervalTSC  = (uint32_t)u64TSCDelta;
    4156         u32UpdateIntervalTSC += pGip->au32TSCHistory[(iTSCHistoryHead - 1) & 7];
    4157         u32UpdateIntervalTSC >>= 1;
    4158 
    4159         /* value choosen on a 2GHz thinkpad running windows */
    4160         u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 7;
    4161     }
    4162     else
    4163     {
    4164         u32UpdateIntervalTSC  = (uint32_t)u64TSCDelta;
    4165 
    4166         /* This value hasn't be checked yet.. waiting for OS/2 and 33Hz timers.. :-) */
    4167         u32UpdateIntervalTSCSlack = u32UpdateIntervalTSC >> 6;
    4168     }
    4169     ASMAtomicXchgU32(&pGip->u32UpdateIntervalTSC, u32UpdateIntervalTSC + u32UpdateIntervalTSCSlack);
    4170 
    4171     /*
    4172      * CpuHz.
    4173      */
    4174     u64CpuHz = ASMMult2xU32RetU64(u32UpdateIntervalTSC, pGip->u32UpdateHz);
    4175     ASMAtomicXchgU64(&pGip->u64CpuHz, u64CpuHz);
     4235     * Update the data.
     4236     */
     4237    supdrvGipDoUpdateCpu(pGip, pGipCpu, u64NanoTS);
    41764238
    41774239    /*
    41784240     * Complete transaction.
    41794241     */
    4180     ASMAtomicIncU32(&pGip->u32TransactionId);
     4242    ASMAtomicIncU32(&pGipCpu->u32TransactionId);
     4243}
     4244
     4245
     4246/**
     4247 * Updates the per cpu GIP data for the calling cpu.
     4248 *
     4249 * @param   pGip        Pointer to the GIP.
     4250 * @param   u64NanoTS   The current nanosecond timesamp.
     4251 * @param   iCpu        The CPU index.
     4252 */
     4253void VBOXCALL   supdrvGipUpdatePerCpu(PSUPGLOBALINFOPAGE pGip, uint64_t u64NanoTS, unsigned iCpu)
     4254{
     4255    PSUPGIPCPU  pGipCpu;
     4256
     4257    if (RT_LIKELY(iCpu <= RT_ELEMENTS(pGip->aCPUs)))
     4258    {
     4259        pGipCpu = &pGip->aCPUs[iCpu];
     4260
     4261        /*
     4262         * Start update transaction.
     4263         */
     4264        if (!(ASMAtomicIncU32(&pGipCpu->u32TransactionId) & 1))
     4265        {
     4266            AssertMsgFailed(("Invalid transaction id, %#x, not odd!\n", pGipCpu->u32TransactionId));
     4267            ASMAtomicIncU32(&pGipCpu->u32TransactionId);
     4268            pGipCpu->cErrors++;
     4269            return;
     4270        }
     4271
     4272        /*
     4273         * Update the data.
     4274         */
     4275        supdrvGipDoUpdateCpu(pGip, pGipCpu, u64NanoTS);
     4276
     4277        /*
     4278         * Complete transaction.
     4279         */
     4280        ASMAtomicIncU32(&pGipCpu->u32TransactionId);
     4281    }
    41814282}
    41824283
  • trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c

    r876 r1027  
    13611361{
    13621362    PSUPDRVDEVEXT pDevExt  = (PSUPDRVDEVEXT)ulUser;
     1363    PSUPGLOBALINFOPAGE pGip = pDevExt->pGip;
    13631364    unsigned long ulNow    = jiffies;
    13641365    unsigned long ulDiff   = ulNow - pDevExt->ulLastJiffies;
     1366    uint64_t u64Monotime;
    13651367    pDevExt->ulLastJiffies = ulNow;
    13661368#ifdef TICK_NSEC
    1367     pDevExt->u64LastMonotime += ulDiff * TICK_NSEC;
     1369    u64Monotime = pDevExt->u64LastMonotime + ulDiff * TICK_NSEC;
    13681370#else
    1369     pDevExt->u64LastMonotime += ulDiff * (1000000 / HZ);
    1370 #endif
    1371     supdrvGipUpdate(pDevExt->pGip, pDevExt->u64LastMonotime);
     1371    u64Monotime = pDevExt->u64LastMonotime + ulDiff * (1000000 / HZ);
     1372#endif
     1373    ASMAtomicXchgU64(&pDevExt->u64LastMonotime, u64Monotime);
     1374    if (RT_LIKELY(pGip))
     1375    {
     1376#ifdef CONFIG_SMP
     1377        if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC)
     1378#endif
     1379            supdrvGipUpdate(pDevExt->pGip, u64Monotime);
     1380#ifdef CONFIG_SMP
     1381        else
     1382        {
     1383            smp_call_function(VBoxSupDrvGipPerCpu, pDevExt, 0 /* don't retry? */, 0 /* don't wait */);
     1384            supdrvGipUpdate(pDevExt->pGip, u64Monotime);
     1385        }
     1386#endif
     1387    }
    13721388    mod_timer(&g_GipTimer, jiffies + (HZ <= 1000 ? 0 : ONE_MSEC_IN_JIFFIES));
    13731389}
     1390
     1391
     1392#ifdef CONFIG_SMP
     1393/**
     1394 * smp_call_function callback.
     1395 * This is invoked on all the other CPUs.
     1396 *
     1397 * @param   pvUser  Pointer to the device extension.
     1398 */
     1399static void VBoxSupDrvGipPerCpu(void *pvUser)
     1400{
     1401    PSUPDRVDEVEXT pDevExt  = (PSUPDRVDEVEXT)ulUser;
     1402    PSUPGLOBALINFOPAGE pGip = pDevExt->pGip;
     1403    supdrvGipUpdatePerCpu(pGip, pDevExt->u64LastMonotime, ASMGetApicId());
     1404}
     1405#endif  /* CONFIG_SMP */
    13741406
    13751407
     
    14931525    if (timer_pending(&g_GipTimer))
    14941526        del_timer(&g_GipTimer);
     1527}
     1528
     1529
     1530/**
     1531 * Get the current CPU count.
     1532 * @returns Number of cpus.
     1533 */
     1534unsigned VBOXCALL supdrvOSGetCPUCount(void)
     1535{
     1536#ifdef CONFIG_SMP
     1537# ifdef num_present_cpus
     1538    return num_present_cpus();
     1539# else
     1540    return smp_num_cpus;
     1541# endif
     1542#else
     1543    return 1;
     1544#endif
    14951545}
    14961546
  • trunk/src/VBox/HostDrivers/Support/testcase/Makefile

    r1 r1027  
    6565tstPage_SOURCES       = $(VBOX_PATH_SUPPORT)/testcase/tstPage.cpp
    6666
    67 tstGIP-1_TEMPLATE     = VBOXR3TSTEXE
    68 tstGIP-1_SOURCES      = $(VBOX_PATH_SUPPORT)/testcase/tstGIP-1.c
    69 
    7067tstGIP-2_TEMPLATE     = VBOXR3TSTEXE
    7168tstGIP-2_SOURCES      = $(VBOX_PATH_SUPPORT)/testcase/tstGIP-2.cpp
  • trunk/src/VBox/HostDrivers/Support/testcase/tstGIP-2.cpp

    r1 r1027  
    5757                RTPrintf("tstGIP-2: %2d: %016llx %016llx %08x %d %08x %15llu %08x %08x %08x %08x %08x %08x %08x %08x\n",
    5858                         i,
    59                          g_pSUPGlobalInfoPage->u64NanoTS,
    60                          g_pSUPGlobalInfoPage->u64TSC,
    61                          g_pSUPGlobalInfoPage->u32UpdateIntervalTSC,
    62                          g_pSUPGlobalInfoPage->iTSCHistoryHead,
    63                          g_pSUPGlobalInfoPage->u32TransactionId,
    64                          g_pSUPGlobalInfoPage->u64CpuHz,
    65                          g_pSUPGlobalInfoPage->au32TSCHistory[0],
    66                          g_pSUPGlobalInfoPage->au32TSCHistory[1],
    67                          g_pSUPGlobalInfoPage->au32TSCHistory[2],
    68                          g_pSUPGlobalInfoPage->au32TSCHistory[3],
    69                          g_pSUPGlobalInfoPage->au32TSCHistory[4],
    70                          g_pSUPGlobalInfoPage->au32TSCHistory[5],
    71                          g_pSUPGlobalInfoPage->au32TSCHistory[6],
    72                          g_pSUPGlobalInfoPage->au32TSCHistory[7]);
     59                         g_pSUPGlobalInfoPage->aCPUs[0].u64NanoTS,
     60                         g_pSUPGlobalInfoPage->aCPUs[0].u64TSC,
     61                         g_pSUPGlobalInfoPage->aCPUs[0].u32UpdateIntervalTSC,
     62                         g_pSUPGlobalInfoPage->aCPUs[0].iTSCHistoryHead,
     63                         g_pSUPGlobalInfoPage->aCPUs[0].u32TransactionId,
     64                         g_pSUPGlobalInfoPage->aCPUs[0].u64CpuHz,
     65                         g_pSUPGlobalInfoPage->aCPUs[0].au32TSCHistory[0],
     66                         g_pSUPGlobalInfoPage->aCPUs[0].au32TSCHistory[1],
     67                         g_pSUPGlobalInfoPage->aCPUs[0].au32TSCHistory[2],
     68                         g_pSUPGlobalInfoPage->aCPUs[0].au32TSCHistory[3],
     69                         g_pSUPGlobalInfoPage->aCPUs[0].au32TSCHistory[4],
     70                         g_pSUPGlobalInfoPage->aCPUs[0].au32TSCHistory[5],
     71                         g_pSUPGlobalInfoPage->aCPUs[0].au32TSCHistory[6],
     72                         g_pSUPGlobalInfoPage->aCPUs[0].au32TSCHistory[7]);
    7373                RTThreadSleep(9);
    7474            }
  • trunk/src/VBox/HostDrivers/Support/win32/SUPDrv-win32.cpp

    r390 r1027  
    7070static void                VBoxSupDrvGipTerm(PSUPDRVDEVEXT pDevExt);
    7171static void     _stdcall   VBoxSupDrvGipTimer(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
     72static void     _stdcall   VBoxSupDrvGipPerCpuDpc(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
    7273
    7374
     
    789790                 */
    790791                KeInitializeTimerEx(&pDevExt->GipTimer, SynchronizationTimer);
    791                 KeInitializeDpc(&pDevExt->GipDpc, VBoxSupDrvGipTimer, pGip);
     792                KeInitializeDpc(&pDevExt->GipDpc, VBoxSupDrvGipTimer, pDevExt);
     793
     794                /*
     795                 * Initialize the DPCs we're using to update the per-cpu GIP data.
     796                 * (Not sure if we need to be this careful with KeSetTargetProcessorDpc...)
     797                 */
     798                UNICODE_STRING  RoutineName;
     799                RtlInitUnicodeString(&RoutineName, L"KeSetTargetProcessorDpc");
     800                VOID (*pfnKeSetTargetProcessorDpc)(IN PRKDPC, IN CCHAR) = (VOID (*)(IN PRKDPC, IN CCHAR))MmGetSystemRoutineAddress(&RoutineName);
     801
     802                for (unsigned i = 0; i < RT_ELEMENTS(pDevExt->aGipCpuDpcs); i++)
     803                {
     804                    KeInitializeDpc(&pDevExt->aGipCpuDpcs[i], VBoxSupDrvGipPerCpuDpc, pGip);
     805                    KeSetImportanceDpc(&pDevExt->aGipCpuDpcs[i], HighImportance);
     806                    if (pfnKeSetTargetProcessorDpc)
     807                        pfnKeSetTargetProcessorDpc(&pDevExt->aGipCpuDpcs[i], i);
     808                }
     809
    792810                dprintf(("VBoxSupDrvGipInit: ulClockFreq=%ld ulClockInterval=%ld ulClockIntervalActual=%ld Phys=%x%08x\n",
    793811                         ulClockFreq, ulClockInterval, ulClockIntervalActual, Phys.HighPart, Phys.LowPart));
    794812                return STATUS_SUCCESS;
    795813            }
    796             else
    797             {
    798                 dprintf(("VBoxSupDrvInitGip: IoAllocateMdl failed for %p/PAGE_SIZE\n", pGip));
    799                 rc = STATUS_NO_MEMORY;
    800             }
     814
     815            dprintf(("VBoxSupDrvInitGip: IoAllocateMdl failed for %p/PAGE_SIZE\n", pGip));
     816            rc = STATUS_NO_MEMORY;
    801817        }
    802818        else
     
    863879/**
    864880 * Timer callback function.
    865  * The ulUser parameter is the GIP pointer.
    866  */
    867 static void __stdcall VBoxSupDrvGipTimer(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
     881 * The pvUser parameter is the pDevExt pointer.
     882 */
     883static void _stdcall VBoxSupDrvGipTimer(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
     884{
     885    PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pvUser;
     886    PSUPGLOBALINFOPAGE pGip = pDevExt->pGip;
     887    if (pGip)
     888    {
     889        if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC)
     890            supdrvGipUpdate(pGip, supdrvOSMonotime());
     891        else
     892        {
     893            RTCCUINTREG xFL = ASMGetFlags();
     894            ASMIntDisable();
     895
     896            /*
     897             * We cannot do other than assume a 1:1 relation ship between the
     898             * affinity mask and the process despite the warnings in the docs.
     899             * If someone knows a better way to get this done, please let bird know.
     900             */
     901            unsigned iSelf = KeGetCurrentProcessorNumber();
     902            KAFFINITY Mask = KeQueryActiveProcessors();
     903
     904            for (unsigned i = 0; i < RT_ELEMENTS(pDevExt->aGipCpuDpcs); i++)
     905            {
     906                if (    i != iSelf
     907                    &&  (Mask & (1 << i)))
     908                    KeInsertQueueDpc(&pDevExt->aGipCpuDpcs[i], 0, 0);
     909            }
     910
     911            /* Run the normal update. */
     912            supdrvGipUpdate(pGip, supdrvOSMonotime());
     913
     914            ASMSetFlags(xFL);
     915        }
     916    }
     917}
     918
     919
     920/**
     921 * Per cpu callback callback function.
     922 * The pvUser parameter is the pGip pointer.
     923 */
     924static void _stdcall VBoxSupDrvGipPerCpuDpc(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
    868925{
    869926    PSUPGLOBALINFOPAGE pGip = (PSUPGLOBALINFOPAGE)pvUser;
    870     supdrvGipUpdate(pGip, supdrvOSMonotime());
     927    supdrvGipUpdatePerCpu(pGip, supdrvOSMonotime(), ASMGetApicId());
    871928}
    872929
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