VirtualBox

Changeset 77240 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Feb 10, 2019 4:34:51 PM (6 years ago)
Author:
vboxsync
Message:

PGMPool: Two optimizations to the dirty page code (PGMPOOL_WITH_OPTIMIZED_DIRTY_PT): Inline the first part of pgmPoolIsDirtyPage so we don't waste time on a full fledged call for nested paging. Split the PGMPOOL::aDirtyPages structure into index and page data so we can scan the indexes without requiring a cache line load for each entry. Also eliminated some double uIdx reads and checks.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/PGMAllPool.cpp

    r76553 r77240  
    14931493
    14941494
    1495 # ifdef PGMPOOL_WITH_OPTIMIZED_DIRTY_PT
    1496 
    1497 #  if defined(VBOX_STRICT) && !defined(IN_RING3)
     1495#ifdef PGMPOOL_WITH_OPTIMIZED_DIRTY_PT
     1496
     1497# if defined(VBOX_STRICT) && !defined(IN_RING3)
    14981498
    14991499/**
     
    15131513    PVM      pVM        = pPool->CTX_SUFF(pVM);
    15141514
    1515 #ifdef VBOX_STRICT
     1515#  ifdef VBOX_STRICT
    15161516    for (unsigned i = 0; i < RT_MIN(RT_ELEMENTS(pShwPT->a), pPage->iFirstPresent); i++)
    15171517        AssertMsg(!PGMSHWPTEPAE_IS_P(pShwPT->a[i]), ("Unexpected PTE: idx=%d %RX64 (first=%d)\n", i, PGMSHWPTEPAE_GET_LOG(pShwPT->a[i]),  pPage->iFirstPresent));
    1518 #endif
     1518#  endif
    15191519    for (unsigned i = pPage->iFirstPresent; i < RT_ELEMENTS(pShwPT->a); i++)
    15201520    {
     
    15791579    PVM      pVM        = pPool->CTX_SUFF(pVM);
    15801580
    1581 #ifdef VBOX_STRICT
     1581#  ifdef VBOX_STRICT
    15821582    for (unsigned i = 0; i < RT_MIN(RT_ELEMENTS(pShwPT->a), pPage->iFirstPresent); i++)
    15831583        AssertMsg(!PGMSHWPTEPAE_IS_P(pShwPT->a[i]), ("Unexpected PTE: idx=%d %RX64 (first=%d)\n", i, PGMSHWPTEPAE_GET_LOG(pShwPT->a[i]),  pPage->iFirstPresent));
    1584 #endif
     1584#  endif
    15851585    for (unsigned i = pPage->iFirstPresent; i < RT_ELEMENTS(pShwPT->a); i++)
    15861586    {
     
    16281628}
    16291629
    1630 #  endif /* VBOX_STRICT && !IN_RING3 */
     1630# endif /* VBOX_STRICT && !IN_RING3 */
    16311631
    16321632/**
     
    16471647    unsigned cChanged = 0;
    16481648
    1649 #ifdef VBOX_STRICT
     1649# ifdef VBOX_STRICT
    16501650    for (unsigned i = 0; i < RT_MIN(RT_ELEMENTS(pShwPT->a), pPage->iFirstPresent); i++)
    16511651        AssertMsg(!PGMSHWPTEPAE_IS_P(pShwPT->a[i]), ("Unexpected PTE: idx=%d %RX64 (first=%d)\n", i, PGMSHWPTEPAE_GET_LOG(pShwPT->a[i]),  pPage->iFirstPresent));
    1652 #endif
     1652# endif
    16531653    *pfFlush = false;
    16541654
     
    16721672            if ((pGstPT->a[i].u & X86_PTE_PAE_PG_MASK) == (pOldGstPT->a[i].u & X86_PTE_PAE_PG_MASK))
    16731673            {
    1674 #ifdef VBOX_STRICT
     1674# ifdef VBOX_STRICT
    16751675                RTHCPHYS HCPhys = NIL_RTGCPHYS;
    16761676                int rc = PGMPhysGCPhys2HCPhys(pPool->CTX_SUFF(pVM), pGstPT->a[i].u & X86_PTE_PAE_PG_MASK, &HCPhys);
    16771677                AssertMsg(rc == VINF_SUCCESS && PGMSHWPTEPAE_GET_HCPHYS(pShwPT->a[i]) == HCPhys, ("rc=%d guest %RX64 old %RX64 shw=%RX64 vs %RHp\n", rc, pGstPT->a[i].u, pOldGstPT->a[i].u, PGMSHWPTEPAE_GET_LOG(pShwPT->a[i]), HCPhys));
    1678 #endif
     1678# endif
    16791679                uint64_t uHostAttr  = PGMSHWPTEPAE_GET_U(pShwPT->a[i]) & (X86_PTE_P | X86_PTE_US | X86_PTE_A | X86_PTE_D | X86_PTE_G | X86_PTE_PAE_NX);
    16801680                bool     fHostRW    = !!(PGMSHWPTEPAE_GET_U(pShwPT->a[i]) & X86_PTE_RW);
     
    17151715    unsigned cChanged = 0;
    17161716
    1717 #ifdef VBOX_STRICT
     1717# ifdef VBOX_STRICT
    17181718    for (unsigned i = 0; i < RT_MIN(RT_ELEMENTS(pShwPT->a), pPage->iFirstPresent); i++)
    17191719        AssertMsg(!PGMSHWPTEPAE_IS_P(pShwPT->a[i]), ("Unexpected PTE: idx=%d %RX64 (first=%d)\n", i, PGMSHWPTEPAE_GET_LOG(pShwPT->a[i]),  pPage->iFirstPresent));
    1720 #endif
     1720# endif
    17211721    *pfFlush = false;
    17221722
     
    17401740            if ((pGstPT->a[i].u & X86_PTE_PG_MASK) == (pOldGstPT->a[i].u & X86_PTE_PG_MASK))
    17411741            {
    1742 #ifdef VBOX_STRICT
     1742# ifdef VBOX_STRICT
    17431743                RTHCPHYS HCPhys = NIL_RTGCPHYS;
    17441744                int rc = PGMPhysGCPhys2HCPhys(pPool->CTX_SUFF(pVM), pGstPT->a[i].u & X86_PTE_PG_MASK, &HCPhys);
    17451745                AssertMsg(rc == VINF_SUCCESS && PGMSHWPTEPAE_GET_HCPHYS(pShwPT->a[i]) == HCPhys, ("rc=%d guest %x old %x shw=%RX64 vs %RHp\n", rc, pGstPT->a[i].u, pOldGstPT->a[i].u, PGMSHWPTEPAE_GET_LOG(pShwPT->a[i]), HCPhys));
    1746 #endif
     1746# endif
    17471747                uint64_t uHostAttr  = PGMSHWPTEPAE_GET_U(pShwPT->a[i]) & (X86_PTE_P | X86_PTE_US | X86_PTE_A | X86_PTE_D | X86_PTE_G);
    17481748                bool     fHostRW    = !!(PGMSHWPTEPAE_GET_U(pShwPT->a[i]) & X86_PTE_RW);
     
    17761776static void pgmPoolFlushDirtyPage(PVM pVM, PPGMPOOL pPool, unsigned idxSlot, bool fAllowRemoval = false)
    17771777{
    1778     PPGMPOOLPAGE pPage;
    1779     unsigned     idxPage;
     1778    AssertCompile(RT_ELEMENTS(pPool->aidxDirtyPages) == RT_ELEMENTS(pPool->aDirtyPages));
    17801779
    17811780    Assert(idxSlot < RT_ELEMENTS(pPool->aDirtyPages));
    1782     if (pPool->aDirtyPages[idxSlot].uIdx == NIL_PGMPOOL_IDX)
     1781    unsigned idxPage = pPool->aidxDirtyPages[idxSlot];
     1782    if (idxPage == NIL_PGMPOOL_IDX)
    17831783        return;
    17841784
    1785     idxPage = pPool->aDirtyPages[idxSlot].uIdx;
    1786     AssertRelease(idxPage != NIL_PGMPOOL_IDX);
    1787     pPage = &pPool->aPages[idxPage];
     1785    PPGMPOOLPAGE pPage = &pPool->aPages[idxPage];
    17881786    Assert(pPage->idx == idxPage);
    17891787    Assert(pPage->iMonitoredNext == NIL_PGMPOOL_IDX && pPage->iMonitoredPrev == NIL_PGMPOOL_IDX);
     
    17921790    Log(("Flush dirty page %RGp cMods=%d\n", pPage->GCPhys, pPage->cModifications));
    17931791
    1794 #if defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0) || defined(IN_RC)
     1792# if defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0) || defined(IN_RC)
    17951793    PVMCPU   pVCpu = VMMGetCpu(pVM);
    17961794    uint32_t iPrevSubset = PGMRZDynMapPushAutoSubset(pVCpu);
    1797 #endif
     1795# endif
    17981796
    17991797    /* First write protect the page again to catch all write accesses. (before checking for changes -> SMP) */
     
    18021800    pPage->fDirty = false;
    18031801
    1804 #ifdef VBOX_STRICT
     1802# ifdef VBOX_STRICT
    18051803    uint64_t fFlags = 0;
    18061804    RTHCPHYS HCPhys;
     
    18121810              ||    rc == VERR_PAGE_NOT_PRESENT,
    18131811              ("PGMShwGetPage -> GCPtr=%RGv rc=%d flags=%RX64\n", pPage->GCPtrDirtyFault, rc, fFlags));
    1814 #endif
     1812# endif
    18151813
    18161814    /* Flush those PTEs that have changed. */
     
    18461844
    18471845    pPool->cDirtyPages--;
    1848     pPool->aDirtyPages[idxSlot].uIdx = NIL_PGMPOOL_IDX;
     1846    pPool->aidxDirtyPages[idxSlot] = NIL_PGMPOOL_IDX;
    18491847    Assert(pPool->cDirtyPages <= RT_ELEMENTS(pPool->aDirtyPages));
    18501848    if (fFlush)
     
    18581856        Log(("Removed dirty page %RGp cMods=%d cChanges=%d\n", pPage->GCPhys, pPage->cModifications, cChanges));
    18591857
    1860 #if defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0) || defined(IN_RC)
     1858# if defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0) || defined(IN_RC)
    18611859    PGMRZDynMapPopAutoSubset(pVCpu, iPrevSubset);
    1862 #endif
     1860# endif
    18631861}
    18641862
     
    18741872void pgmPoolAddDirtyPage(PVM pVM, PPGMPOOL pPool, PPGMPOOLPAGE pPage)
    18751873{
    1876     unsigned idxFree;
    1877 
    18781874    PGM_LOCK_ASSERT_OWNER(pVM);
    18791875    AssertCompile(RT_ELEMENTS(pPool->aDirtyPages) == 8 || RT_ELEMENTS(pPool->aDirtyPages) == 16);
    18801876    Assert(!pPage->fDirty);
    18811877
    1882     idxFree = pPool->idxFreeDirtyPage;
     1878    unsigned idxFree = pPool->idxFreeDirtyPage;
    18831879    Assert(idxFree < RT_ELEMENTS(pPool->aDirtyPages));
    18841880    Assert(pPage->iMonitoredNext == NIL_PGMPOOL_IDX && pPage->iMonitoredPrev == NIL_PGMPOOL_IDX);
     
    18901886    }
    18911887    Assert(pPool->cDirtyPages < RT_ELEMENTS(pPool->aDirtyPages));
    1892     AssertMsg(pPool->aDirtyPages[idxFree].uIdx == NIL_PGMPOOL_IDX, ("idxFree=%d cDirtyPages=%d\n", idxFree, pPool->cDirtyPages));
     1888    AssertMsg(pPool->aidxDirtyPages[idxFree] == NIL_PGMPOOL_IDX, ("idxFree=%d cDirtyPages=%d\n", idxFree, pPool->cDirtyPages));
    18931889
    18941890    Log(("Add dirty page %RGp (slot=%d)\n", pPage->GCPhys, idxFree));
     
    19151911    pPage->fDirty                    = true;
    19161912    pPage->idxDirtyEntry             = (uint8_t)idxFree; Assert(pPage->idxDirtyEntry == idxFree);
    1917     pPool->aDirtyPages[idxFree].uIdx = pPage->idx;
     1913    pPool->aidxDirtyPages[idxFree]  = pPage->idx;
    19181914    pPool->cDirtyPages++;
    19191915
    19201916    pPool->idxFreeDirtyPage        = (pPool->idxFreeDirtyPage + 1) & (RT_ELEMENTS(pPool->aDirtyPages) - 1);
    19211917    if (    pPool->cDirtyPages < RT_ELEMENTS(pPool->aDirtyPages)
    1922         &&  pPool->aDirtyPages[pPool->idxFreeDirtyPage].uIdx != NIL_PGMPOOL_IDX)
     1918        &&  pPool->aidxDirtyPages[pPool->idxFreeDirtyPage] != NIL_PGMPOOL_IDX)
    19231919    {
    19241920        unsigned i;
     
    19261922        {
    19271923            idxFree = (pPool->idxFreeDirtyPage + i) & (RT_ELEMENTS(pPool->aDirtyPages) - 1);
    1928             if (pPool->aDirtyPages[idxFree].uIdx == NIL_PGMPOOL_IDX)
     1924            if (pPool->aidxDirtyPages[idxFree] == NIL_PGMPOOL_IDX)
    19291925            {
    19301926                pPool->idxFreeDirtyPage = idxFree;
     
    19351931    }
    19361932
    1937     Assert(pPool->cDirtyPages == RT_ELEMENTS(pPool->aDirtyPages) || pPool->aDirtyPages[pPool->idxFreeDirtyPage].uIdx == NIL_PGMPOOL_IDX);
     1933    Assert(pPool->cDirtyPages == RT_ELEMENTS(pPool->aDirtyPages) || pPool->aidxDirtyPages[pPool->idxFreeDirtyPage] == NIL_PGMPOOL_IDX);
    19381934
    19391935    /*
     
    19521948 * @param   GCPhys          Guest physical address
    19531949 */
    1954 bool pgmPoolIsDirtyPage(PVM pVM, RTGCPHYS GCPhys)
     1950bool pgmPoolIsDirtyPageSlow(PVM pVM, RTGCPHYS GCPhys)
    19551951{
    19561952    PPGMPOOL pPool = pVM->pgm.s.CTX_SUFF(pPool);
     
    19631959    for (unsigned i = 0; i < RT_ELEMENTS(pPool->aDirtyPages); i++)
    19641960    {
    1965         if (pPool->aDirtyPages[i].uIdx != NIL_PGMPOOL_IDX)
    1966         {
    1967             PPGMPOOLPAGE pPage;
    1968             unsigned     idxPage = pPool->aDirtyPages[i].uIdx;
    1969 
    1970             pPage = &pPool->aPages[idxPage];
     1961        unsigned idxPage = pPool->aidxDirtyPages[i];
     1962        if (idxPage != NIL_PGMPOOL_IDX)
     1963        {
     1964            PPGMPOOLPAGE pPage = &pPool->aPages[idxPage];
    19711965            if (pPage->GCPhys == GCPhys)
    19721966                return true;
     
    19971991    pPool->idxFreeDirtyPage = 0;
    19981992    if (    pPool->cDirtyPages != RT_ELEMENTS(pPool->aDirtyPages)
    1999         &&  pPool->aDirtyPages[pPool->idxFreeDirtyPage].uIdx != NIL_PGMPOOL_IDX)
     1993        &&  pPool->aidxDirtyPages[pPool->idxFreeDirtyPage] != NIL_PGMPOOL_IDX)
    20001994    {
    20011995        unsigned i;
    20021996        for (i = 1; i < RT_ELEMENTS(pPool->aDirtyPages); i++)
    20031997        {
    2004             if (pPool->aDirtyPages[i].uIdx == NIL_PGMPOOL_IDX)
     1998            if (pPool->aidxDirtyPages[i] == NIL_PGMPOOL_IDX)
    20051999            {
    20062000                pPool->idxFreeDirtyPage = i;
     
    20112005    }
    20122006
    2013     Assert(pPool->aDirtyPages[pPool->idxFreeDirtyPage].uIdx == NIL_PGMPOOL_IDX || pPool->cDirtyPages == RT_ELEMENTS(pPool->aDirtyPages));
     2007    Assert(pPool->aidxDirtyPages[pPool->idxFreeDirtyPage] == NIL_PGMPOOL_IDX || pPool->cDirtyPages == RT_ELEMENTS(pPool->aDirtyPages));
    20142008    return;
    20152009}
     
    20342028    for (unsigned i = 0; i < RT_ELEMENTS(pPool->aDirtyPages); i++)
    20352029    {
     2030    /** @todo What was intended here??? This looks incomplete... */
    20362031    }
    20372032}
     
    20582053    for (unsigned i = 0; i < RT_ELEMENTS(pPool->aDirtyPages); i++)
    20592054    {
    2060         if (pPool->aDirtyPages[i].uIdx != NIL_PGMPOOL_IDX)
    2061         {
    2062             unsigned     idxPage = pPool->aDirtyPages[i].uIdx;
    2063 
     2055        unsigned idxPage = pPool->aidxDirtyPages[i];
     2056        if (idxPage != NIL_PGMPOOL_IDX)
     2057        {
    20642058            PPGMPOOLPAGE pPage = &pPool->aPages[idxPage];
    20652059            if (pPage->GCPhys == GCPhysPT)
     
    20752069        pgmPoolFlushDirtyPage(pVM, pPool, idxDirtyPage, true /* allow removal of reused page tables*/);
    20762070        if (    pPool->cDirtyPages != RT_ELEMENTS(pPool->aDirtyPages)
    2077             &&  pPool->aDirtyPages[pPool->idxFreeDirtyPage].uIdx != NIL_PGMPOOL_IDX)
     2071            &&  pPool->aidxDirtyPages[pPool->idxFreeDirtyPage] != NIL_PGMPOOL_IDX)
    20782072        {
    20792073            unsigned i;
    20802074            for (i = 0; i < RT_ELEMENTS(pPool->aDirtyPages); i++)
    20812075            {
    2082                 if (pPool->aDirtyPages[i].uIdx == NIL_PGMPOOL_IDX)
     2076                if (pPool->aidxDirtyPages[i] == NIL_PGMPOOL_IDX)
    20832077                {
    20842078                    pPool->idxFreeDirtyPage = i;
     
    20912085}
    20922086
    2093 # endif /* PGMPOOL_WITH_OPTIMIZED_DIRTY_PT */
     2087#endif /* PGMPOOL_WITH_OPTIMIZED_DIRTY_PT */
    20942088
    20952089/**
     
    55735567    pPool->idxFreeDirtyPage = 0;
    55745568    pPool->cDirtyPages      = 0;
    5575     for (unsigned i = 0; i < RT_ELEMENTS(pPool->aDirtyPages); i++)
    5576         pPool->aDirtyPages[i].uIdx = NIL_PGMPOOL_IDX;
     5569    for (unsigned i = 0; i < RT_ELEMENTS(pPool->aidxDirtyPages); i++)
     5570        pPool->aidxDirtyPages[i] = NIL_PGMPOOL_IDX;
    55775571#endif
    55785572
  • trunk/src/VBox/VMM/VMMR3/PGMPool.cpp

    r76553 r77240  
    743743    for (unsigned i = 0; i < RT_ELEMENTS(pPool->aDirtyPages); i++)
    744744    {
    745         PPGMPOOLPAGE pPage;
    746         unsigned     idxPage;
    747 
    748         if (pPool->aDirtyPages[i].uIdx == NIL_PGMPOOL_IDX)
     745        unsigned idxPage = pPool->aidxDirtyPages[i];
     746        if (idxPage == NIL_PGMPOOL_IDX)
    749747            continue;
    750748
    751         idxPage = pPool->aDirtyPages[i].uIdx;
    752         AssertRelease(idxPage != NIL_PGMPOOL_IDX);
    753         pPage = &pPool->aPages[idxPage];
     749        PPGMPOOLPAGE pPage = &pPool->aPages[idxPage];
    754750        Assert(pPage->idx == idxPage);
    755751        Assert(pPage->iMonitoredNext == NIL_PGMPOOL_IDX && pPage->iMonitoredPrev == NIL_PGMPOOL_IDX);
     
    764760        pPage->fDirty = false;
    765761
    766         pPool->aDirtyPages[i].uIdx = NIL_PGMPOOL_IDX;
     762        pPool->aidxDirtyPages[i] = NIL_PGMPOOL_IDX;
    767763    }
    768764
  • trunk/src/VBox/VMM/include/PGMInline.h

    r76585 r77240  
    14961496
    14971497/**
     1498 * Check if the specified page is dirty (not write monitored)
     1499 *
     1500 * @return dirty or not
     1501 * @param   pVM             The cross context VM structure.
     1502 * @param   GCPhys          Guest physical address
     1503 */
     1504DECLINLINE(bool) pgmPoolIsDirtyPage(PVM pVM, RTGCPHYS GCPhys)
     1505{
     1506    PPGMPOOL pPool = pVM->pgm.s.CTX_SUFF(pPool);
     1507    PGM_LOCK_ASSERT_OWNER(pVM);
     1508    if (!pPool->cDirtyPages)
     1509        return false;
     1510    return pgmPoolIsDirtyPageSlow(pVM, GCPhys);
     1511}
     1512
     1513
     1514/**
    14981515 * Tells if mappings are to be put into the shadow page table or not.
    14991516 *
  • trunk/src/VBox/VMM/include/PGMInternal.h

    r76993 r77240  
    24762476    uint32_t                    cDirtyPages;
    24772477    /** Array of current dirty pgm pool page indices. */
     2478    uint16_t                    aidxDirtyPages[16];
     2479    /** Array running in parallel to aidxDirtyPages with the page data. */
    24782480    struct
    24792481    {
    2480         uint16_t                    uIdx;
    2481         uint16_t                    Alignment[3];
    2482         uint64_t                    aPage[512];
     2482        uint64_t                aPage[512];
    24832483    } aDirtyPages[16];
     2484
    24842485    /** The number of pages currently in use. */
    24852486    uint16_t                    cUsedPages;
     
    42944295PPGMPOOLPAGE    pgmPoolQueryPageForDbg(PPGMPOOL pPool, RTHCPHYS HCPhys);
    42954296int             pgmPoolSyncCR3(PVMCPU pVCpu);
    4296 bool            pgmPoolIsDirtyPage(PVM pVM, RTGCPHYS GCPhys);
     4297bool            pgmPoolIsDirtyPageSlow(PVM pVM, RTGCPHYS GCPhys);
    42974298void            pgmPoolInvalidateDirtyPage(PVM pVM, RTGCPHYS GCPhysPT);
    42984299int             pgmPoolTrackUpdateGCPhys(PVM pVM, RTGCPHYS GCPhysPage, PPGMPAGE pPhysPage, bool fFlushPTEs, bool *pfFlushTLBs);
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