VirtualBox

Changeset 32087 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Aug 30, 2010 12:23:05 PM (14 years ago)
Author:
vboxsync
Message:

PGM: Account for aliased and off pages in physical handlers so that PGMR0Trap0eHandlerNPMisconfig can avoid resolving the PGMPAGE when these features are not used.

Location:
trunk/src/VBox/VMM/VMMAll
Files:
2 edited

Legend:

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

    r32036 r32087  
    9696        case PGMPHYSHANDLERTYPE_MMIO:
    9797        case PGMPHYSHANDLERTYPE_PHYSICAL_ALL:
    98             /* Simplification in PGMPhysRead among other places. */
     98            /* Simplification for PGMPhysRead, PGMR0Trap0eHandlerNPMisconfig and others. */
    9999            AssertMsgReturn(!(GCPhys & PAGE_OFFSET_MASK), ("%RGp\n", GCPhys), VERR_INVALID_PARAMETER);
    100100            AssertMsgReturn((GCPhysLast & PAGE_OFFSET_MASK) == PAGE_OFFSET_MASK, ("%RGp\n", GCPhysLast), VERR_INVALID_PARAMETER);
     
    146146    pNew->enmType       = enmType;
    147147    pNew->cPages        = (GCPhysLast - (GCPhys & X86_PTE_PAE_PG_MASK) + PAGE_SIZE) >> PAGE_SHIFT;
     148    pNew->cAliasedPages = 0;
     149    pNew->cTmpOffPages  = 0;
    148150    pNew->pfnHandlerR3  = pfnHandlerR3;
    149151    pNew->pvUserR3      = pvUserR3;
     
    219221            PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, uState);
    220222
    221             int rc2 = pgmPoolTrackUpdateGCPhys(pVM, pRam->GCPhys + (i << PAGE_SHIFT), pPage, false /* allow updates of PTEs (instead of flushing) */, &fFlushTLBs);
     223            int rc2 = pgmPoolTrackUpdateGCPhys(pVM, pRam->GCPhys + (i << PAGE_SHIFT), pPage,
     224                                               false /* allow updates of PTEs (instead of flushing) */, &fFlushTLBs);
    222225            if (rc2 != VINF_SUCCESS && rc == VINF_SUCCESS)
    223226                rc = rc2;
     
    350353
    351354/**
    352  * pgmHandlerPhysicalResetRamFlags helper that checks for
    353  * other handlers on edge pages.
    354  */
    355 DECLINLINE(void) pgmHandlerPhysicalRecalcPageState(PPGM pPGM, RTGCPHYS GCPhys, bool fAbove, PPGMRAMRANGE *ppRamHint)
     355 * pgmHandlerPhysicalResetRamFlags helper that checks for other handlers on
     356 * edge pages.
     357 */
     358DECLINLINE(void) pgmHandlerPhysicalRecalcPageState(PVM pVM, RTGCPHYS GCPhys, bool fAbove, PPGMRAMRANGE *ppRamHint)
    356359{
    357360    /*
     
    361364    for (;;)
    362365    {
    363         PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysGetBestFit(&pPGM->CTX_SUFF(pTrees)->PhysHandlers, GCPhys, fAbove);
     366        PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysGetBestFit(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys, fAbove);
    364367        if (    !pCur
    365368            ||  ((fAbove ? pCur->Core.Key : pCur->Core.KeyLast) >> PAGE_SHIFT) != (GCPhys >> PAGE_SHIFT))
     
    384387    {
    385388        PPGMPAGE pPage;
    386         int rc = pgmPhysGetPageWithHintEx(pPGM, GCPhys, &pPage, ppRamHint);
     389        int rc = pgmPhysGetPageWithHintEx(&pVM->pgm.s, GCPhys, &pPage, ppRamHint);
    387390        if (    RT_SUCCESS(rc)
    388391            &&  PGM_PAGE_GET_HNDL_PHYS_STATE(pPage) < uState)
     392        {
     393            /* This should normally not be necessary. */
    389394            PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, uState);
     395            bool fFlushTLBs ;
     396            rc = pgmPoolTrackUpdateGCPhys(pVM, GCPhys, pPage, false /*fFlushPTEs*/, &fFlushTLBs);
     397            if (RT_SUCCESS(rc) && fFlushTLBs)
     398                PGM_INVL_ALL_VCPU_TLBS(pVM);
     399            else
     400                AssertRC(rc);
     401        }
    390402        else
    391403            AssertRC(rc);
     
    397409 * Resets an aliased page.
    398410 *
    399  * @param   pVM         The VM.
    400  * @param   pPage       The page.
    401  * @param   GCPhysPage  The page address in case it comes in handy.
    402  */
    403 void pgmHandlerPhysicalResetAliasedPage(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhysPage)
     411 * @param   pVM             The VM.
     412 * @param   pPage           The page.
     413 * @param   GCPhysPage      The page address in case it comes in handy.
     414 * @param   fDoAccounting   Whether to perform accounting.  (Only set during
     415 *                          reset where pgmR3PhysRamReset doesn't have the
     416 *                          handler structure handy.)
     417 */
     418void pgmHandlerPhysicalResetAliasedPage(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhysPage, bool fDoAccounting)
    404419{
    405420    Assert(PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_MMIO2_ALIAS_MMIO);
     
    410425     */
    411426    bool fFlushTLBs = false;
    412     int rc = pgmPoolTrackFlushGCPhys(pVM, GCPhysPage, pPage, &fFlushTLBs);
     427    int rc = pgmPoolTrackUpdateGCPhys(pVM, GCPhysPage, pPage, true /*fFlushPTEs*/, &fFlushTLBs);
    413428    AssertLogRelRCReturnVoid(rc);
    414429# ifdef IN_RC
     
    431446    PGMPhysInvalidatePageMapTLBEntry(pVM, GCPhysPage);
    432447
    433     NOREF(GCPhysPage);
     448    /*
     449     * Do accounting for pgmR3PhysRamReset.
     450     */
     451    if (fDoAccounting)
     452    {
     453        PPGMPHYSHANDLER pHandler = pgmHandlerPhysicalLookup(pVM, GCPhysPage);
     454        if (RT_LIKELY(pHandler))
     455        {
     456            Assert(pHandler->cAliasedPages > 0);
     457            pHandler->cAliasedPages--;
     458        }
     459        else
     460            AssertFailed();
     461    }
    434462}
    435463
     
    443471 * @param   pCur    The physical handler.
    444472 *
    445  * @remark  We don't start messing with the shadow page tables, as we've already got code
    446  *          in Trap0e which deals with out of sync handler flags (originally conceived for
    447  *          global pages).
     473 * @remark  We don't start messing with the shadow page tables, as we've
     474 *          already got code in Trap0e which deals with out of sync handler
     475 *          flags (originally conceived for global pages).
    448476 */
    449477static void pgmHandlerPhysicalResetRamFlags(PVM pVM, PPGMPHYSHANDLER pCur)
     
    465493               (We don't flip MMIO to RAM though, that's PGMPhys.cpp's job.)  */
    466494            if (PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_MMIO2_ALIAS_MMIO)
    467                 pgmHandlerPhysicalResetAliasedPage(pVM, pPage, GCPhys);
     495            {
     496                Assert(pCur->cAliasedPages > 0);
     497                pgmHandlerPhysicalResetAliasedPage(pVM, pPage, GCPhys, false /*fDoAccounting*/);
     498                pCur->cAliasedPages--;
     499            }
    468500            AssertMsg(pCur->enmType != PGMPHYSHANDLERTYPE_MMIO || PGM_PAGE_IS_MMIO(pPage), ("%RGp %R[pgmpage]\n", GCPhys, pPage));
    469501            PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, PGM_PAGE_HNDL_PHYS_STATE_NONE);
     
    478510    }
    479511
     512    pCur->cAliasedPages = 0;
     513    pCur->cTmpOffPages  = 0;
     514
    480515    /*
    481516     * Check for partial start and end pages.
    482517     */
    483518    if (pCur->Core.Key & PAGE_OFFSET_MASK)
    484         pgmHandlerPhysicalRecalcPageState(pPGM, pCur->Core.Key - 1, false /* fAbove */, &pRamHint);
    485     if ((pCur->Core.KeyLast & PAGE_OFFSET_MASK) != PAGE_SIZE - 1)
    486         pgmHandlerPhysicalRecalcPageState(pPGM, pCur->Core.KeyLast + 1, true /* fAbove */, &pRamHint);
     519        pgmHandlerPhysicalRecalcPageState(pVM, pCur->Core.Key - 1, false /* fAbove */, &pRamHint);
     520    if ((pCur->Core.KeyLast & PAGE_OFFSET_MASK) != PAGE_OFFSET_MASK)
     521        pgmHandlerPhysicalRecalcPageState(pVM, pCur->Core.KeyLast + 1, true /* fAbove */, &pRamHint);
    487522}
    488523
     
    795830
    796831/**
    797  * Resets any modifications to individual pages in a physical
    798  * page access handler region.
    799  *
    800  * This is used in pair with PGMHandlerPhysicalPageTempOff() or
    801  * PGMHandlerPhysicalPageAlias().
     832 * Resets any modifications to individual pages in a physical page access
     833 * handler region.
     834 *
     835 * This is used in pair with PGMHandlerPhysicalPageTempOff(),
     836 * PGMHandlerPhysicalPageAlias() or PGMHandlerPhysicalPageAliasHC().
    802837 *
    803838 * @returns VBox status code.
     
    808843 *                      PGMHandlerPhysicalModify().
    809844 */
    810 VMMDECL(int)  PGMHandlerPhysicalReset(PVM pVM, RTGCPHYS GCPhys)
     845VMMDECL(int) PGMHandlerPhysicalReset(PVM pVM, RTGCPHYS GCPhys)
    811846{
    812847    LogFlow(("PGMHandlerPhysicalReset GCPhys=%RGp\n", GCPhys));
     
    842877                     * to do that now...
    843878                     */
    844                     PPGMPAGE    pPage = &pRam->aPages[(pCur->Core.Key - pRam->GCPhys) >> PAGE_SHIFT];
    845                     uint32_t    cLeft = pCur->cPages;
    846                     while (cLeft-- > 0)
     879                    if (pCur->cAliasedPages)
    847880                    {
    848                         if (PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_MMIO2_ALIAS_MMIO)
    849                             pgmHandlerPhysicalResetAliasedPage(pVM, pPage, pRam->GCPhys + ((RTGCPHYS)(uintptr_t)(pPage - &pRam->aPages[0]) << PAGE_SHIFT));
    850                         Assert(PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_MMIO);
    851                         pPage++;
     881                        PPGMPAGE    pPage = &pRam->aPages[(pCur->Core.Key - pRam->GCPhys) >> PAGE_SHIFT];
     882                        uint32_t    cLeft = pCur->cPages;
     883                        while (cLeft-- > 0)
     884                        {
     885                            if (PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_MMIO2_ALIAS_MMIO)
     886                            {
     887                                Assert(pCur->cAliasedPages > 0);
     888                                pgmHandlerPhysicalResetAliasedPage(pVM, pPage, pRam->GCPhys + ((RTGCPHYS)cLeft << PAGE_SHIFT),
     889                                                                   false /*fDoAccounting*/);
     890                                --pCur->cAliasedPages;
     891#ifndef VBOX_STRICT
     892                                if (pCur->cAliasedPages == 0)
     893                                    break;
     894#endif
     895                            }
     896                            Assert(PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_MMIO);
     897                            pPage++;
     898                        }
     899                        Assert(pCur->cAliasedPages == 0);
    852900                    }
    853901                }
    854                 else
     902                else if (pCur->cTmpOffPages > 0)
    855903                {
    856904                    /*
     
    859907                    rc = pgmHandlerPhysicalSetRamFlagsAndFlushShadowPTs(pVM, pCur, pRam);
    860908                }
     909
     910                pCur->cAliasedPages = 0;
     911                pCur->cTmpOffPages  = 0;
    861912
    862913                rc = VINF_SUCCESS;
     
    930981            int rc = pgmPhysGetPageEx(&pVM->pgm.s, GCPhysPage, &pPage);
    931982            AssertReturnStmt(RT_SUCCESS_NP(rc), pgmUnlock(pVM), rc);
    932             PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, PGM_PAGE_HNDL_PHYS_STATE_DISABLED);
     983            if (PGM_PAGE_GET_HNDL_PHYS_STATE(pPage) != PGM_PAGE_HNDL_PHYS_STATE_DISABLED)
     984            {
     985                PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, PGM_PAGE_HNDL_PHYS_STATE_DISABLED);
     986                pCur->cTmpOffPages++;
     987            }
    933988            pgmUnlock(pVM);
    934989            return VINF_SUCCESS;
     
    10331088                Log(("PGMHandlerPhysicalPageAlias: GCPhysPage=%RGp (%R[pgmpage]; %RHp -> %RHp\n",
    10341089                     GCPhysPage, pPage, PGM_PAGE_GET_HCPHYS(pPage), PGM_PAGE_GET_HCPHYS(pPageRemap)));
    1035                 pgmHandlerPhysicalResetAliasedPage(pVM, pPage, GCPhysPage);
     1090                pgmHandlerPhysicalResetAliasedPage(pVM, pPage, GCPhysPage, false /*fDoAccounting*/);
     1091                pCur->cAliasedPages--;
    10361092            }
    10371093            Assert(PGM_PAGE_IS_ZERO(pPage));
     
    10481104            PGM_PAGE_SET_PAGEID(pPage, PGM_PAGE_GET_PAGEID(pPageRemap));
    10491105            PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, PGM_PAGE_HNDL_PHYS_STATE_DISABLED);
     1106            pCur->cAliasedPages++;
     1107            Assert(pCur->cAliasedPages <= pCur->cPages);
    10501108
    10511109            /* Flush its TLB entry. */
     
    11511209            PGM_PAGE_SET_PAGEID(pPage, NIL_GMM_PAGEID);
    11521210            PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, PGM_PAGE_HNDL_PHYS_STATE_DISABLED);
     1211            pCur->cAliasedPages++;
     1212            Assert(pCur->cAliasedPages <= pCur->cPages);
    11531213
    11541214            /* Flush its TLB entry. */
    11551215            PGMPhysInvalidatePageMapTLBEntry(pVM, GCPhysPage);
     1216
    11561217            LogFlow(("PGMHandlerPhysicalPageAliasHC: => %R[pgmpage]\n", pPage));
    11571218            pgmUnlock(pVM);
  • trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp

    r32036 r32087  
    399399     */
    400400    bool fFlushTLBs = false;
    401     int rc = pgmPoolTrackFlushGCPhys(pVM, GCPhys, pPage, &fFlushTLBs);
     401    int rc = pgmPoolTrackUpdateGCPhys(pVM, GCPhys, pPage, true /*fFlushTLBs*/, &fFlushTLBs);
    402402    AssertMsgReturn(rc == VINF_SUCCESS || rc == VINF_PGM_SYNC_CR3, ("%Rrc\n", rc), RT_FAILURE(rc) ? rc : VERR_IPE_UNEXPECTED_STATUS);
    403403
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