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.

Location:
trunk/src/VBox/HostDrivers/Support
Files:
5 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. */
  • trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h

    r64255 r64281  
    215215 *          - nothing.
    216216 */
    217 #define SUPDRV_IOC_VERSION                              0x00270000
     217#define SUPDRV_IOC_VERSION                              0x00280000
    218218
    219219/** SUP_IOCTL_COOKIE. */
  • trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h

    r64255 r64281  
    801801
    802802/**
     803 * Called during GIP initializtion to calc the CPU group table size.
     804 *
     805 * This is currently only implemented on windows [lazy bird].
     806 *
     807 * @returns Number of bytes needed for SUPGIPCPUGROUP structures.
     808 * @param   pDevExt             The device globals.
     809 */
     810size_t VBOXCALL supdrvOSGipGetGroupTableSize(PSUPDRVDEVEXT pDevExt);
     811
     812/**
    803813 * Called during GIP initialization to set up the group table and group count.
    804814 *
     
    808818 * @param   pGip                The GIP which group table needs initialization.
    809819 *                              It's only partially initialized at this point.
    810  */
    811 void VBOXCALL   supdrvOSInitGipGroupTable(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip);
    812 
    813 /**
    814  * Gets the CPU group and member indexes for the given CPU ID.
     820 * @param   cbGipCpuGroups      What supdrvOSGipGetGroupTableSize returned.
     821 */
     822int VBOXCALL    supdrvOSInitGipGroupTable(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, size_t cbGipCpuGroups);
     823
     824/**
     825 * Initializes the group related members when a CPU is added to the GIP.
     826 *
     827 * This is called both during GIP initalization and during an CPU online event.
    815828 *
    816829 * This is currently only implemented on windows [lazy bird].
     
    821834 * @param   piCpuGroupMember    Where to return the group member number.
    822835 */
    823 uint16_t VBOXCALL supdrvOSGipGetGroupFromCpu(PSUPDRVDEVEXT pDevExt, RTCPUID idCpu, uint16_t *piCpuGroupMember);
     836void VBOXCALL supdrvOSGipInitGroupBitsForCpu(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, PSUPGIPCPU pGipCpu);
    824837
    825838void VBOXCALL   supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession);
  • trunk/src/VBox/HostDrivers/Support/testcase/tstGIP-2.cpp

    r64255 r64281  
    137137                     g_pSUPGlobalInfoPage->u32Version,
    138138                     g_pSUPGlobalInfoPage->fGetGipCpu);
    139             RTPrintf("tstGIP-2: cCpus=%d  cPossibleCpus=%d cPossibleCpuGroups=%d cPresentCpus=%d cOnlineCpus=%d\n",
     139            RTPrintf("tstGIP-2: cCpus=%d  cPossibleCpus=%d cPossibleCpuGroups=%d cPresentCpus=%d cOnlineCpus=%d idCpuMax=%#x\n",
    140140                     g_pSUPGlobalInfoPage->cCpus,
    141141                     g_pSUPGlobalInfoPage->cPossibleCpus,
    142142                     g_pSUPGlobalInfoPage->cPossibleCpuGroups,
    143143                     g_pSUPGlobalInfoPage->cPresentCpus,
    144                      g_pSUPGlobalInfoPage->cOnlineCpus);
     144                     g_pSUPGlobalInfoPage->cOnlineCpus,
     145                     g_pSUPGlobalInfoPage->idCpuMax);
    145146            RTPrintf("tstGIP-2: u32UpdateHz=%RU32  u32UpdateIntervalNS=%RU32  u64NanoTSLastUpdateHz=%RX64  u64CpuHz=%RU64  uCpuHzRef=%RU64\n",
    146147                     g_pSUPGlobalInfoPage->u32UpdateHz,
     
    149150                     g_pSUPGlobalInfoPage->u64CpuHz,
    150151                     uCpuHzRef);
     152            for (uint32_t iCpu = 0; iCpu < g_pSUPGlobalInfoPage->cCpus; iCpu++)
     153                if (g_pSUPGlobalInfoPage->aCPUs[iCpu].enmState != SUPGIPCPUSTATE_INVALID)
     154                {
     155                    SUPGIPCPU const *pGipCpu = &g_pSUPGlobalInfoPage->aCPUs[iCpu];
     156                    RTPrintf("tstGIP-2: aCPU[%u]: enmState=%d iCpuSet=%u idCpu=%#010x iCpuGroup=%u iCpuGroupMember=%u idApic=%#x\n",
     157                             iCpu, pGipCpu->enmState, pGipCpu->iCpuSet, pGipCpu->idCpu, pGipCpu->iCpuGroup,
     158                             pGipCpu->iCpuGroupMember, pGipCpu->idApic);
     159                }
    151160
    152161            RTPrintf(fHex
  • trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp

    r64255 r64281  
    17111711
    17121712
    1713 void VBOXCALL supdrvOSInitGipGroupTable(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip)
     1713size_t VBOXCALL supdrvOSGipGetGroupTableSize(PSUPDRVDEVEXT pDevExt)
    17141714{
    17151715    NOREF(pDevExt);
     1716    uint32_t cMaxCpus = RTMpGetCount();
     1717    uint32_t cGroups  = RTMpGetMaxCpuGroupCount();
     1718
     1719    return cGroups * RT_OFFSETOF(SUPGIPCPUGROUP, aiCpuSetIdxs)
     1720         + RT_SIZEOFMEMB(SUPGIPCPUGROUP, aiCpuSetIdxs[0]) * cMaxCpus;
     1721}
     1722
     1723
     1724int VBOXCALL supdrvOSInitGipGroupTable(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, size_t cbGipCpuGroups)
     1725{
     1726    Assert(cbGipCpuGroups > 0); NOREF(cbGipCpuGroups); NOREF(pDevExt);
     1727
     1728    unsigned const  cGroups = RTMpGetMaxCpuGroupCount();
     1729    AssertReturn(cGroups > 0 && cGroups < RT_ELEMENTS(pGip->aoffCpuGroup), VERR_INTERNAL_ERROR_2);
     1730    pGip->cPossibleCpuGroups = cGroups;
     1731
     1732    PSUPGIPCPUGROUP pGroup = (PSUPGIPCPUGROUP)&pGip->aCPUs[pGip->cCpus];
     1733    for (uint32_t idxGroup = 0; idxGroup < cGroups; idxGroup++)
     1734    {
     1735        uint32_t cActive  = 0;
     1736        uint32_t cMax     = RTMpGetCpuGroupCounts(idxGroup, &cActive);
     1737        uint32_t cbNeeded = RT_OFFSETOF(SUPGIPCPUGROUP, aiCpuSetIdxs[cMax]);
     1738        AssertReturn(cbNeeded <= cbGipCpuGroups, VERR_INTERNAL_ERROR_3);
     1739        AssertReturn(cActive <= cMax, VERR_INTERNAL_ERROR_4);
     1740
     1741        pGip->aoffCpuGroup[idxGroup] = (uint16_t)((uintptr_t)pGroup - (uintptr_t)pGip);
     1742        pGroup->cMembers    = cActive;
     1743        pGroup->cMaxMembers = cMax;
     1744        for (uint32_t idxMember = 0; idxMember < cMax; idxMember++)
     1745        {
     1746            pGroup->aiCpuSetIdxs[idxMember] = RTMpSetIndexFromCpuGroupMember(idxGroup, idxMember);
     1747            Assert((unsigned)pGroup->aiCpuSetIdxs[idxMember] < pGip->cPossibleCpus);
     1748        }
     1749
     1750        /* advance. */
     1751        cbGipCpuGroups -= cbNeeded;
     1752        pGroup = (PSUPGIPCPUGROUP)&pGroup->aiCpuSetIdxs[cMax];
     1753    }
     1754
     1755    return VINF_SUCCESS;
     1756}
     1757
     1758
     1759void VBOXCALL supdrvOSGipInitGroupBitsForCpu(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, PSUPGIPCPU pGipCpu)
     1760{
     1761    NOREF(pDevExt);
    17161762
    17171763    /*
    1718      * The indexes are assigned in group order (see initterm-r0drv-nt.cpp).
     1764     * Translate the CPU index into a group and member.
    17191765     */
    1720     if (   g_pfnKeQueryMaximumGroupCount
    1721         && g_pfnKeGetProcessorIndexFromNumber)
    1722     {
    1723         unsigned cGroups = g_pfnKeQueryMaximumGroupCount();
    1724         AssertStmt(cGroups > 0, cGroups = 1);
    1725         AssertStmt(cGroups < RT_ELEMENTS(pGip->aiFirstCpuSetIdxFromCpuGroup),
    1726                    cGroups = RT_ELEMENTS(pGip->aiFirstCpuSetIdxFromCpuGroup));
    1727         pGip->cPossibleCpuGroups = cGroups;
    1728 
    1729         KEPROCESSORINDEX idxCpuMin = 0;
    1730         for (unsigned iGroup = 0; iGroup < cGroups; iGroup++)
    1731         {
    1732             PROCESSOR_NUMBER ProcNum;
    1733             ProcNum.Group    = (USHORT)iGroup;
    1734             ProcNum.Number   = 0;
    1735             ProcNum.Reserved = 0;
    1736             KEPROCESSORINDEX idxCpu = g_pfnKeGetProcessorIndexFromNumber(&ProcNum);
    1737             Assert(idxCpu != INVALID_PROCESSOR_INDEX);
    1738             Assert(idxCpu >= idxCpuMin);
    1739             idxCpuMin = idxCpu;
    1740             pGip->aiFirstCpuSetIdxFromCpuGroup[iGroup] = (uint16_t)idxCpu;
    1741         }
    1742     }
    1743     else
    1744     {
    1745         Assert(!g_pfnKeQueryMaximumGroupCount);
    1746         Assert(!g_pfnKeGetProcessorIndexFromNumber);
    1747 
    1748         pGip->cPossibleCpuGroups              = 1;
    1749         pGip->aiFirstCpuSetIdxFromCpuGroup[0] = 0;
    1750     }
    1751 }
    1752 
    1753 
    1754 uint16_t VBOXCALL supdrvOSGipGetGroupFromCpu(PSUPDRVDEVEXT pDevExt, RTCPUID idCpu, uint16_t *piCpuGroupMember)
    1755 {
    1756     NOREF(pDevExt);
     1766    PROCESSOR_NUMBER ProcNum = { 0, pGipCpu->iCpuSet, 0 };
     1767    if (g_pfnKeGetProcessorNumberFromIndex)
     1768    {
     1769        NTSTATUS rcNt = g_pfnKeGetProcessorNumberFromIndex(pGipCpu->iCpuSet, &ProcNum);
     1770        if (NT_SUCCESS(rcNt))
     1771            Assert(ProcNum.Group < g_pfnKeQueryMaximumGroupCount());
     1772        else
     1773        {
     1774            AssertFailed();
     1775            ProcNum.Group  = 0;
     1776            ProcNum.Number = pGipCpu->iCpuSet;
     1777        }
     1778    }
     1779    pGipCpu->iCpuGroup       = ProcNum.Group;
     1780    pGipCpu->iCpuGroupMember = ProcNum.Number;
    17571781
    17581782    /*
    1759      * This is just a wrapper around KeGetProcessorNumberFromIndex.
     1783     * Update the group info.  Just do this wholesale for now (doesn't scale well).
    17601784     */
    1761     if (g_pfnKeGetProcessorNumberFromIndex)
    1762     {
    1763         PROCESSOR_NUMBER ProcNum = { UINT16_MAX, UINT8_MAX, 0 };
    1764         NTSTATUS rcNt = g_pfnKeGetProcessorNumberFromIndex(idCpu, &ProcNum);
    1765         if (NT_SUCCESS(rcNt))
    1766         {
    1767             Assert(ProcNum.Group < g_pfnKeQueryMaximumGroupCount());
    1768             *piCpuGroupMember = ProcNum.Number;
    1769             return ProcNum.Group;
    1770         }
    1771 
    1772         AssertMsgFailed(("rcNt=%#x for idCpu=%u\n", rcNt, idCpu));
    1773     }
    1774 
    1775     *piCpuGroupMember = 0;
    1776     return idCpu;
     1785    for (uint32_t idxGroup = 0; idxGroup < pGip->cPossibleCpuGroups; idxGroup++)
     1786        if (pGip->aoffCpuGroup[idxGroup] != UINT16_MAX)
     1787        {
     1788            PSUPGIPCPUGROUP pGroup = (PSUPGIPCPUGROUP)((uintptr_t)pGip + pGip->aoffCpuGroup[idxGroup]);
     1789
     1790            uint32_t cActive  = 0;
     1791            uint32_t cMax     = RTMpGetCpuGroupCounts(idxGroup, &cActive);
     1792            AssertStmt(cMax == pGroup->cMaxMembers, cMax = pGroup->cMaxMembers);
     1793            AssertStmt(cActive <= cMax, cActive = cMax);
     1794            if (pGroup->cMembers != cActive)
     1795                pGroup->cMembers = cActive;
     1796
     1797            for (uint32_t idxMember = 0; idxMember < cMax; idxMember++)
     1798            {
     1799                int idxCpuSet = RTMpSetIndexFromCpuGroupMember(idxGroup, idxMember);
     1800                AssertMsg((unsigned)idxCpuSet < pGip->cPossibleCpus,
     1801                          ("%d vs %d for %u.%u\n", idxCpuSet, pGip->cPossibleCpus, idxGroup, idxMember));
     1802
     1803                if (pGroup->aiCpuSetIdxs[idxMember] != idxCpuSet)
     1804                    pGroup->aiCpuSetIdxs[idxMember] = idxCpuSet;
     1805            }
     1806        }
    17771807}
    17781808
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