VirtualBox

Ignore:
Timestamp:
Oct 15, 2016 4:46:29 PM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
111296
Message:

IPRT,SUP: Major vboxdrv and GIP version change; more flexible processor group handling on Windows.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/SUPDrvGip.cpp

    r64260 r64281  
    13201320    pGip->aCPUs[i].iCpuGroupMember = iCpuSet;
    13211321#ifdef RT_OS_WINDOWS
    1322     pGip->aCPUs[i].iCpuGroup = supdrvOSGipGetGroupFromCpu(pDevExt, idCpu, &pGip->aCPUs[i].iCpuGroupMember);
     1322    supdrvOSGipInitGroupBitsForCpu(pDevExt, pGip, &pGip->aCPUs[i]);
    13231323#endif
    13241324
     
    17441744 * Initializes the GIP data.
    17451745 *
     1746 * @returns VBox status code.
    17461747 * @param   pDevExt             Pointer to the device instance data.
    17471748 * @param   pGip                Pointer to the read-write kernel mapping of the GIP.
     
    17511752 * @param   uUpdateIntervalNS   The update interval in nanoseconds.
    17521753 * @param   cCpus               The CPU count.
    1753  */
    1754 static void supdrvGipInit(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, RTHCPHYS HCPhys,
    1755                           uint64_t u64NanoTS, unsigned uUpdateHz, unsigned uUpdateIntervalNS, unsigned cCpus)
    1756 {
    1757     size_t const    cbGip = RT_ALIGN_Z(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[cCpus]), PAGE_SIZE);
    1758     unsigned        i;
     1754 * @param   cbGipCpuGroups      The supdrvOSGipGetGroupTableSize return value we
     1755 *                              used when allocating the GIP structure.
     1756 */
     1757static int supdrvGipInit(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, RTHCPHYS HCPhys,
     1758                         uint64_t u64NanoTS, unsigned uUpdateHz, unsigned uUpdateIntervalNS,
     1759                         unsigned cCpus, size_t cbGipCpuGroups)
     1760{
     1761    size_t const cbGip = RT_ALIGN_Z(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[cCpus]) + cbGipCpuGroups, PAGE_SIZE);
     1762    unsigned i;
    17591763#ifdef DEBUG_DARWIN_GIP
    17601764    OSDBGPRINT(("supdrvGipInit: pGip=%p HCPhys=%lx u64NanoTS=%llu uUpdateHz=%d cCpus=%u\n", pGip, (long)HCPhys, u64NanoTS, uUpdateHz, cCpus));
     
    17941798    for (i = 0; i < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx); i++)
    17951799        pGip->aiCpuFromCpuSetIdx[i] = UINT16_MAX;
    1796     pGip->aiFirstCpuSetIdxFromCpuGroup[0] = 0;
    1797     for (i = 1; i < RT_ELEMENTS(pGip->aiFirstCpuSetIdxFromCpuGroup); i++)
    1798         pGip->aiFirstCpuSetIdxFromCpuGroup[i] = UINT16_MAX;
    1799 #ifdef RT_OS_WINDOWS
    1800     supdrvOSInitGipGroupTable(pDevExt, pGip);
    1801 #endif
     1800    for (i = 0; i < RT_ELEMENTS(pGip->aoffCpuGroup); i++)
     1801        pGip->aoffCpuGroup[i] = UINT16_MAX;
    18021802    for (i = 0; i < cCpus; i++)
    18031803        supdrvGipInitCpu(pGip, &pGip->aCPUs[i], u64NanoTS, 0 /*uCpuHz*/);
     1804#ifdef RT_OS_WINDOWS
     1805    int rc = supdrvOSInitGipGroupTable(pDevExt, pGip, cbGipCpuGroups);
     1806    AssertRCReturn(rc, rc);
     1807#endif
    18041808
    18051809    /*
     
    18091813    pDevExt->HCPhysGip = HCPhys;
    18101814    pDevExt->cGipUsers = 0;
     1815
     1816    return VINF_SUCCESS;
    18111817}
    18121818
     
    18211827{
    18221828    PSUPGLOBALINFOPAGE  pGip;
     1829    size_t              cbGip;
     1830    size_t              cbGipCpuGroups;
    18231831    RTHCPHYS            HCPhysGip;
    18241832    uint32_t            u32SystemResolution;
     
    18621870     * Allocate a contiguous set of pages with a default kernel mapping.
    18631871     */
    1864     rc = RTR0MemObjAllocCont(&pDevExt->GipMemObj, RT_UOFFSETOF(SUPGLOBALINFOPAGE, aCPUs[cCpus]), false /*fExecutable*/);
     1872    cbGipCpuGroups = supdrvOSGipGetGroupTableSize(pDevExt);
     1873    cbGip = RT_UOFFSETOF(SUPGLOBALINFOPAGE, aCPUs[cCpus]) + cbGipCpuGroups;
     1874    rc = RTR0MemObjAllocCont(&pDevExt->GipMemObj, cbGip, false /*fExecutable*/);
    18651875    if (RT_FAILURE(rc))
    18661876    {
     
    18841894        u32Interval += u32SystemResolution - uMod;
    18851895
    1886     supdrvGipInit(pDevExt, pGip, HCPhysGip, RTTimeSystemNanoTS(), RT_NS_1SEC / u32Interval /*=Hz*/, u32Interval, cCpus);
    1887 
    1888     /*
    1889      * Important sanity check...
     1896    rc = supdrvGipInit(pDevExt, pGip, HCPhysGip, RTTimeSystemNanoTS(), RT_NS_1SEC / u32Interval /*=Hz*/, u32Interval,
     1897                       cCpus, cbGipCpuGroups);
     1898
     1899    /*
     1900     * Important sanity check...  (Sets rc)
    18901901     */
    18911902    if (RT_UNLIKELY(   pGip->enmUseTscDelta == SUPGIPUSETSCDELTA_ZERO_CLAIMED
     
    18941905    {
    18951906        OSDBGPRINT(("supdrvGipCreate: Host-OS/user claims the TSC-deltas are zero but we detected async. TSC! Bad.\n"));
    1896         return VERR_INTERNAL_ERROR_2;
     1907        rc = VERR_INTERNAL_ERROR_2;
    18971908    }
    18981909
    18991910    /* It doesn't make sense to do TSC-delta detection on systems we detect as async. */
    1900     AssertReturn(   pGip->u32Mode != SUPGIPMODE_ASYNC_TSC
    1901                  || pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ZERO_CLAIMED, VERR_INTERNAL_ERROR_3);
     1911    AssertStmt(   pGip->u32Mode != SUPGIPMODE_ASYNC_TSC
     1912               || pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ZERO_CLAIMED,
     1913               rc = VERR_INTERNAL_ERROR_3);
    19021914
    19031915    /*
     
    19121924     * array with more reasonable values.
    19131925     */
    1914     if (pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC)
    1915     {
    1916         rc = supdrvGipInitMeasureTscFreq(pGip, true /*fRough*/); /* cannot fail */
    1917         supdrvGipInitStartTimerForRefiningInvariantTscFreq(pDevExt);
    1918     }
    1919     else
    1920         rc = supdrvGipInitMeasureTscFreq(pGip, false /*fRough*/);
    19211926    if (RT_SUCCESS(rc))
    19221927    {
    1923         /*
    1924          * Start TSC-delta measurement thread before we start getting MP
    1925          * events that will try kick it into action (includes the
    1926          * RTMpOnAll/supdrvGipInitOnCpu call below).
    1927          */
    1928         RTCpuSetEmpty(&pDevExt->TscDeltaCpuSet);
    1929         RTCpuSetEmpty(&pDevExt->TscDeltaObtainedCpuSet);
    1930 #ifdef SUPDRV_USE_TSC_DELTA_THREAD
    1931         if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED)
    1932             rc = supdrvTscDeltaThreadInit(pDevExt);
    1933 #endif
     1928        if (pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC)
     1929        {
     1930            rc = supdrvGipInitMeasureTscFreq(pGip, true /*fRough*/); /* cannot fail */
     1931            supdrvGipInitStartTimerForRefiningInvariantTscFreq(pDevExt);
     1932        }
     1933        else
     1934            rc = supdrvGipInitMeasureTscFreq(pGip, false /*fRough*/);
    19341935        if (RT_SUCCESS(rc))
    19351936        {
    1936             rc = RTMpNotificationRegister(supdrvGipMpEvent, pDevExt);
     1937            /*
     1938             * Start TSC-delta measurement thread before we start getting MP
     1939             * events that will try kick it into action (includes the
     1940             * RTMpOnAll/supdrvGipInitOnCpu call below).
     1941             */
     1942            RTCpuSetEmpty(&pDevExt->TscDeltaCpuSet);
     1943            RTCpuSetEmpty(&pDevExt->TscDeltaObtainedCpuSet);
     1944    #ifdef SUPDRV_USE_TSC_DELTA_THREAD
     1945            if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED)
     1946                rc = supdrvTscDeltaThreadInit(pDevExt);
     1947    #endif
    19371948            if (RT_SUCCESS(rc))
    19381949            {
    1939                 /*
    1940                  * Do GIP initialization on all online CPUs.  Wake up the
    1941                  * TSC-delta thread afterwards.
    1942                  */
    1943                 rc = RTMpOnAll(supdrvGipInitOnCpu, pDevExt, pGip);
     1950                rc = RTMpNotificationRegister(supdrvGipMpEvent, pDevExt);
    19441951                if (RT_SUCCESS(rc))
    19451952                {
    1946 #ifdef SUPDRV_USE_TSC_DELTA_THREAD
    1947                     supdrvTscDeltaThreadStartMeasurement(pDevExt, true /* fForceAll */);
    1948 #else
    1949                     uint16_t iCpu;
    1950                     if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED)
     1953                    /*
     1954                     * Do GIP initialization on all online CPUs.  Wake up the
     1955                     * TSC-delta thread afterwards.
     1956                     */
     1957                    rc = RTMpOnAll(supdrvGipInitOnCpu, pDevExt, pGip);
     1958                    if (RT_SUCCESS(rc))
    19511959                    {
    1952                         /*
    1953                          * Measure the TSC deltas now that we have MP notifications.
    1954                          */
    1955                         int cTries = 5;
    1956                         do
     1960    #ifdef SUPDRV_USE_TSC_DELTA_THREAD
     1961                        supdrvTscDeltaThreadStartMeasurement(pDevExt, true /* fForceAll */);
     1962    #else
     1963                        uint16_t iCpu;
     1964                        if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED)
    19571965                        {
    1958                             rc = supdrvTscMeasureInitialDeltas(pDevExt);
    1959                             if (   rc != VERR_TRY_AGAIN
    1960                                 && rc != VERR_CPU_OFFLINE)
    1961                                 break;
    1962                         } while (--cTries > 0);
    1963                         for (iCpu = 0; iCpu < pGip->cCpus; iCpu++)
    1964                             Log(("supdrvTscDeltaInit: cpu[%u] delta %lld\n", iCpu, pGip->aCPUs[iCpu].i64TSCDelta));
     1966                            /*
     1967                             * Measure the TSC deltas now that we have MP notifications.
     1968                             */
     1969                            int cTries = 5;
     1970                            do
     1971                            {
     1972                                rc = supdrvTscMeasureInitialDeltas(pDevExt);
     1973                                if (   rc != VERR_TRY_AGAIN
     1974                                    && rc != VERR_CPU_OFFLINE)
     1975                                    break;
     1976                            } while (--cTries > 0);
     1977                            for (iCpu = 0; iCpu < pGip->cCpus; iCpu++)
     1978                                Log(("supdrvTscDeltaInit: cpu[%u] delta %lld\n", iCpu, pGip->aCPUs[iCpu].i64TSCDelta));
     1979                        }
     1980                        else
     1981                        {
     1982                            for (iCpu = 0; iCpu < pGip->cCpus; iCpu++)
     1983                                AssertMsg(!pGip->aCPUs[iCpu].i64TSCDelta, ("iCpu=%u %lld mode=%d\n", iCpu, pGip->aCPUs[iCpu].i64TSCDelta, pGip->u32Mode));
     1984                        }
     1985                        if (RT_SUCCESS(rc))
     1986    #endif
     1987                        {
     1988                            /*
     1989                             * Create the timer.
     1990                             * If CPU_ALL isn't supported we'll have to fall back to synchronous mode.
     1991                             */
     1992                            if (pGip->u32Mode == SUPGIPMODE_ASYNC_TSC)
     1993                            {
     1994                                rc = RTTimerCreateEx(&pDevExt->pGipTimer, u32Interval, RTTIMER_FLAGS_CPU_ALL,
     1995                                                     supdrvGipAsyncTimer, pDevExt);
     1996                                if (rc == VERR_NOT_SUPPORTED)
     1997                                {
     1998                                    OSDBGPRINT(("supdrvGipCreate: omni timer not supported, falling back to synchronous mode\n"));
     1999                                    pGip->u32Mode = SUPGIPMODE_SYNC_TSC;
     2000                                }
     2001                            }
     2002                            if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC)
     2003                                rc = RTTimerCreateEx(&pDevExt->pGipTimer, u32Interval, 0 /* fFlags */,
     2004                                                     supdrvGipSyncAndInvariantTimer, pDevExt);
     2005                            if (RT_SUCCESS(rc))
     2006                            {
     2007                                /*
     2008                                 * We're good.
     2009                                 */
     2010                                Log(("supdrvGipCreate: %u ns interval.\n", u32Interval));
     2011                                supdrvGipReleaseHigherTimerFrequencyFromSystem(pDevExt);
     2012
     2013                                g_pSUPGlobalInfoPage = pGip;
     2014                                return VINF_SUCCESS;
     2015                            }
     2016
     2017                            OSDBGPRINT(("supdrvGipCreate: failed create GIP timer at %u ns interval. rc=%Rrc\n", u32Interval, rc));
     2018                            Assert(!pDevExt->pGipTimer);
     2019                        }
    19652020                    }
    19662021                    else
    1967                     {
    1968                         for (iCpu = 0; iCpu < pGip->cCpus; iCpu++)
    1969                             AssertMsg(!pGip->aCPUs[iCpu].i64TSCDelta, ("iCpu=%u %lld mode=%d\n", iCpu, pGip->aCPUs[iCpu].i64TSCDelta, pGip->u32Mode));
    1970                     }
    1971                     if (RT_SUCCESS(rc))
    1972 #endif
    1973                     {
    1974                         /*
    1975                          * Create the timer.
    1976                          * If CPU_ALL isn't supported we'll have to fall back to synchronous mode.
    1977                          */
    1978                         if (pGip->u32Mode == SUPGIPMODE_ASYNC_TSC)
    1979                         {
    1980                             rc = RTTimerCreateEx(&pDevExt->pGipTimer, u32Interval, RTTIMER_FLAGS_CPU_ALL,
    1981                                                  supdrvGipAsyncTimer, pDevExt);
    1982                             if (rc == VERR_NOT_SUPPORTED)
    1983                             {
    1984                                 OSDBGPRINT(("supdrvGipCreate: omni timer not supported, falling back to synchronous mode\n"));
    1985                                 pGip->u32Mode = SUPGIPMODE_SYNC_TSC;
    1986                             }
    1987                         }
    1988                         if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC)
    1989                             rc = RTTimerCreateEx(&pDevExt->pGipTimer, u32Interval, 0 /* fFlags */,
    1990                                                  supdrvGipSyncAndInvariantTimer, pDevExt);
    1991                         if (RT_SUCCESS(rc))
    1992                         {
    1993                             /*
    1994                              * We're good.
    1995                              */
    1996                             Log(("supdrvGipCreate: %u ns interval.\n", u32Interval));
    1997                             supdrvGipReleaseHigherTimerFrequencyFromSystem(pDevExt);
    1998 
    1999                             g_pSUPGlobalInfoPage = pGip;
    2000                             return VINF_SUCCESS;
    2001                         }
    2002 
    2003                         OSDBGPRINT(("supdrvGipCreate: failed create GIP timer at %u ns interval. rc=%Rrc\n", u32Interval, rc));
    2004                         Assert(!pDevExt->pGipTimer);
    2005                     }
     2022                        OSDBGPRINT(("supdrvGipCreate: RTMpOnAll failed. rc=%Rrc\n", rc));
    20062023                }
    20072024                else
    2008                     OSDBGPRINT(("supdrvGipCreate: RTMpOnAll failed. rc=%Rrc\n", rc));
     2025                    OSDBGPRINT(("supdrvGipCreate: failed to register MP event notfication. rc=%Rrc\n", rc));
    20092026            }
    20102027            else
    2011                 OSDBGPRINT(("supdrvGipCreate: failed to register MP event notfication. rc=%Rrc\n", rc));
     2028                OSDBGPRINT(("supdrvGipCreate: supdrvTscDeltaInit failed. rc=%Rrc\n", rc));
    20122029        }
    20132030        else
    2014             OSDBGPRINT(("supdrvGipCreate: supdrvTscDeltaInit failed. rc=%Rrc\n", rc));
    2015     }
    2016     else
    2017         OSDBGPRINT(("supdrvGipCreate: supdrvTscMeasureInitialDeltas failed. rc=%Rrc\n", rc));
     2031            OSDBGPRINT(("supdrvGipCreate: supdrvTscMeasureInitialDeltas failed. rc=%Rrc\n", rc));
     2032    }
    20182033
    20192034    /* Releases timer frequency increase too. */
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