VirtualBox

Changeset 15411 in vbox


Ignore:
Timestamp:
Dec 13, 2008 3:30:58 AM (16 years ago)
Author:
vboxsync
Message:

VMM: Working around set overflows caused by the page pool.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/pgm.h

    r15403 r15411  
    455455VMMDECL(void)       PGMDynMapFlushAutoSet(PVMCPU pVCpu);
    456456VMMDECL(void)       PGMDynMapMigrateAutoSet(PVMCPU pVCpu);
     457VMMDECL(uint32_t)   PGMDynMapPushAutoSubset(PVMCPU pVCpu);
     458VMMDECL(void)       PGMDynMapPopAutoSubset(PVMCPU pVCpu, uint32_t iPrevSubset);
    457459
    458460/**
  • trunk/src/VBox/VMM/PGM.cpp

    r15404 r15411  
    16091609    STAM_REG(pVM, &pPGM->StatR0DynMapPage,                  STAMTYPE_COUNTER, "/PGM/R0/DynMapPage",                 STAMUNIT_OCCURENCES,     "Calls to pgmR0DynMapPage");
    16101610    STAM_REG(pVM, &pPGM->StatR0DynMapSetOptimize,           STAMTYPE_COUNTER, "/PGM/R0/DynMapPage/SetOptimize",     STAMUNIT_OCCURENCES,     "Calls to pgmDynMapOptimizeAutoSet.");
     1611    STAM_REG(pVM, &pPGM->StatR0DynMapSetSearchFlushes,      STAMTYPE_COUNTER, "/PGM/R0/DynMapPage/SetSearchFlushes",STAMUNIT_OCCURENCES,     "Set search restorting to subset flushes.");
    16111612    STAM_REG(pVM, &pPGM->StatR0DynMapSetSearchHits,         STAMTYPE_COUNTER, "/PGM/R0/DynMapPage/SetSearchHits",   STAMUNIT_OCCURENCES,     "Set search hits.");
    16121613    STAM_REG(pVM, &pPGM->StatR0DynMapSetSearchMisses,       STAMTYPE_COUNTER, "/PGM/R0/DynMapPage/SetSearchMisses", STAMUNIT_OCCURENCES,     "Set search misses.");
     
    16201621    STAM_REG(pVM, &pPGM->StatR0DynMapPageSlowLoopMisses,    STAMTYPE_COUNTER, "/PGM/R0/DynMapPage/SlowLoopMisses",  STAMUNIT_OCCURENCES,     "Misses in the loop path. NonLoopMisses = Slow - SlowLoopHit - SlowLoopMisses");
    16211622    //STAM_REG(pVM, &pPGM->StatR0DynMapPageSlowLostHits,      STAMTYPE_COUNTER, "/PGM/R0/DynMapPage/SlowLostHits",    STAMUNIT_OCCURENCES,     "Lost hits.");
     1623    STAM_REG(pVM, &pPGM->StatR0DynMapSubsets,               STAMTYPE_COUNTER, "/PGM/R0/Subsets",                    STAMUNIT_OCCURENCES,     "Times PGMDynMapPushAutoSubset was called.");
     1624    STAM_REG(pVM, &pPGM->StatR0DynMapPopFlushes,            STAMTYPE_COUNTER, "/PGM/R0/SubsetPopFlushes",           STAMUNIT_OCCURENCES,     "Times PGMDynMapPopAutoSubset flushes the subset.");
    16221625
    16231626    /* GC only: */
  • trunk/src/VBox/VMM/PGMInternal.h

    r15410 r15411  
    13151315typedef struct PGMMAPSET
    13161316{
    1317     /** The index of the current CPU, only valid if the set is open. */
    1318     int32_t                     iCpu;
    1319     /** The number of occupied.
     1317    /** The number of occupied entries.
    13201318     * This is PGMMAPSET_CLOSED if the set is closed and we're not supposed to do
    13211319     * dynamic mappings. */
    13221320    uint32_t                    cEntries;
     1321    /** The start of the current subset.
     1322     * This is UINT32_MAX if no subset is currently open. */
     1323    uint32_t                    iSubset;
     1324    /** The index of the current CPU, only valid if the set is open. */
     1325    int32_t                     iCpu;
    13231326    /** The entries. */
    13241327    PGMMAPSETENTRY              aEntries[32];
     
    18181821
    18191822#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
    1820 DECLINLINE(void *) pgmPoolMapPageInlined(PVM pVM, PPGMPOOLPAGE pPage);
     1823DECLINLINE(void *) pgmPoolMapPageInlined(PVM pVM, PPGMPOOLPAGE pPage, int iLine, const char *pszFile);
    18211824#endif
    18221825
     
    18321835 * @remark  There is no need to assert on the result.
    18331836 */
    1834 #if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
    1835 # define PGMPOOL_PAGE_2_PTR(pVM, pPage)  pgmPoolMapPageInlined(&(pVM)->pgm.s, (pPage))
     1837#if defined(IN_RC)
     1838# define PGMPOOL_PAGE_2_PTR(pVM, pPage)  pgmPoolMapPageInlined(&(pVM)->pgm.s, (pPage), __LINE__, 0)
     1839#elif defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
     1840# define PGMPOOL_PAGE_2_PTR(pVM, pPage)  pgmPoolMapPageInlined(&(pVM)->pgm.s, (pPage), __LINE__, __PRETTY_FUNCTION__)
    18361841#elif defined(VBOX_STRICT)
    18371842# define PGMPOOL_PAGE_2_PTR(pVM, pPage)  pgmPoolMapPageStrict(pPage)
     
    18561861 * @remark  There is no need to assert on the result.
    18571862 */
    1858 #if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
    1859 # define PGMPOOL_PAGE_2_PTR_BY_PGM(pPGM, pPage)  pgmPoolMapPageInlined((pPGM), (pPage))
     1863#if defined(IN_RC)
     1864# define PGMPOOL_PAGE_2_PTR_BY_PGM(pPGM, pPage)  pgmPoolMapPageInlined((pPGM), (pPage), __LINE__, 0)
     1865#elif defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
     1866# define PGMPOOL_PAGE_2_PTR_BY_PGM(pPGM, pPage)  pgmPoolMapPageInlined((pPGM), (pPage), __LINE__, __PRETTY_FUNCTION__)
    18601867#else
    18611868# define PGMPOOL_PAGE_2_PTR_BY_PGM(pPGM, pPage)  PGMPOOL_PAGE_2_PTR(PGM2VM(pPGM), pPage)
     
    26602667    STAMPROFILE StatR0DynMapHCPage;                 /**< R0: Calls to PGMDynMapHCPage. */
    26612668    STAMCOUNTER StatR0DynMapSetOptimize;            /**< R0: Calls to pgmDynMapOptimizeAutoSet. */
     2669    STAMCOUNTER StatR0DynMapSetSearchFlushes;       /**< R0: Set search restorting to subset flushes. */
    26622670    STAMCOUNTER StatR0DynMapSetSearchHits;          /**< R0: Set search hits. */
    26632671    STAMCOUNTER StatR0DynMapSetSearchMisses;        /**< R0: Set search misses. */
     
    26712679    STAMCOUNTER StatR0DynMapPageSlowLoopMisses;     /**< R0: Misses in the pgmR0DynMapPageSlow search loop. */
    26722680    //STAMCOUNTER StatR0DynMapPageSlowLostHits;       /**< R0: Lost hits. */
     2681    STAMCOUNTER StatR0DynMapSubsets;                /**< R0: Times PGMDynMapPushAutoSubset was called. */
     2682    STAMCOUNTER StatR0DynMapPopFlushes;             /**< R0: Times PGMDynMapPopAutoSubset flushes the subset. */
    26732683
    26742684    /* RC only: */
     
    46214631 * @param   pPage       The page.
    46224632 */
    4623 DECLINLINE(void *) pgmPoolMapPageInlined(PPGM pPGM, PPGMPOOLPAGE pPage)
     4633DECLINLINE(void *) pgmPoolMapPageInlined(PPGM pPGM, PPGMPOOLPAGE pPage, int iLine, const char *pszFile)
    46244634{
    46254635    if (pPage->idx >= PGMPOOL_IDX_FIRST)
     
    46344644        if (RT_SUCCESS(rc))
    46354645            return pv;
     4646        AssertMsgFailed(("%Rrc: %s(%d)\n", rc, pszFile, iLine));
    46364647    }
    46374648    return pgmPoolMapPageFallback(pPGM, pPage);
  • trunk/src/VBox/VMM/VMMAll/PGMAllPool.cpp

    r15410 r15411  
    36743674    }
    36753675
     3676#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
     3677    /* Start a subset so we won't run out of mapping space. */
     3678    PVMCPU pVCpu = VMMGetCpu(pPool->CTX_SUFF(pVM));
     3679    uint32_t iPrevSubset = PGMDynMapPushAutoSubset(pVCpu);
     3680#endif
     3681
    36763682    /*
    36773683     * Nuke the free list and reinsert all pages into it.
     
    38153821    }
    38163822
     3823#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
     3824    /* Pop the subset. */
     3825    PGMDynMapPopAutoSubset(pVCpu, iPrevSubset);
     3826#endif
     3827
    38173828    /*
    38183829     * Finally, assert the FF.
     
    38633874    }
    38643875
     3876#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
     3877    /* Start a subset so we won't run out of mapping space. */
     3878    PVMCPU pVCpu = VMMGetCpu(pPool->CTX_SUFF(pVM));
     3879    uint32_t iPrevSubset = PGMDynMapPushAutoSubset(pVCpu);
     3880#endif
     3881
    38653882    /*
    38663883     * Mark the page as being in need of a ASMMemZeroPage().
     
    38843901    pgmPoolCacheFlushPage(pPool, pPage);
    38853902#endif /* PGMPOOL_WITH_CACHE */
     3903
     3904#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
     3905    /* Heavy stuff done. */
     3906    PGMDynMapPopAutoSubset(pVCpu, iPrevSubset);
     3907#endif
    38863908
    38873909#ifdef PGMPOOL_WITH_MONITORING
  • trunk/src/VBox/VMM/VMMR0/PGMR0DynMap.cpp

    r15402 r15411  
    367367        }
    368368        pSet->cEntries = PGMMAPSET_CLOSED;
     369        pSet->iSubset = UINT32_MAX;
    369370        pSet->iCpu = -1;
    370371        memset(&pSet->aiHashTable[0], 0xff, sizeof(pSet->aiHashTable));
     
    466467                }
    467468                pSet->cEntries = PGMMAPSET_CLOSED;
     469                pSet->iSubset = UINT32_MAX;
    468470                pSet->iCpu = -1;
    469471            }
     
    14981500{
    14991501    Assert(pVCpu->pgm.s.AutoSet.cEntries == PGMMAPSET_CLOSED);
     1502    Assert(pVCpu->pgm.s.AutoSet.iSubset == UINT32_MAX);
    15001503    pVCpu->pgm.s.AutoSet.cEntries = 0;
    15011504    pVCpu->pgm.s.AutoSet.iCpu = RTMpCpuIdToSetIndex(RTMpCpuId());
     
    15571560    AssertMsg(cEntries <= RT_ELEMENTS(pSet->aEntries), ("%#x (%u)\n", cEntries, cEntries));
    15581561    pSet->cEntries = PGMMAPSET_CLOSED;
     1562    pSet->iSubset = UINT32_MAX;
    15591563    pSet->iCpu = -1;
    15601564
     
    15871591    }
    15881592}
    1589 
    15901593
    15911594
     
    16161619            {
    16171620                PPGMR0DYNMAP    pThis = g_pPGMR0DynMap;
     1621                RTSPINLOCKTMP   Tmp = RTSPINLOCKTMP_INITIALIZER;
     1622                RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
     1623
    16181624                while (i-- > 0)
    16191625                {
     
    16241630                    {
    16251631                        RTCpuSetDelByIndex(&pThis->paPages[iPage].PendingSet, iRealCpu);
     1632                        RTSpinlockRelease(pThis->hSpinlock, &Tmp);
     1633
    16261634                        ASMInvalidatePage(pThis->paPages[iPage].pvPage);
    16271635                        STAM_COUNTER_INC(&pVCpu->pVMR0->pgm.s.StatR0DynMapMigrateInvlPg);
     1636
     1637                        RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
    16281638                    }
    16291639                }
    16301640
     1641                RTSpinlockRelease(pThis->hSpinlock, &Tmp);
    16311642            }
    16321643        }
    16331644        pSet->iCpu = iRealCpu;
    16341645    }
     1646}
     1647
     1648
     1649/**
     1650 * Worker function that flushes the current subset.
     1651 *
     1652 * This is called when the set is popped or when the set
     1653 * hash a too high load. As also pointed out elsewhere, the
     1654 * whole subset thing is a hack for working around code that
     1655 * accesses too many pages. Like PGMPool.
     1656 *
     1657 * @param   pSet        The set which subset to flush.
     1658 */
     1659static void pgmDynMapFlushSubset(PPGMMAPSET pSet)
     1660{
     1661    uint32_t iSubset = pSet->iSubset;
     1662    uint32_t i       = pSet->cEntries;
     1663    Assert(i <= RT_ELEMENTS(pSet->aEntries));
     1664    if (    i > iSubset
     1665        &&  i <= RT_ELEMENTS(pSet->aEntries))
     1666    {
     1667        pSet->cEntries = iSubset;
     1668
     1669        PPGMR0DYNMAP    pThis = g_pPGMR0DynMap;
     1670        RTSPINLOCKTMP   Tmp   = RTSPINLOCKTMP_INITIALIZER;
     1671        RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
     1672
     1673        while (i-- > iSubset)
     1674        {
     1675            uint32_t iPage = pSet->aEntries[i].iPage;
     1676            Assert(iPage < pThis->cPages);
     1677            int32_t  cRefs = pSet->aEntries[i].cRefs;
     1678            Assert(cRefs > 0);
     1679            pgmR0DynMapReleasePageLocked(pThis, iPage, cRefs);
     1680
     1681            pSet->aEntries[i].iPage = UINT16_MAX;
     1682            pSet->aEntries[i].cRefs = 0;
     1683        }
     1684
     1685        RTSpinlockRelease(pThis->hSpinlock, &Tmp);
     1686    }
     1687}
     1688
     1689
     1690/**
     1691 * Creates a subset.
     1692 *
     1693 * A subset is a hack to avoid having to rewrite code that touches a lot of
     1694 * pages. It prevents the mapping set from being overflowed by automatically
     1695 * flushing previous mappings when a certain threshold is reached.
     1696 *
     1697 * Pages mapped after calling this function are only valid until the next page
     1698 * is mapped.
     1699 *
     1700 * @returns The index of the previous subset. Pass this to
     1701 *        PGMDynMapPopAutoSubset when poping it.
     1702 * @param   pVCpu           Pointer to the virtual cpu data.
     1703 */
     1704VMMDECL(uint32_t) PGMDynMapPushAutoSubset(PVMCPU pVCpu)
     1705{
     1706    PPGMMAPSET      pSet = &pVCpu->pgm.s.AutoSet;
     1707    AssertReturn(pSet->cEntries != PGMMAPSET_CLOSED, UINT32_MAX);
     1708    uint32_t        iPrevSubset = pSet->iSubset;
     1709Assert(iPrevSubset == UINT32_MAX);
     1710    pSet->iSubset = pSet->cEntries;
     1711    STAM_COUNTER_INC(&pVCpu->pVMR0->pgm.s.StatR0DynMapSubsets);
     1712    return iPrevSubset;
     1713}
     1714
     1715
     1716/**
     1717 * Pops a subset created by a previous call to PGMDynMapPushAutoSubset.
     1718 *
     1719 * @param   pVCpu           Pointer to the virtual cpu data.
     1720 * @param   iPrevSubset     What PGMDynMapPushAutoSubset returned.
     1721 */
     1722VMMDECL(void) PGMDynMapPopAutoSubset(PVMCPU pVCpu, uint32_t iPrevSubset)
     1723{
     1724    PPGMMAPSET      pSet = &pVCpu->pgm.s.AutoSet;
     1725    AssertReturnVoid(pSet->cEntries != PGMMAPSET_CLOSED);
     1726    AssertReturnVoid(pSet->iSubset <= iPrevSubset || iPrevSubset == UINT32_MAX);
     1727Assert(iPrevSubset == UINT32_MAX);
     1728    if (    pSet->cEntries >= RT_ELEMENTS(pSet->aEntries) / 2
     1729        &&  pSet->cEntries != pSet->iSubset)
     1730    {
     1731        STAM_COUNTER_INC(&pVCpu->pVMR0->pgm.s.StatR0DynMapPopFlushes);
     1732        pgmDynMapFlushSubset(pSet);
     1733    }
     1734    pSet->iSubset = iPrevSubset;
    16351735}
    16361736
     
    17741874        {
    17751875            STAM_COUNTER_INC(&pVM->pgm.s.StatR0DynMapSetSearchMisses);
     1876            if (pSet->iSubset < pSet->cEntries)
     1877            {
     1878                STAM_COUNTER_INC(&pVM->pgm.s.StatR0DynMapSetSearchFlushes);
     1879                pgmDynMapFlushSubset(pSet);
     1880            }
     1881
    17761882            if (RT_UNLIKELY(pSet->cEntries >= RT_ELEMENTS(pSet->aEntries)))
    17771883            {
     
    17791885                pgmDynMapOptimizeAutoSet(pSet);
    17801886            }
     1887
    17811888            if (RT_LIKELY(pSet->cEntries < RT_ELEMENTS(pSet->aEntries)))
    17821889            {
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