VirtualBox

Changeset 27038 in vbox


Ignore:
Timestamp:
Mar 4, 2010 2:48:14 PM (15 years ago)
Author:
vboxsync
Message:

Try to reuse a 2mb large page if it was previously disabled for monitoring purposes.

Location:
trunk/src/VBox/VMM
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/PGM.cpp

    r26718 r27038  
    15821582    STAM_REL_REG(pVM, &pPGM->StatLargePageReused,                STAMTYPE_COUNTER, "/PGM/LargePage/Reused",              STAMUNIT_OCCURENCES, "The number of times we've reused a large page.");
    15831583    STAM_REL_REG(pVM, &pPGM->StatLargePageRefused,               STAMTYPE_COUNTER, "/PGM/LargePage/Refused",             STAMUNIT_OCCURENCES, "The number of times we couldn't use a large page.");
     1584    STAM_REL_REG(pVM, &pPGM->StatLargePageRecheck,               STAMTYPE_COUNTER, "/PGM/LargePage/Recheck",             STAMUNIT_OCCURENCES, "The number of times we've rechecked a disabled large page.");   
    15841585
    15851586    /* Live save */
  • trunk/src/VBox/VMM/PGMInternal.h

    r27026 r27038  
    27892789    STAMCOUNTER                     StatLargePageReused;                /**< The number of large pages we've reused.*/
    27902790    STAMCOUNTER                     StatLargePageRefused;               /**< The number of times we couldn't use a large page.*/
     2791    STAMCOUNTER                     StatLargePageRecheck;               /**< The number of times we rechecked a disabled large page.*/
    27912792    /** @} */
    27922793
     
    33323333int             pgmPhysAllocPage(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys);
    33333334int             pgmPhysAllocLargePage(PVM pVM, RTGCPHYS GCPhys);
     3335int             pgmPhysIsValidLargePage(PVM pVM, RTGCPHYS GCPhys, PPGMPAGE pLargePage);
    33343336int             pgmPhysPageLoadIntoTlb(PPGM pPGM, RTGCPHYS GCPhys);
    33353337int             pgmPhysPageLoadIntoTlbWithPage(PPGM pPGM, PPGMPAGE pPage, RTGCPHYS GCPhys);
  • trunk/src/VBox/VMM/VMMAll/PGMAllBth.h

    r27026 r27038  
    29752975            }
    29762976            else
     2977            if (PGM_PAGE_GET_PDE_TYPE(pPage) == PGM_PAGE_PDE_TYPE_PDE_DISABLED)
     2978            {
     2979                /* Recheck the entire 2 MB range to see if we can use it again as a large page. */
     2980                rc = pgmPhysIsValidLargePage(pVM, GCPtrPage, pPage);
     2981                if (RT_SUCCESS(rc))
     2982                {
     2983                    Assert(PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_ALLOCATED);
     2984                    Assert(PGM_PAGE_GET_PDE_TYPE(pPage) == PGM_PAGE_PDE_TYPE_PDE);
     2985                    HCPhys = PGM_PAGE_GET_HCPHYS(pPage);
     2986                }
     2987            }
     2988            else
    29772989            if (PGMIsUsingLargePages(pVM))
    29782990            {
  • trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp

    r27026 r27038  
    551551    return VERR_PGM_INVALID_LARGE_PAGE_RANGE;
    552552}
     553
     554/**
     555 * Recheck the entire 2 MB range to see if we can use it again as a large page.
     556 *
     557 * @returns The following VBox status codes.
     558 * @retval  VINF_SUCCESS on success, the large page can be used again
     559 * @retval  VERR_PGM_INVALID_LARGE_PAGE_RANGE if it can't be reused
     560 *
     561 * @param   pVM         The VM address.
     562 * @param   GCPhys      The address of the page.
     563 * @param   pLargePage  Page structure of the base page
     564 */
     565int pgmPhysIsValidLargePage(PVM pVM, RTGCPHYS GCPhys, PPGMPAGE pLargePage)
     566{
     567    unsigned i;
     568
     569    STAM_REL_COUNTER_INC(&pVM->pgm.s.StatLargePageRecheck);
     570
     571    GCPhys &= X86_PDE2M_PAE_PG_MASK;
     572
     573    /* Check the base page. */
     574    Assert(PGM_PAGE_GET_PDE_TYPE(pLargePage) == PGM_PAGE_PDE_TYPE_PDE_DISABLED);
     575    if (    PGM_PAGE_GET_STATE(pLargePage) != PGM_PAGE_STATE_ALLOCATED
     576        ||  PGM_PAGE_GET_TYPE(pLargePage) != PGMPAGETYPE_RAM
     577        ||  PGM_PAGE_GET_HNDL_PHYS_STATE(pLargePage) != PGM_PAGE_HNDL_PHYS_STATE_NONE)
     578    {
     579        LogFlow(("pgmPhysIsValidLargePage: checks failed for base page %x %x %x\n", PGM_PAGE_GET_STATE(pLargePage), PGM_PAGE_GET_TYPE(pLargePage), PGM_PAGE_GET_HNDL_PHYS_STATE(pLargePage)));
     580        return VERR_PGM_INVALID_LARGE_PAGE_RANGE;
     581    }
     582
     583    /* Check all remaining pages in the 2 MB range. */
     584    GCPhys += PAGE_SIZE;
     585    for (i = 1; i < _2M/PAGE_SIZE; i++)
     586    {
     587        PPGMPAGE pPage;
     588        int rc = pgmPhysGetPageEx(&pVM->pgm.s, GCPhys, &pPage);
     589        AssertRCBreak(rc);
     590
     591        if (    PGM_PAGE_GET_STATE(pPage) != PGM_PAGE_STATE_ALLOCATED
     592            ||  PGM_PAGE_GET_PDE_TYPE(pPage) != PGM_PAGE_PDE_TYPE_PDE
     593            ||  PGM_PAGE_GET_TYPE(pPage) != PGMPAGETYPE_RAM
     594            ||  PGM_PAGE_GET_HNDL_PHYS_STATE(pPage) != PGM_PAGE_HNDL_PHYS_STATE_NONE)
     595        {
     596            LogFlow(("pgmPhysIsValidLargePage: checks failed for page %d; %x %x %x\n", i, PGM_PAGE_GET_STATE(pPage), PGM_PAGE_GET_TYPE(pPage), PGM_PAGE_GET_HNDL_PHYS_STATE(pPage)));
     597            break;
     598        }
     599
     600        GCPhys += PAGE_SIZE;
     601    }
     602    if (i == _2M/PAGE_SIZE)
     603    {
     604        PGM_PAGE_SET_PDE_TYPE(pLargePage, PGM_PAGE_PDE_TYPE_PDE);
     605        Log(("pgmPhysIsValidLargePage: page %RGp can be reused!\n", GCPhys));
     606        return VINF_SUCCESS;
     607    }
     608
     609    return VERR_PGM_INVALID_LARGE_PAGE_RANGE;
     610}
     611
    553612#endif /* PGM_WITH_LARGE_PAGES */
    554613
  • trunk/src/VBox/VMM/VMMAll/PGMAllPool.cpp

    r27026 r27038  
    32963296        Log(("pgmPoolTrackUpdateGCPhys: update large page PDE for %RGp (%RGp)\n", GCPhysBase, GCPhysPage));
    32973297
    3298         /* Mark the large page as disabled as we need to break it up to change a single page in the 2 MB range. */
    3299         PGM_PAGE_SET_PDE_TYPE(pPhysBase, PGM_PAGE_PDE_TYPE_PDE_DISABLED);
    3300 
    3301         /* Update the base as that *only* that one has a reference and there's only one PDE to clear. */
    3302         rc = pgmPoolTrackUpdateGCPhys(pVM, GCPhysBase, pPhysBase, fFlushPTEs, pfFlushTLBs);
    3303 
    3304         *pfFlushTLBs = true;
    3305         pgmUnlock(pVM);
    3306         return rc;
     3298        if (PGM_PAGE_GET_PDE_TYPE(pPhysBase) == PGM_PAGE_PDE_TYPE_PDE)
     3299        {
     3300            /* Mark the large page as disabled as we need to break it up to change a single page in the 2 MB range. */
     3301            PGM_PAGE_SET_PDE_TYPE(pPhysBase, PGM_PAGE_PDE_TYPE_PDE_DISABLED);
     3302
     3303            /* Update the base as that *only* that one has a reference and there's only one PDE to clear. */
     3304            rc = pgmPoolTrackUpdateGCPhys(pVM, GCPhysBase, pPhysBase, fFlushPTEs, pfFlushTLBs);
     3305
     3306            *pfFlushTLBs = true;
     3307            pgmUnlock(pVM);
     3308            return rc;
     3309        }
    33073310    }
    33083311#else
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