VirtualBox

Changeset 7869 in vbox


Ignore:
Timestamp:
Apr 10, 2008 12:39:02 PM (17 years ago)
Author:
vboxsync
Message:

Linux: detect asynchronous TSCs

File:
1 edited

Legend:

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

    r7521 r7869  
    4141#include <iprt/mem.h>
    4242#include <iprt/log.h>
     43#include <iprt/mp.h>
    4344
    4445#include <linux/sched.h>
     
    462463# endif /* DO_DISABLE_NMI */
    463464#endif /* CONFIG_X86_LOCAL_APIC */
     465
     466
     467/**
     468 * Determine if the time stamp counters of the CPU cores are asynchronous.
     469 */
     470static uint64_t g_aTsc[8][8];
     471
     472static DECLCALLBACK(void) Worker(RTCPUID idCpu, void *pvUser1, void *pvUser2)
     473{
     474    int iSlot = *(int*)pvUser1;
     475    int iCpu  = *(int*)pvUser2;
     476    g_aTsc[iSlot][iCpu] = ASMReadTSC();
     477}
     478
     479/*
     480 * When using the default/normal timer code it is essential that the time stamp counter
     481 * (TSC) runs never backwards, that is, a read operation to the counter should return
     482 * a bigger value than any previous read operation. This is guaranteed by the latest
     483 * AMD CPUs and by newer Intel CPUs which never enter the C2 state (P4). In any other
     484 * case we have to choose the asynchronous timer mode.
     485 */
     486static void VBoxDetermineAsyncTsc(void)
     487{
     488    uint64_t u64Diff, u64DiffMin, u64DiffMax, u64TscLast;
     489    int iSlot, iCpu;
     490    bool fBackwards = false;
     491    int cCpu = RTMpGetOnlineCount();
     492
     493    printk(KERN_DEBUG DEVICE_NAME ": Found %u cores.\n", cCpu);
     494    if (cCpu < 2)
     495        return;
     496
     497    if (cCpu > RT_ELEMENTS(g_aTsc))
     498        cCpu = RT_ELEMENTS(g_aTsc);
     499
     500    for (iSlot = 0; iSlot < RT_ELEMENTS(g_aTsc); iSlot++)
     501    {
     502        for (iCpu = 0; iCpu < cCpu; iCpu++)
     503            RTMpOnSpecific(iCpu, Worker, &iSlot, &iCpu);
     504    }
     505
     506    u64DiffMin = (uint64_t)~0;
     507    u64TscLast = 0;
     508    for (iSlot = 0; iSlot < RT_ELEMENTS(g_aTsc); iSlot++)
     509    {
     510        uint64_t u64Tsc0 = g_aTsc[iSlot][0];
     511        u64DiffMax = 0;
     512        if (u64Tsc0 <= u64TscLast)
     513            fBackwards = true;
     514        u64TscLast = u64Tsc0;
     515        for (iCpu = 1; iCpu < cCpu; iCpu++)
     516        {
     517            uint64_t u64TscN = g_aTsc[iSlot][iCpu];
     518            if (u64TscN <= u64TscLast)
     519                fBackwards = true;
     520            u64TscLast = u64TscN;
     521            u64Diff = u64TscN > u64Tsc0 ? u64TscN - u64Tsc0 : u64Tsc0 - u64TscN;
     522            if (u64DiffMax < u64Diff)
     523                u64DiffMax = u64Diff;
     524        }
     525        if (u64DiffMin > u64DiffMax)
     526            u64DiffMin = u64DiffMax;
     527    }
     528    /* Don't depend on 64-bit arithmetics in the printk code. We assume that the difference between both
     529     * cores is smaller than 2^32. */
     530    printk(KERN_DEBUG DEVICE_NAME ": fBackwards=%d u64DiffMin=%u.\n", fBackwards, (uint32_t)u64DiffMin);
     531    if (fBackwards)
     532        force_async_tsc = 1;
     533}
    464534
    465535/**
     
    590660#endif /* CONFIG_X86_LOCAL_APIC */
    591661
     662    /*
     663     * Check for synchronous/asynchronous TSC mode.
     664     */
     665    VBoxDetermineAsyncTsc();
     666
    592667#ifdef CONFIG_VBOXDRV_AS_MISC
    593668    rc = misc_register(&gMiscDevice);
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