VirtualBox

Ignore:
Timestamp:
Oct 19, 2021 11:18:13 PM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
147650
Message:

VMM/NEM,PGM: First bunch changes for watered down guest memory managment for NEM. (Gets stuck in bios.) bugref:10122

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/PGMPhys.cpp

    r91732 r91848  
    11581158 * @param   GCPhys      The address of the first page.
    11591159 * @param   GCPhysLast  The address of the last page.
    1160  * @param   enmType     The page type to replace then with.
    1161  */
    1162 static int pgmR3PhysFreePageRange(PVM pVM, PPGMRAMRANGE pRam, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast, PGMPAGETYPE enmType)
     1160 * @param   pvMmio2     Pointer to the ring-3 mapping of any MMIO2 memory that
     1161 *                      will replace the pages we're freeing up.
     1162 */
     1163static int pgmR3PhysFreePageRange(PVM pVM, PPGMRAMRANGE pRam, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast, void *pvMmio2)
    11631164{
    11641165    PGM_LOCK_ASSERT_OWNER(pVM);
     1166
     1167#ifdef VBOX_WITH_PGM_NEM_MODE
     1168    /*
     1169     * In simplified memory mode we don't actually free the memory,
     1170     * we just unmap it and let NEM do any unlocking of it.
     1171     */
     1172    if (pVM->pgm.s.fNemMode)
     1173    {
     1174        Assert(VM_IS_NEM_ENABLED(pVM));
     1175        uint32_t const  fNemNotify = (pvMmio2 ? NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2 : 0) | NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE;
     1176        uint8_t         u2State    = 0; /* (We don't support UINT8_MAX here.) */
     1177        int rc = NEMR3NotifyPhysMmioExMapEarly(pVM, GCPhys, GCPhysLast - GCPhys + 1, fNemNotify,
     1178                                               pRam->pvR3 ? (uint8_t *)pRam->pvR3 + GCPhys - pRam->GCPhys : NULL,
     1179                                               pvMmio2, &u2State);
     1180        AssertLogRelRCReturn(rc, rc);
     1181
     1182        /* Iterate the pages. */
     1183        PPGMPAGE pPageDst   = &pRam->aPages[(GCPhys - pRam->GCPhys) >> PAGE_SHIFT];
     1184        uint32_t cPagesLeft = ((GCPhysLast - GCPhys) >> PAGE_SHIFT) + 1;
     1185        while (cPagesLeft-- > 0)
     1186        {
     1187            rc = pgmPhysFreePage(pVM, NULL, NULL, pPageDst, GCPhys, PGMPAGETYPE_MMIO);
     1188            AssertLogRelRCReturn(rc, rc); /* We're done for if this goes wrong. */
     1189
     1190            PGM_PAGE_SET_TYPE(pVM, pPageDst, PGMPAGETYPE_MMIO);
     1191            PGM_PAGE_SET_NEM_STATE(pPageDst, u2State);
     1192
     1193            GCPhys += PAGE_SIZE;
     1194            pPageDst++;
     1195        }
     1196        return rc;
     1197    }
     1198#endif /* VBOX_WITH_PGM_NEM_MODE */
     1199
     1200    /*
     1201     * Regular mode.
     1202     */
     1203    /* Prepare. */
    11651204    uint32_t            cPendingPages = 0;
    11661205    PGMMFREEPAGESREQ    pReq;
     
    11681207    AssertLogRelRCReturn(rc, rc);
    11691208
     1209#ifdef VBOX_WITH_NATIVE_NEM
     1210    /* Tell NEM up-front. */
     1211    uint8_t u2State = UINT8_MAX;
     1212    if (VM_IS_NEM_ENABLED(pVM))
     1213    {
     1214        uint32_t const fNemNotify = (pvMmio2 ? NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2 : 0) | NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE;
     1215        rc = NEMR3NotifyPhysMmioExMapEarly(pVM, GCPhys, GCPhysLast - GCPhys + 1, fNemNotify, NULL, pvMmio2, &u2State);
     1216        AssertLogRelRCReturnStmt(rc, GMMR3FreePagesCleanup(pReq), rc);
     1217    }
     1218#endif
     1219
    11701220    /* Iterate the pages. */
    11711221    PPGMPAGE pPageDst   = &pRam->aPages[(GCPhys - pRam->GCPhys) >> PAGE_SHIFT];
     
    11731223    while (cPagesLeft-- > 0)
    11741224    {
    1175         rc = pgmPhysFreePage(pVM, pReq, &cPendingPages, pPageDst, GCPhys, enmType);
     1225        rc = pgmPhysFreePage(pVM, pReq, &cPendingPages, pPageDst, GCPhys, PGMPAGETYPE_MMIO);
    11761226        AssertLogRelRCReturn(rc, rc); /* We're done for if this goes wrong. */
    11771227
    1178         PGM_PAGE_SET_TYPE(pVM, pPageDst, enmType);
     1228        PGM_PAGE_SET_TYPE(pVM, pPageDst, PGMPAGETYPE_MMIO);
     1229#ifdef VBOX_WITH_NATIVE_NEM
     1230        if (u2State != UINT8_MAX)
     1231            PGM_PAGE_SET_NEM_STATE(pPageDst, u2State);
     1232#endif
    11791233
    11801234        GCPhys += PAGE_SIZE;
     
    11821236    }
    11831237
     1238    /* Finish pending and cleanup. */
    11841239    if (cPendingPages)
    11851240    {
     
    16341689 * PGMR3PhysRegisterRam worker that initializes and links a RAM range.
    16351690 *
     1691 * In NEM mode, this will allocate the pages backing the RAM range and this may
     1692 * fail.  NEM registration may also fail.  (In regular HM mode it won't fail.)
     1693 *
     1694 * @returns VBox status code.
    16361695 * @param   pVM             The cross context VM structure.
    16371696 * @param   pNew            The new RAM range.
     
    16441703 * @param   pPrev           The previous RAM range (for linking).
    16451704 */
    1646 static void pgmR3PhysInitAndLinkRamRange(PVM pVM, PPGMRAMRANGE pNew, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast,
    1647                                          RTRCPTR RCPtrNew, RTR0PTR R0PtrNew, const char *pszDesc, PPGMRAMRANGE pPrev)
     1705static int pgmR3PhysInitAndLinkRamRange(PVM pVM, PPGMRAMRANGE pNew, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast,
     1706                                        RTRCPTR RCPtrNew, RTR0PTR R0PtrNew, const char *pszDesc, PPGMRAMRANGE pPrev)
    16481707{
    16491708    /*
    16501709     * Initialize the range.
    16511710     */
    1652     pNew->pSelfR0       = R0PtrNew != NIL_RTR0PTR ? R0PtrNew : MMHyperCCToR0(pVM, pNew);
     1711    pNew->pSelfR0       = R0PtrNew;
    16531712    pNew->GCPhys        = GCPhys;
    16541713    pNew->GCPhysLast    = GCPhysLast;
    16551714    pNew->cb            = GCPhysLast - GCPhys + 1;
    16561715    pNew->pszDesc       = pszDesc;
    1657     pNew->fFlags        = RCPtrNew != NIL_RTRCPTR ? PGM_RAM_RANGE_FLAGS_FLOATING : 0;
    16581716    pNew->pvR3          = NULL;
    16591717    pNew->paLSPages     = NULL;
     1718    pNew->fFlags        = 0;
     1719#ifndef PGM_WITHOUT_MAPPINGS
     1720    if (RCPtrNew != NIL_RTRCPTR)
     1721        pNew->fFlags   |= PGM_RAM_RANGE_FLAGS_FLOATING;
     1722#else
     1723    NOREF(RCPtrNew);
     1724#endif
    16601725
    16611726    uint32_t const cPages = pNew->cb >> PAGE_SHIFT;
    1662     RTGCPHYS iPage = cPages;
    1663     while (iPage-- > 0)
    1664         PGM_PAGE_INIT_ZERO(&pNew->aPages[iPage], pVM, PGMPAGETYPE_RAM);
    1665 
    1666     /* Update the page count stats. */
    1667     pVM->pgm.s.cZeroPages += cPages;
    1668     pVM->pgm.s.cAllPages  += cPages;
     1727#ifdef VBOX_WITH_PGM_NEM_MODE
     1728    if (!pVM->pgm.s.fNemMode)
     1729#endif
     1730    {
     1731        RTGCPHYS iPage = cPages;
     1732        while (iPage-- > 0)
     1733            PGM_PAGE_INIT_ZERO(&pNew->aPages[iPage], pVM, PGMPAGETYPE_RAM);
     1734
     1735        /* Update the page count stats. */
     1736        pVM->pgm.s.cZeroPages += cPages;
     1737        pVM->pgm.s.cAllPages  += cPages;
     1738    }
     1739#ifdef VBOX_WITH_PGM_NEM_MODE
     1740    else
     1741    {
     1742        int rc = SUPR3PageAlloc(cPages, &pNew->pvR3);
     1743        if (RT_FAILURE(rc))
     1744            return rc;
     1745
     1746        RTGCPHYS iPage = cPages;
     1747        while (iPage-- > 0)
     1748            PGM_PAGE_INIT(&pNew->aPages[iPage], UINT64_C(0x0000fffffffff000), NIL_GMM_PAGEID,
     1749                          PGMPAGETYPE_RAM, PGM_PAGE_STATE_ALLOCATED);
     1750
     1751        /* Update the page count stats. */
     1752        pVM->pgm.s.cPrivatePages += cPages;
     1753        pVM->pgm.s.cAllPages     += cPages;
     1754    }
     1755#endif
    16691756
    16701757    /*
     
    16721759     */
    16731760    pgmR3PhysLinkRamRange(pVM, pNew, pPrev);
     1761
     1762    /*
     1763     * Notify NEM now that it has been linked.
     1764     */
     1765    int rc = NEMR3NotifyPhysRamRegister(pVM, GCPhys, pNew->cb, pNew->pvR3);
     1766    if (RT_FAILURE(rc))
     1767        pgmR3PhysUnlinkRamRange2(pVM, pNew, pPrev);
     1768    return rc;
    16741769}
    16751770
     
    17571852         * We push these in below the HMA.
    17581853         */
    1759         RTGCPTR GCPtrChunkMap = pVM->pgm.s.GCPtrPrevRamRangeMapping - cbChunk;
    1760 #ifndef PGM_WITHOUT_MAPPINGS
     1854#ifdef PGM_WITHOUT_MAPPINGS
     1855        RTGCPTR const GCPtrChunk = NIL_RTGCPTR;
     1856        RT_NOREF(cbChunk);
     1857#else
     1858        RTGCPTR const GCPtrChunkMap = pVM->pgm.s.GCPtrPrevRamRangeMapping - cbChunk;
    17611859        rc = PGMR3MapPT(pVM, GCPtrChunkMap, cbChunk, 0 /*fFlags*/, pgmR3PhysRamRangeRelocate, pNew, pszDescChunk);
    17621860        if (RT_SUCCESS(rc))
    1763 #endif /* !PGM_WITHOUT_MAPPINGS */
    17641861        {
    17651862            pVM->pgm.s.GCPtrPrevRamRangeMapping = GCPtrChunkMap;
    17661863
    17671864            RTGCPTR const   GCPtrChunk = GCPtrChunkMap + PAGE_SIZE;
    1768 #ifndef PGM_WITHOUT_MAPPINGS
    17691865            RTGCPTR         GCPtrPage  = GCPtrChunk;
    17701866            for (uint32_t iPage = 0; iPage < cChunkPages && RT_SUCCESS(rc); iPage++, GCPtrPage += PAGE_SIZE)
     
    17761872                 * Ok, init and link the range.
    17771873                 */
    1778                 pgmR3PhysInitAndLinkRamRange(pVM, pNew, GCPhys, GCPhys + ((RTGCPHYS)cRamPages << PAGE_SHIFT) - 1,
    1779                                              (RTRCPTR)GCPtrChunk, R0PtrChunk, pszDescChunk, *ppPrev);
    1780                 *ppPrev = pNew;
     1874                rc = pgmR3PhysInitAndLinkRamRange(pVM, pNew, GCPhys, GCPhys + ((RTGCPHYS)cRamPages << PAGE_SHIFT) - 1,
     1875                                                  (RTRCPTR)GCPtrChunk, R0PtrChunk, pszDescChunk, *ppPrev);
     1876                if (RT_SUCCESS(rc))
     1877                    *ppPrev = pNew;
    17811878            }
    1782         }
     1879#ifndef PGM_WITHOUT_MAPPINGS
     1880        }
     1881#endif
    17831882
    17841883        if (RT_FAILURE(rc))
     
    18971996        PPGMRAMRANGE pNew;
    18981997        rc = MMR3HyperAllocOnceNoRel(pVM, cbRamRange, 0, MM_TAG_PGM_PHYS, (void **)&pNew);
    1899         AssertLogRelMsgRCReturn(rc, ("cbRamRange=%zu\n", cbRamRange), rc);
    1900 
    1901         pgmR3PhysInitAndLinkRamRange(pVM, pNew, GCPhys, GCPhysLast, NIL_RTRCPTR, NIL_RTR0PTR, pszDesc, pPrev);
     1998        AssertLogRelMsgRCReturn(rc, ("rc=%Rrc cbRamRange=%zu\n", rc, cbRamRange), rc);
     1999
     2000        rc = pgmR3PhysInitAndLinkRamRange(pVM, pNew, GCPhys, GCPhysLast, NIL_RTRCPTR, MMHyperCCToR0(pVM, pNew), pszDesc, pPrev);
     2001        AssertLogRelMsgRCReturn(rc, ("rc=%Rrc cbRamRange=%zu\n", rc, cbRamRange), rc);
    19022002    }
    19032003    pgmPhysInvalidatePageMapTLB(pVM);
    19042004
    1905     /*
    1906      * Notify NEM while holding the lock (experimental) and REM without (like always).
    1907      */
    1908     rc = NEMR3NotifyPhysRamRegister(pVM, GCPhys, cb);
    19092005    PGM_UNLOCK(pVM);
    19102006    return rc;
     
    19262022    Assert(pVM->pgm.s.fRamPreAlloc);
    19272023    Log(("pgmR3PhysRamPreAllocate: enter\n"));
     2024#ifdef VBOX_WITH_PGM_NEM_MODE
     2025    AssertLogRelReturn(!pVM->pgm.s.fNemMode, VERR_PGM_NOT_SUPPORTED_FOR_NEM_MODE);
     2026#endif
    19282027
    19292028    /*
     
    21002199
    21012200        if (   !pVM->pgm.s.fRamPreAlloc
     2201#ifdef VBOX_WITH_PGM_NEM_MODE
     2202            && !pVM->pgm.s.fNemMode
     2203#endif
    21022204            && pVM->pgm.s.fZeroRamPagesOnReset)
    21032205        {
     
    21352237                    case PGMPAGETYPE_SPECIAL_ALIAS_MMIO: /** @todo perhaps leave the special page alone?  I don't think VT-x copes with this code. */
    21362238                        pgmHandlerPhysicalResetAliasedPage(pVM, pPage, pRam->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT),
    2137                                                            true /*fDoAccounting*/);
     2239                                                           pRam, true /*fDoAccounting*/);
    21382240                        break;
    21392241
     
    21882290                    case PGMPAGETYPE_SPECIAL_ALIAS_MMIO: /** @todo perhaps leave the special page alone?  I don't think VT-x copes with this code. */
    21892291                        pgmHandlerPhysicalResetAliasedPage(pVM, pPage, pRam->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT),
    2190                                                            true /*fDoAccounting*/);
     2292                                                           pRam, true /*fDoAccounting*/);
    21912293                        break;
    21922294
     
    23962498         * for PCI memory, but we're doing the same thing for MMIO2 pages.
    23972499         */
    2398         rc = pgmR3PhysFreePageRange(pVM, pRam, GCPhys, GCPhysLast, PGMPAGETYPE_MMIO);
     2500        rc = pgmR3PhysFreePageRange(pVM, pRam, GCPhys, GCPhysLast, NULL);
    23992501        AssertRCReturnStmt(rc, PGM_UNLOCK(pVM), rc);
    24002502
     
    24092511    else
    24102512    {
    2411 
    24122513        /*
    24132514         * No RAM range, insert an ad hoc one.
     
    24182519        Log(("PGMR3PhysMMIORegister: Adding ad hoc MMIO range for %RGp-%RGp %s\n", GCPhys, GCPhysLast, pszDesc));
    24192520
     2521        /* Alloc. */
    24202522        const uint32_t cPages = cb >> PAGE_SHIFT;
    24212523        const size_t cbRamRange = RT_UOFFSETOF_DYN(PGMRAMRANGE, aPages[cPages]);
    24222524        rc = MMHyperAlloc(pVM, RT_UOFFSETOF_DYN(PGMRAMRANGE, aPages[cPages]), 16, MM_TAG_PGM_PHYS, (void **)&pNew);
    24232525        AssertLogRelMsgRCReturnStmt(rc, ("cbRamRange=%zu\n", cbRamRange), PGM_UNLOCK(pVM), rc);
     2526
     2527#ifdef VBOX_WITH_NATIVE_NEM
     2528        /* Notify NEM. */
     2529        uint8_t u2State = 0; /* (must have valid state as there can't be anything to preserve) */
     2530        if (VM_IS_NEM_ENABLED(pVM))
     2531        {
     2532            rc = NEMR3NotifyPhysMmioExMapEarly(pVM, GCPhys, cPages << PAGE_SHIFT, 0 /*fFlags*/, NULL, NULL, &u2State);
     2533            AssertLogRelRCReturnStmt(rc, MMHyperFree(pVM, pNew), rc);
     2534        }
     2535#endif
    24242536
    24252537        /* Initialize the range. */
     
    24352547        uint32_t iPage = cPages;
    24362548        while (iPage-- > 0)
     2549        {
    24372550            PGM_PAGE_INIT_ZERO(&pNew->aPages[iPage], pVM, PGMPAGETYPE_MMIO);
     2551#ifdef VBOX_WITH_NATIVE_NEM
     2552            PGM_PAGE_SET_NEM_STATE(&pNew->aPages[iPage], u2State);
     2553#endif
     2554        }
    24382555        Assert(PGM_PAGE_GET_TYPE(&pNew->aPages[0]) == PGMPAGETYPE_MMIO);
    24392556
     
    24502567     */
    24512568    rc = PGMHandlerPhysicalRegister(pVM, GCPhys, GCPhysLast, hType, pvUserR3, pvUserR0, pvUserRC, pszDesc);
    2452     if (    RT_FAILURE(rc)
    2453         &&  !fRamExists)
     2569    if (RT_SUCCESS(rc))
     2570    {
     2571#ifdef VBOX_WITH_NATIVE_NEM
     2572        /* Late NEM notification. */
     2573        if (VM_IS_NEM_ENABLED(pVM))
     2574        {
     2575            uint32_t const fNemNotify = (fRamExists ? NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE : 0);
     2576            rc = NEMR3NotifyPhysMmioExMapLate(pVM, GCPhys, GCPhysLast - GCPhys + 1, fNemNotify,
     2577                                              fRamExists ? (uint8_t *)pRam->pvR3 + (uintptr_t)(GCPhys - pRam->GCPhys) : NULL,
     2578                                              NULL);
     2579            AssertLogRelRCReturn(rc, rc);
     2580        }
     2581#endif
     2582    }
     2583    /** @todo the phys handler failure handling isn't complete, esp. wrt NEM. */
     2584    else if (!fRamExists)
    24542585    {
    24552586        pVM->pgm.s.cPureMmioPages -= cb >> PAGE_SHIFT;
     
    25322663                    Log(("PGMR3PhysMMIODeregister: Freeing ad hoc MMIO range for %RGp-%RGp %s\n",
    25332664                         GCPhys, GCPhysLast, pRam->pszDesc));
     2665                    /** @todo check the ad-hoc flags? */
     2666
     2667#ifdef VBOX_WITH_NATIVE_NEM
     2668                    if (VM_IS_NEM_ENABLED(pVM)) /* Notify REM before we unlink the range. */
     2669                    {
     2670                        rc = NEMR3NotifyPhysMmioExUnmap(pVM, GCPhys, GCPhysLast - GCPhys + 1, 0 /*fFlags*/, NULL, NULL, NULL);
     2671                        AssertLogRelRCReturn(rc, rc);
     2672                    }
     2673#endif
    25342674
    25352675                    pVM->pgm.s.cAllPages      -= cPages;
     
    25682708                    iPage++;
    25692709                }
     2710
     2711#ifdef VBOX_WITH_NATIVE_NEM
     2712                /* Notify REM (failure will probably leave things in a non-working state). */
     2713                if (VM_IS_NEM_ENABLED(pVM))
     2714                {
     2715                    uint8_t u2State = UINT8_MAX;
     2716                    rc = NEMR3NotifyPhysMmioExUnmap(pVM, GCPhys, GCPhysLast - GCPhys + 1, NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE,
     2717                                                    pRam->pvR3 ? (uint8_t *)pRam->pvR3 + GCPhys - pRam->GCPhys : NULL,
     2718                                                    NULL, &u2State);
     2719                    AssertLogRelRCReturn(rc, rc);
     2720                    if (u2State != UINT8_MAX)
     2721                        pgmPhysSetNemStateForPages(&pRam->aPages[(GCPhys - pRam->GCPhys) >> PAGE_SHIFT],
     2722                                                   cb >> PAGE_SHIFT, u2State);
     2723                }
     2724#endif
    25702725                break;
    25712726            }
     
    33843539         * for PCI memory, but we're doing the same thing for MMIO2 pages.
    33853540         *
    3386          * We replace this MMIO/ZERO pages with real pages in the MMIO2 case.
     3541         * We replace these MMIO/ZERO pages with real pages in the MMIO2 case.
    33873542         */
    33883543        Assert(pFirstMmio->fFlags & PGMREGMMIO2RANGE_F_LAST_CHUNK); /* Only one chunk */
    3389 
    3390         int rc = pgmR3PhysFreePageRange(pVM, pRam, GCPhys, GCPhysLast, PGMPAGETYPE_MMIO);
     3544        Assert(pFirstMmio->pvR3 == pFirstMmio->RamRange.pvR3);
     3545        Assert(pFirstMmio->fFlags & PGMREGMMIO2RANGE_F_MMIO2
     3546               ? pFirstMmio->RamRange.pvR3 != NULL : pFirstMmio->RamRange.pvR3 == NULL);
     3547
     3548#ifdef VBOX_WITH_PGM_NEM_MODE
     3549        /* We cannot mix MMIO2 into a RAM range in simplified memory mode because pRam->pvR3 can't point
     3550           both at the RAM and MMIO2, so we won't ever write & read from the actual MMIO2 memory if we try. */
     3551        AssertLogRelMsgReturn(!pVM->pgm.s.fNemMode || !(pFirstMmio->fFlags & PGMREGMMIO2RANGE_F_MMIO2),
     3552                              ("%s at %RGp-%RGp\n", pFirstMmio->RamRange.pszDesc, GCPhys, GCPhysLast),
     3553                              VERR_PGM_NOT_SUPPORTED_FOR_NEM_MODE);
     3554#endif
     3555
     3556        int rc = pgmR3PhysFreePageRange(pVM, pRam, GCPhys, GCPhysLast, pFirstMmio->RamRange.pvR3);
    33913557        AssertRCReturnStmt(rc, PGM_UNLOCK(pVM), rc);
    33923558
     
    34103576                PGM_PAGE_SET_PTE_INDEX(pVM, pPageDst, 0);
    34113577                PGM_PAGE_SET_TRACKING(pVM, pPageDst, 0);
    3412                 /* (We tell NEM at the end of the function.) */
     3578                /* NEM state is set by pgmR3PhysFreePageRange. */
    34133579
    34143580                pVM->pgm.s.cZeroPages--;
     
    34363602        for (PPGMREGMMIO2RANGE pCurMmio = pFirstMmio; ; pCurMmio = pCurMmio->pNextR3)
    34373603        {
     3604#ifdef VBOX_WITH_NATIVE_NEM
     3605            /* Tell NEM and get the new NEM state for the pages. */
     3606            uint8_t u2NemState = 0;
     3607            if (VM_IS_NEM_ENABLED(pVM))
     3608            {
     3609                int rc = NEMR3NotifyPhysMmioExMapEarly(pVM, pCurMmio->RamRange.GCPhys,
     3610                                                       pCurMmio->RamRange.GCPhysLast - pCurMmio->RamRange.GCPhys + 1,
     3611                                                       pFirstMmio->fFlags & PGMREGMMIO2RANGE_F_MMIO2
     3612                                                       ? NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2 : 0,
     3613                                                       NULL, pCurMmio->RamRange.pvR3, &u2NemState);
     3614                AssertLogRelRCReturnStmt(rc, PGM_UNLOCK(pVM), rc);
     3615            }
     3616#endif
     3617
    34383618            /* Clear the tracking data of pages we're going to reactivate. */
    34393619            PPGMPAGE pPageSrc = &pCurMmio->RamRange.aPages[0];
     
    34433623                PGM_PAGE_SET_TRACKING(pVM, pPageSrc, 0);
    34443624                PGM_PAGE_SET_PTE_INDEX(pVM, pPageSrc, 0);
     3625#ifdef VBOX_WITH_NATIVE_NEM
     3626                PGM_PAGE_SET_NEM_STATE(pPageSrc, u2NemState);
     3627#endif
    34453628                pPageSrc++;
    34463629            }
     
    34873670                {
    34883671                    pCurMmio->fFlags &= ~PGMREGMMIO2RANGE_F_MAPPED;
    3489                     pgmHandlerPhysicalExDeregister(pVM, pCurMmio->pPhysHandlerR3, fRamExists);
     3672                    pgmHandlerPhysicalExDeregister(pVM, pCurMmio->pPhysHandlerR3);
    34903673                }
    34913674
     
    35113694            }
    35123695
     3696            /** @todo NEM notification cleanup */
    35133697            PGM_UNLOCK(pVM);
    35143698            return rc;
     
    35313715    pgmPhysInvalidatePageMapTLB(pVM);
    35323716
    3533     /*
    3534      * Notify NEM while holding the lock (experimental) and REM without (like always).
    3535      */
    3536     uint32_t const fNemNotify = (pFirstMmio->fFlags & PGMREGMMIO2RANGE_F_MMIO2       ? NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2   : 0)
    3537                               | (pFirstMmio->fFlags & PGMREGMMIO2RANGE_F_OVERLAPPING ? NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE : 0);
    3538     int rc = NEMR3NotifyPhysMmioExMap(pVM, GCPhys, cbRange, fNemNotify, pFirstMmio->pvR3);
     3717#ifdef VBOX_WITH_NATIVE_NEM
     3718    /*
     3719     * Late NEM notification.
     3720     */
     3721    if (VM_IS_NEM_ENABLED(pVM))
     3722    {
     3723        int rc;
     3724        uint32_t fNemFlags = pFirstMmio->fFlags & PGMREGMMIO2RANGE_F_MMIO2 ? NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2 : 0;
     3725        if (fRamExists)
     3726            rc = NEMR3NotifyPhysMmioExMapLate(pVM, GCPhys, GCPhysLast - GCPhys + 1, fNemFlags | NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE,
     3727                                              pRam->pvR3 ? (uint8_t *)pRam->pvR3 + GCPhys - pRam->GCPhys : NULL, pFirstMmio->pvR3);
     3728        else
     3729        {
     3730            rc = VINF_SUCCESS;
     3731            for (PPGMREGMMIO2RANGE pCurMmio = pFirstMmio; ; pCurMmio = pCurMmio->pNextR3)
     3732            {
     3733                rc = NEMR3NotifyPhysMmioExMapLate(pVM, pCurMmio->RamRange.GCPhys, pCurMmio->RamRange.cb, fNemFlags,
     3734                                                  NULL, pCurMmio->RamRange.pvR3);
     3735                if ((pCurMmio->fFlags & PGMREGMMIO2RANGE_F_LAST_CHUNK) || RT_FAILURE(rc))
     3736                    break;
     3737            }
     3738        }
     3739        AssertLogRelRCReturnStmt(rc, PGMR3PhysMmio2Unmap(pVM, pDevIns, hMmio2, GCPhys); PGM_UNLOCK(pVM), rc);
     3740    }
     3741#endif
    35393742
    35403743    PGM_UNLOCK(pVM);
    35413744
    3542     return rc;
     3745    return VINF_SUCCESS;
    35433746}
    35443747
     
    36013804
    36023805        PPGMREGMMIO2RANGE pCurMmio = pFirstMmio;
    3603         rc = pgmHandlerPhysicalExDeregister(pVM, pFirstMmio->pPhysHandlerR3, RT_BOOL(fOldFlags & PGMREGMMIO2RANGE_F_OVERLAPPING));
     3806        rc = pgmHandlerPhysicalExDeregister(pVM, pFirstMmio->pPhysHandlerR3);
    36043807        AssertRCReturnStmt(rc, PGM_UNLOCK(pVM), rc);
    36053808        while (!(pCurMmio->fFlags & PGMREGMMIO2RANGE_F_LAST_CHUNK))
    36063809        {
    36073810            pCurMmio = pCurMmio->pNextR3;
    3608             rc = pgmHandlerPhysicalExDeregister(pVM, pCurMmio->pPhysHandlerR3, RT_BOOL(fOldFlags & PGMREGMMIO2RANGE_F_OVERLAPPING));
     3811            rc = pgmHandlerPhysicalExDeregister(pVM, pCurMmio->pPhysHandlerR3);
    36093812            AssertRCReturnStmt(rc, PGM_UNLOCK(pVM), VERR_PGM_PHYS_MMIO_EX_IPE);
    36103813        }
     
    36143817     * Unmap it.
    36153818     */
    3616     RTGCPHYS const GCPhysRangeNotify = pFirstMmio->RamRange.GCPhys;
     3819    int            rcRet     = VINF_SUCCESS;
     3820#ifdef VBOX_WITH_NATIVE_NEM
     3821    uint32_t const fNemFlags = pFirstMmio->fFlags & PGMREGMMIO2RANGE_F_MMIO2 ?  NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2 : 0;
     3822#endif
    36173823    if (fOldFlags & PGMREGMMIO2RANGE_F_OVERLAPPING)
    36183824    {
     
    36323838            pRam = pRam->pNextR3;
    36333839
     3840        PPGMPAGE pPageDst   = &pRam->aPages[(pFirstMmio->RamRange.GCPhys - pRam->GCPhys) >> PAGE_SHIFT];
    36343841        uint32_t cPagesLeft = pFirstMmio->RamRange.cb >> PAGE_SHIFT;
    36353842        if (fOldFlags & PGMREGMMIO2RANGE_F_MMIO2)
    36363843            pVM->pgm.s.cZeroPages += cPagesLeft;
    36373844
    3638         PPGMPAGE pPageDst = &pRam->aPages[(pFirstMmio->RamRange.GCPhys - pRam->GCPhys) >> PAGE_SHIFT];
     3845#ifdef VBOX_WITH_NATIVE_NEM
     3846        if (VM_IS_NEM_ENABLED(pVM)) /* Notify NEM. Note! we cannot be here in simple memory mode, see mapping function. */
     3847        {
     3848            uint8_t u2State = UINT8_MAX;
     3849            rc = NEMR3NotifyPhysMmioExUnmap(pVM, pFirstMmio->RamRange.GCPhys, pFirstMmio->RamRange.cb,
     3850                                            fNemFlags | NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE,
     3851                                            pRam->pvR3
     3852                                            ? (uint8_t *)pRam->pvR3 + pFirstMmio->RamRange.GCPhys - pRam->GCPhys : NULL,
     3853                                            pFirstMmio->pvR3, &u2State);
     3854            AssertRCStmt(rc, rcRet = rc);
     3855            if (u2State != UINT8_MAX)
     3856                pgmPhysSetNemStateForPages(pPageDst, cPagesLeft, u2State);
     3857        }
     3858#endif
     3859
    36393860        while (cPagesLeft-- > 0)
    36403861        {
     
    36583879        for (PPGMREGMMIO2RANGE pCurMmio = pFirstMmio; ; pCurMmio = pCurMmio->pNextR3)
    36593880        {
     3881#ifdef VBOX_WITH_NATIVE_NEM
     3882            if (VM_IS_NEM_ENABLED(pVM)) /* Notify NEM. */
     3883            {
     3884                uint8_t u2State = UINT8_MAX;
     3885                rc = NEMR3NotifyPhysMmioExUnmap(pVM, pCurMmio->RamRange.GCPhys, pCurMmio->RamRange.cb, fNemFlags,
     3886                                                NULL, pCurMmio->pvR3, &u2State);
     3887                AssertRCStmt(rc, rcRet = rc);
     3888                if (u2State != UINT8_MAX)
     3889                    pgmPhysSetNemStateForPages(pCurMmio->RamRange.aPages, pCurMmio->RamRange.cb >> PAGE_SHIFT, u2State);
     3890            }
     3891#endif
    36603892            pgmR3PhysUnlinkRamRange(pVM, &pCurMmio->RamRange);
    36613893            pCurMmio->RamRange.GCPhys = NIL_RTGCPHYS;
     
    36773909    pgmPhysInvalidatePageMapTLB(pVM);
    36783910    pgmPhysInvalidRamRangeTlbs(pVM);
    3679 
    3680     /*
    3681      * Notify NEM while holding the lock (experimental) and REM without (like always).
    3682      */
    3683     uint32_t const fNemFlags = (fOldFlags & PGMREGMMIO2RANGE_F_MMIO2       ? NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2   : 0)
    3684                              | (fOldFlags & PGMREGMMIO2RANGE_F_OVERLAPPING ? NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE : 0);
    3685     rc = NEMR3NotifyPhysMmioExUnmap(pVM, GCPhysRangeNotify, cbRange, fNemFlags);
    36863911
    36873912    PGM_UNLOCK(pVM);
     
    39314156 */
    39324157static int pgmR3PhysRomRegisterLocked(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPHYS cb,
    3933                                       const void *pvBinary, uint32_t cbBinary, uint32_t fFlags, const char *pszDesc)
     4158                                      const void *pvBinary, uint32_t cbBinary, uint8_t fFlags, const char *pszDesc)
    39344159{
    39354160    /*
     
    39694194     * Find the RAM location and check for conflicts.
    39704195     *
    3971      * Conflict detection is a bit different than for RAM
    3972      * registration since a ROM can be located within a RAM
    3973      * range. So, what we have to check for is other memory
    3974      * types (other than RAM that is) and that we don't span
    3975      * more than one RAM range (layz).
     4196     * Conflict detection is a bit different than for RAM registration since a
     4197     * ROM can be located within a RAM range. So, what we have to check for is
     4198     * other memory types (other than RAM that is) and that we don't span more
     4199     * than one RAM range (lazy).
    39764200     */
    39774201    bool            fRamExists = false;
     
    40084232                                   pRam->GCPhys + ((RTGCPHYS)(uintptr_t)(pPage - &pRam->aPages[0]) << PAGE_SHIFT),
    40094233                                   pPage, GCPhys, GCPhysLast, pszDesc), VERR_PGM_RAM_CONFLICT);
    4010             Assert(PGM_PAGE_IS_ZERO(pPage));
     4234            Assert(PGM_PAGE_IS_ZERO(pPage) || PGM_IS_IN_NEM_MODE(pVM));
    40114235            pPage++;
    40124236        }
     
    40264250    }
    40274251
    4028     /*
    4029      * Allocate memory for the virgin copy of the RAM.
    4030      */
    4031     PGMMALLOCATEPAGESREQ pReq;
    4032     int rc = GMMR3AllocatePagesPrepare(pVM, &pReq, cPages, GMMACCOUNT_BASE);
    4033     AssertRCReturn(rc, rc);
    4034 
    4035     for (uint32_t iPage = 0; iPage < cPages; iPage++)
    4036     {
    4037         pReq->aPages[iPage].HCPhysGCPhys = GCPhys + (iPage << PAGE_SHIFT);
    4038         pReq->aPages[iPage].idPage = NIL_GMM_PAGEID;
    4039         pReq->aPages[iPage].idSharedPage = NIL_GMM_PAGEID;
    4040     }
    4041 
    4042     rc = GMMR3AllocatePagesPerform(pVM, pReq);
    4043     if (RT_FAILURE(rc))
    4044     {
    4045         GMMR3AllocatePagesCleanup(pReq);
    4046         return rc;
     4252#ifdef VBOX_WITH_NATIVE_NEM
     4253    /*
     4254     * Early NEM notification before we've made any changes or anything.
     4255     */
     4256    uint32_t const fNemNotify = (fRamExists ? NEM_NOTIFY_PHYS_ROM_F_REPLACE : 0)
     4257                              | (fFlags & PGMPHYS_ROM_FLAGS_SHADOWED ? NEM_NOTIFY_PHYS_ROM_F_SHADOW : 0);
     4258    uint8_t        u2NemState = UINT8_MAX;
     4259    if (VM_IS_NEM_ENABLED(pVM))
     4260    {
     4261        int rc = NEMR3NotifyPhysRomRegisterEarly(pVM, GCPhys, cPages << PAGE_SHIFT,
     4262                                                fRamExists ? PGM_RAMRANGE_CALC_PAGE_R3PTR(pRam, GCPhys) : NULL,
     4263                                                fNemNotify, &u2NemState);
     4264        AssertLogRelRCReturn(rc, rc);
     4265    }
     4266#endif
     4267
     4268    /*
     4269     * Allocate memory for the virgin copy of the RAM.  In simplified memory mode,
     4270     * we allocate memory for any ad-hoc RAM range and for shadow pages.
     4271     */
     4272    PGMMALLOCATEPAGESREQ pReq  = NULL;
     4273#ifdef VBOX_WITH_PGM_NEM_MODE
     4274    void                *pvRam = NULL;
     4275    void                *pvAlt = NULL;
     4276    if (pVM->pgm.s.fNemMode)
     4277    {
     4278        if (!fRamExists)
     4279        {
     4280            int rc = SUPR3PageAlloc(cPages, &pvRam);
     4281            if (RT_FAILURE(rc))
     4282                return rc;
     4283        }
     4284        if (fFlags & PGMPHYS_ROM_FLAGS_SHADOWED)
     4285        {
     4286            int rc = SUPR3PageAlloc(cPages, &pvAlt);
     4287            if (RT_FAILURE(rc))
     4288            {
     4289                if (pvRam)
     4290                    SUPR3PageFree(pvRam, cPages);
     4291                return rc;
     4292            }
     4293        }
     4294    }
     4295    else
     4296#endif
     4297    {
     4298        int rc = GMMR3AllocatePagesPrepare(pVM, &pReq, cPages, GMMACCOUNT_BASE);
     4299        AssertRCReturn(rc, rc);
     4300
     4301        for (uint32_t iPage = 0; iPage < cPages; iPage++)
     4302        {
     4303            pReq->aPages[iPage].HCPhysGCPhys = GCPhys + (iPage << PAGE_SHIFT);
     4304            pReq->aPages[iPage].idPage = NIL_GMM_PAGEID;
     4305            pReq->aPages[iPage].idSharedPage = NIL_GMM_PAGEID;
     4306        }
     4307
     4308        rc = GMMR3AllocatePagesPerform(pVM, pReq);
     4309        if (RT_FAILURE(rc))
     4310        {
     4311            GMMR3AllocatePagesCleanup(pReq);
     4312            return rc;
     4313        }
    40474314    }
    40484315
     
    40514318     */
    40524319    PPGMROMRANGE pRomNew;
    4053     rc = MMHyperAlloc(pVM, RT_UOFFSETOF_DYN(PGMROMRANGE, aPages[cPages]), 0, MM_TAG_PGM_PHYS, (void **)&pRomNew);
     4320    int rc = MMHyperAlloc(pVM, RT_UOFFSETOF_DYN(PGMROMRANGE, aPages[cPages]), 0, MM_TAG_PGM_PHYS, (void **)&pRomNew);
    40544321    if (RT_SUCCESS(rc))
    40554322    {
     
    40624329             * Initialize and insert the RAM range (if required).
    40634330             */
     4331            uint32_t const idxFirstRamPage = fRamExists ? (GCPhys - pRam->GCPhys) >> PAGE_SHIFT : 0;
    40644332            PPGMROMPAGE pRomPage = &pRomNew->aPages[0];
    40654333            if (!fRamExists)
    40664334            {
     4335                /* New RAM range. */
    40674336                pRamNew->pSelfR0       = MMHyperCCToR0(pVM, pRamNew);
    40684337                pRamNew->GCPhys        = GCPhys;
     
    40744343                pRamNew->paLSPages     = NULL;
    40754344
    4076                 PPGMPAGE pPage = &pRamNew->aPages[0];
    4077                 for (uint32_t iPage = 0; iPage < cPages; iPage++, pPage++, pRomPage++)
     4345                PPGMPAGE pRamPage = &pRamNew->aPages[idxFirstRamPage];
     4346#ifdef VBOX_WITH_PGM_NEM_MODE
     4347                if (pVM->pgm.s.fNemMode)
    40784348                {
    4079                     PGM_PAGE_INIT(pPage,
    4080                                   pReq->aPages[iPage].HCPhysGCPhys,
    4081                                   pReq->aPages[iPage].idPage,
    4082                                   PGMPAGETYPE_ROM,
    4083                                   PGM_PAGE_STATE_ALLOCATED);
    4084 
    4085                     pRomPage->Virgin = *pPage;
     4349                    AssertPtr(pvRam); Assert(pReq == NULL);
     4350                    pRamNew->pvR3 = pvRam;
     4351                    for (uint32_t iPage = 0; iPage < cPages; iPage++, pRamPage++, pRomPage++)
     4352                    {
     4353                        PGM_PAGE_INIT(pRamPage, UINT64_C(0x0000fffffffff000), NIL_GMM_PAGEID,
     4354                                      PGMPAGETYPE_ROM, PGM_PAGE_STATE_ALLOCATED);
     4355                        pRomPage->Virgin = *pRamPage;
     4356                    }
    40864357                }
    4087 
    4088                 pVM->pgm.s.cAllPages += cPages;
     4358                else
     4359#endif
     4360                    for (uint32_t iPage = 0; iPage < cPages; iPage++, pRamPage++, pRomPage++)
     4361                    {
     4362                        PGM_PAGE_INIT(pRamPage,
     4363                                      pReq->aPages[iPage].HCPhysGCPhys,
     4364                                      pReq->aPages[iPage].idPage,
     4365                                      PGMPAGETYPE_ROM,
     4366                                      PGM_PAGE_STATE_ALLOCATED);
     4367
     4368                        pRomPage->Virgin = *pRamPage;
     4369                    }
     4370
     4371                pVM->pgm.s.cAllPages     += cPages;
     4372                pVM->pgm.s.cPrivatePages += cPages;
    40894373                pgmR3PhysLinkRamRange(pVM, pRamNew, pRamPrev);
    40904374            }
    40914375            else
    40924376            {
    4093                 PPGMPAGE pPage = &pRam->aPages[(GCPhys - pRam->GCPhys) >> PAGE_SHIFT];
    4094                 for (uint32_t iPage = 0; iPage < cPages; iPage++, pPage++, pRomPage++)
     4377                /* Existing RAM range. */
     4378                PPGMPAGE pRamPage = &pRam->aPages[idxFirstRamPage];
     4379#ifdef VBOX_WITH_PGM_NEM_MODE
     4380                if (pVM->pgm.s.fNemMode)
    40954381                {
    4096                     PGM_PAGE_SET_TYPE(pVM, pPage,   PGMPAGETYPE_ROM);
    4097                     PGM_PAGE_SET_HCPHYS(pVM, pPage, pReq->aPages[iPage].HCPhysGCPhys);
    4098                     PGM_PAGE_SET_STATE(pVM, pPage,  PGM_PAGE_STATE_ALLOCATED);
    4099                     PGM_PAGE_SET_PAGEID(pVM, pPage, pReq->aPages[iPage].idPage);
    4100                     PGM_PAGE_SET_PDE_TYPE(pVM, pPage, PGM_PAGE_PDE_TYPE_DONTCARE);
    4101                     PGM_PAGE_SET_PTE_INDEX(pVM, pPage, 0);
    4102                     PGM_PAGE_SET_TRACKING(pVM, pPage, 0);
    4103 
    4104                     pRomPage->Virgin = *pPage;
     4382                    Assert(pvRam == NULL); Assert(pReq == NULL);
     4383                    for (uint32_t iPage = 0; iPage < cPages; iPage++, pRamPage++, pRomPage++)
     4384                    {
     4385                        Assert(PGM_PAGE_GET_HCPHYS(pRamPage) == UINT64_C(0x0000fffffffff000));
     4386                        Assert(PGM_PAGE_GET_PAGEID(pRamPage) == NIL_GMM_PAGEID);
     4387                        Assert(PGM_PAGE_GET_STATE(pRamPage) == PGM_PAGE_STATE_ALLOCATED);
     4388                        PGM_PAGE_SET_TYPE(pVM, pRamPage, PGMPAGETYPE_ROM);
     4389                        PGM_PAGE_SET_STATE(pVM, pRamPage,  PGM_PAGE_STATE_ALLOCATED);
     4390                        PGM_PAGE_SET_PDE_TYPE(pVM, pRamPage, PGM_PAGE_PDE_TYPE_DONTCARE);
     4391                        PGM_PAGE_SET_PTE_INDEX(pVM, pRamPage, 0);
     4392                        PGM_PAGE_SET_TRACKING(pVM, pRamPage, 0);
     4393
     4394                        pRomPage->Virgin = *pRamPage;
     4395                    }
    41054396                }
    4106 
     4397                else
     4398#endif
     4399                {
     4400                    for (uint32_t iPage = 0; iPage < cPages; iPage++, pRamPage++, pRomPage++)
     4401                    {
     4402                        PGM_PAGE_SET_TYPE(pVM, pRamPage,   PGMPAGETYPE_ROM);
     4403                        PGM_PAGE_SET_HCPHYS(pVM, pRamPage, pReq->aPages[iPage].HCPhysGCPhys);
     4404                        PGM_PAGE_SET_STATE(pVM, pRamPage,  PGM_PAGE_STATE_ALLOCATED);
     4405                        PGM_PAGE_SET_PAGEID(pVM, pRamPage, pReq->aPages[iPage].idPage);
     4406                        PGM_PAGE_SET_PDE_TYPE(pVM, pRamPage, PGM_PAGE_PDE_TYPE_DONTCARE);
     4407                        PGM_PAGE_SET_PTE_INDEX(pVM, pRamPage, 0);
     4408                        PGM_PAGE_SET_TRACKING(pVM, pRamPage, 0);
     4409
     4410                        pRomPage->Virgin = *pRamPage;
     4411                    }
     4412                    pVM->pgm.s.cZeroPages    -= cPages;
     4413                    pVM->pgm.s.cPrivatePages += cPages;
     4414                }
    41074415                pRamNew = pRam;
    4108 
    4109                 pVM->pgm.s.cZeroPages -= cPages;
    41104416            }
    4111             pVM->pgm.s.cPrivatePages += cPages;
     4417
     4418            /* Set the NEM state of the pages if needed. */
     4419            if (u2NemState != UINT8_MAX)
     4420                pgmPhysSetNemStateForPages(&pRamNew->aPages[idxFirstRamPage], cPages, u2NemState);
    41124421
    41134422            /* Flush physical page map TLB. */
    41144423            pgmPhysInvalidatePageMapTLB(pVM);
    41154424
    4116 
    4117             /* Notify NEM before we register handlers. */
    4118             uint32_t const fNemNotify = (fRamExists ? NEM_NOTIFY_PHYS_ROM_F_REPLACE : 0)
    4119                                       | (fFlags & PGMPHYS_ROM_FLAGS_SHADOWED ? NEM_NOTIFY_PHYS_ROM_F_SHADOW : 0);
    4120             rc = NEMR3NotifyPhysRomRegisterEarly(pVM, GCPhys, cb, fNemNotify);
    4121 
    4122             /* Register the ROM access handler. */
    4123             if (RT_SUCCESS(rc))
    4124                 rc = PGMHandlerPhysicalRegister(pVM, GCPhys, GCPhysLast, pVM->pgm.s.hRomPhysHandlerType,
    4125                                                 pRomNew, MMHyperCCToR0(pVM, pRomNew), MMHyperCCToRC(pVM, pRomNew),
    4126                                                 pszDesc);
     4425            /*
     4426             * Register the ROM access handler.
     4427             */
     4428            rc = PGMHandlerPhysicalRegister(pVM, GCPhys, GCPhysLast, pVM->pgm.s.hRomPhysHandlerType,
     4429                                            pRomNew, MMHyperCCToR0(pVM, pRomNew), MMHyperCCToRC(pVM, pRomNew), pszDesc);
    41274430            if (RT_SUCCESS(rc))
    41284431            {
     
    41324435                 */
    41334436                size_t          cbBinaryLeft = cbBinary;
    4134                 PPGMPAGE        pRamPage     = &pRamNew->aPages[(GCPhys - pRamNew->GCPhys) >> PAGE_SHIFT];
     4437                PPGMPAGE        pRamPage     = &pRamNew->aPages[idxFirstRamPage];
    41354438                for (uint32_t iPage = 0; iPage < cPages; iPage++, pRamPage++)
    41364439                {
     
    41704473                    pRomNew->cbOriginal = cbBinary;
    41714474                    pRomNew->pszDesc    = pszDesc;
     4475#ifdef VBOX_WITH_PGM_NEM_MODE
     4476                    pRomNew->pbR3Alternate = (uint8_t *)pvAlt;
     4477#endif
    41724478                    pRomNew->pvOriginal = fFlags & PGMPHYS_ROM_FLAGS_PERMANENT_BINARY
    41734479                                        ? pvBinary : RTMemDup(pvBinary, cbBinary);
     
    41784484                            PPGMROMPAGE pPage = &pRomNew->aPages[iPage];
    41794485                            pPage->enmProt = PGMROMPROT_READ_ROM_WRITE_IGNORE;
    4180                             PGM_PAGE_INIT_ZERO(&pPage->Shadow, pVM, PGMPAGETYPE_ROM_SHADOW);
     4486#ifdef VBOX_WITH_PGM_NEM_MODE
     4487                            if (pVM->pgm.s.fNemMode)
     4488                                PGM_PAGE_INIT(&pPage->Shadow, UINT64_C(0x0000fffffffff000), NIL_GMM_PAGEID,
     4489                                              PGMPAGETYPE_ROM_SHADOW, PGM_PAGE_STATE_ALLOCATED);
     4490                            else
     4491#endif
     4492                                PGM_PAGE_INIT_ZERO(&pPage->Shadow, pVM, PGMPAGETYPE_ROM_SHADOW);
    41814493                        }
    41824494
     
    41844496                        if (fFlags & PGMPHYS_ROM_FLAGS_SHADOWED)
    41854497                        {
    4186                             pVM->pgm.s.cZeroPages += cPages;
    4187                             pVM->pgm.s.cAllPages  += cPages;
     4498#ifdef VBOX_WITH_PGM_NEM_MODE
     4499                            if (pVM->pgm.s.fNemMode)
     4500                                pVM->pgm.s.cPrivatePages += cPages;
     4501                            else
     4502#endif
     4503                                pVM->pgm.s.cZeroPages += cPages;
     4504                            pVM->pgm.s.cAllPages += cPages;
    41884505                        }
    41894506
     
    42064523
    42074524                        pgmPhysInvalidatePageMapTLB(pVM);
    4208                         GMMR3AllocatePagesCleanup(pReq);
    4209 
    4210                         /* Notify NEM again. */
    4211                         return NEMR3NotifyPhysRomRegisterLate(pVM, GCPhys, cb, fNemNotify);
     4525#ifdef VBOX_WITH_PGM_NEM_MODE
     4526                        if (!pVM->pgm.s.fNemMode)
     4527#endif
     4528                            GMMR3AllocatePagesCleanup(pReq);
     4529
     4530                        /*
     4531                         * Notify NEM again.
     4532                         */
     4533                        u2NemState = UINT8_MAX;
     4534                        rc = NEMR3NotifyPhysRomRegisterLate(pVM, GCPhys, cb, PGM_RAMRANGE_CALC_PAGE_R3PTR(pRamNew, GCPhys),
     4535                                                            fNemNotify, &u2NemState);
     4536                        if (u2NemState != UINT8_MAX)
     4537                            pgmPhysSetNemStateForPages(&pRamNew->aPages[idxFirstRamPage], cPages, u2NemState);
     4538                        if (RT_SUCCESS(rc))
     4539                            return rc;
     4540
     4541                        /*
     4542                         * bail out
     4543                         */
     4544                        /* unlink */
     4545                        if (pRomPrev)
     4546                        {
     4547                            pRomPrev->pNextR3 = pRom;
     4548                            pRomPrev->pNextR0 = pRom ? MMHyperCCToR0(pVM, pRom) : NIL_RTR0PTR;
     4549                        }
     4550                        else
     4551                        {
     4552                            pVM->pgm.s.pRomRangesR3 = pRom;
     4553                            pVM->pgm.s.pRomRangesR0 = pRom ? MMHyperCCToR0(pVM, pRom) : NIL_RTR0PTR;
     4554                        }
     4555
     4556                        if (fFlags & PGMPHYS_ROM_FLAGS_SHADOWED)
     4557                        {
     4558#ifdef VBOX_WITH_PGM_NEM_MODE
     4559                            if (pVM->pgm.s.fNemMode)
     4560                                pVM->pgm.s.cPrivatePages -= cPages;
     4561                            else
     4562#endif
     4563                                pVM->pgm.s.cZeroPages -= cPages;
     4564                            pVM->pgm.s.cAllPages -= cPages;
     4565                        }
     4566
    42124567                    }
    4213 
    4214                     /* bail out */
    4215                     rc = VERR_NO_MEMORY;
     4568                    else
     4569                        rc = VERR_NO_MEMORY;
    42164570                }
    42174571
     
    42254579                MMHyperFree(pVM, pRamNew);
    42264580            }
     4581            else
     4582            {
     4583                PPGMPAGE pRamPage = &pRam->aPages[idxFirstRamPage];
     4584#ifdef VBOX_WITH_PGM_NEM_MODE
     4585                if (pVM->pgm.s.fNemMode)
     4586                {
     4587                    Assert(pvRam == NULL); Assert(pReq == NULL);
     4588                    for (uint32_t iPage = 0; iPage < cPages; iPage++, pRamPage++, pRomPage++)
     4589                    {
     4590                        Assert(PGM_PAGE_GET_HCPHYS(pRamPage) == UINT64_C(0x0000fffffffff000));
     4591                        Assert(PGM_PAGE_GET_PAGEID(pRamPage) == NIL_GMM_PAGEID);
     4592                        Assert(PGM_PAGE_GET_STATE(pRamPage) == PGM_PAGE_STATE_ALLOCATED);
     4593                        PGM_PAGE_SET_TYPE(pVM, pRamPage, PGMPAGETYPE_RAM);
     4594                        PGM_PAGE_SET_STATE(pVM, pRamPage,  PGM_PAGE_STATE_ALLOCATED);
     4595                    }
     4596                }
     4597                else
     4598#endif
     4599                {
     4600                    for (uint32_t iPage = 0; iPage < cPages; iPage++, pRamPage++)
     4601                        PGM_PAGE_INIT_ZERO(pRamPage, pVM, PGMPAGETYPE_RAM);
     4602                    pVM->pgm.s.cZeroPages    += cPages;
     4603                    pVM->pgm.s.cPrivatePages -= cPages;
     4604                }
     4605            }
    42274606        }
    42284607        MMHyperFree(pVM, pRomNew);
     
    42304609
    42314610    /** @todo Purge the mapping cache or something... */
    4232     GMMR3FreeAllocatedPages(pVM, pReq);
    4233     GMMR3AllocatePagesCleanup(pReq);
     4611#ifdef VBOX_WITH_PGM_NEM_MODE
     4612    if (pVM->pgm.s.fNemMode)
     4613    {
     4614        Assert(!pReq);
     4615        if (pvRam)
     4616            SUPR3PageFree(pvRam, cPages);
     4617        if (pvAlt)
     4618            SUPR3PageFree(pvAlt, cPages);
     4619    }
     4620    else
     4621#endif
     4622    {
     4623        GMMR3FreeAllocatedPages(pVM, pReq);
     4624        GMMR3AllocatePagesCleanup(pReq);
     4625    }
    42344626    return rc;
    42354627}
     
    42674659 */
    42684660VMMR3DECL(int) PGMR3PhysRomRegister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPHYS cb,
    4269                                     const void *pvBinary, uint32_t cbBinary, uint32_t fFlags, const char *pszDesc)
     4661                                    const void *pvBinary, uint32_t cbBinary, uint8_t fFlags, const char *pszDesc)
    42704662{
    42714663    Log(("PGMR3PhysRomRegister: pDevIns=%p GCPhys=%RGp(-%RGp) cb=%RGp pvBinary=%p cbBinary=%#x fFlags=%#x pszDesc=%s\n",
     
    43084700             * out all the dirty pages and replace them by the zero page.
    43094701             */
     4702#ifdef VBOX_WITH_PGM_NEM_MODE
     4703            if (pVM->pgm.s.fNemMode)
     4704            {
     4705                /* Clear all the shadow pages (currently using alternate backing). */
     4706                RT_BZERO(pRom->pbR3Alternate, pRom->cb);
     4707            }
     4708            else
     4709#endif
    43104710            if (!pVM->pgm.s.fRamPreAlloc)
    43114711            {
     
    44674867             * Iterate the relevant pages and make necessary the changes.
    44684868             */
     4869#ifdef VBOX_WITH_NATIVE_NEM
     4870            PPGMRAMRANGE const pRam = pgmPhysGetRange(pVM, GCPhys);
     4871            AssertPtrReturn(pRam, VERR_INTERNAL_ERROR_3);
     4872#endif
    44694873            bool fChanges = false;
    44704874            uint32_t const cPages = pRom->GCPhysLast <= GCPhysLast
     
    44814885
    44824886                    /* flush references to the page. */
    4483                     PPGMPAGE pRamPage = pgmPhysGetPage(pVM, pRom->GCPhys + (iPage << PAGE_SHIFT));
    4484                     int rc2 = pgmPoolTrackUpdateGCPhys(pVM, pRom->GCPhys + (iPage << PAGE_SHIFT), pRamPage,
    4485                                                       true /*fFlushPTEs*/, &fFlushTLB);
     4887                    RTGCPHYS const GCPhysPage = pRom->GCPhys + (iPage << PAGE_SHIFT);
     4888                    PPGMPAGE pRamPage = pgmPhysGetPage(pVM, GCPhysPage);
     4889                    int rc2 = pgmPoolTrackUpdateGCPhys(pVM, GCPhysPage, pRamPage, true /*fFlushPTEs*/, &fFlushTLB);
    44864890                    if (rc2 != VINF_SUCCESS && (rc == VINF_SUCCESS || RT_FAILURE(rc2)))
    44874891                        rc = rc2;
     
    44954899                    /** @todo preserve the volatile flags (handlers) when these have been moved out of HCPhys! */
    44964900
     4901#ifdef VBOX_WITH_NATIVE_NEM
     4902# ifdef VBOX_WITH_PGM_NEM_MODE
     4903                    /* In simplified mode we have to switch the page data around too. */
     4904                    if (pVM->pgm.s.fNemMode)
     4905                    {
     4906                        uint8_t         abPage[PAGE_SIZE];
     4907                        uint8_t * const pbRamPage = PGM_RAMRANGE_CALC_PAGE_R3PTR(pRam, GCPhysPage);
     4908                        memcpy(abPage, &pRom->pbR3Alternate[(size_t)iPage << PAGE_SHIFT], sizeof(abPage));
     4909                        memcpy(&pRom->pbR3Alternate[(size_t)iPage << PAGE_SHIFT], pbRamPage, sizeof(abPage));
     4910                        memcpy(pbRamPage, abPage, sizeof(abPage));
     4911                    }
     4912# endif
    44974913                    /* Tell NEM about the backing and protection change. */
    44984914                    if (VM_IS_NEM_ENABLED(pVM))
     
    45004916                        PGMPAGETYPE enmType = (PGMPAGETYPE)PGM_PAGE_GET_TYPE(pNew);
    45014917                        NEMHCNotifyPhysPageChanged(pVM, GCPhys, PGM_PAGE_GET_HCPHYS(pOld), PGM_PAGE_GET_HCPHYS(pNew),
     4918                                                   PGM_RAMRANGE_CALC_PAGE_R3PTR(pRam, GCPhysPage),
    45024919                                                   pgmPhysPageCalcNemProtection(pRamPage, enmType), enmType, &u2State);
    45034920                        PGM_PAGE_SET_NEM_STATE(pRamPage, u2State);
    45044921                    }
     4922#endif
    45054923                }
    45064924                pRomPage->enmProt = enmProt;
     
    52165634 *
    52175635 * @param   pVM             The cross context VM structure.
    5218  * @param   pReq            Pointer to the request.
     5636 * @param   pReq            Pointer to the request.  This is NULL when doing a
     5637 *                          bulk free in NEM memory mode.
    52195638 * @param   pcPendingPages  Where the number of pages waiting to be freed are
    5220  *                          kept.  This will normally be incremented.
     5639 *                          kept.  This will normally be incremented.  This is
     5640 *                          NULL when doing a bulk free in NEM memory mode.
    52215641 * @param   pPage           Pointer to the page structure.
    52225642 * @param   GCPhys          The guest physical address of the page, if applicable.
     
    52505670    const uint32_t idPage = PGM_PAGE_GET_PAGEID(pPage);
    52515671    Log3(("pgmPhysFreePage: idPage=%#x GCPhys=%RGp pPage=%R[pgmpage]\n", idPage, GCPhys, pPage));
    5252     if (RT_UNLIKELY(    idPage == NIL_GMM_PAGEID
    5253                     ||  idPage > GMM_PAGEID_LAST
    5254                     ||  PGM_PAGE_GET_CHUNKID(pPage) == NIL_GMM_CHUNKID))
     5672    if (RT_UNLIKELY(!PGM_IS_IN_NEM_MODE(pVM)
     5673                    ?    idPage == NIL_GMM_PAGEID
     5674                      ||  idPage > GMM_PAGEID_LAST
     5675                      ||  PGM_PAGE_GET_CHUNKID(pPage) == NIL_GMM_CHUNKID
     5676                    :    idPage != NIL_GMM_PAGEID))
    52555677    {
    52565678        AssertMsgFailed(("GCPhys=%RGp pPage=%R[pgmpage]\n", GCPhys, pPage));
     
    52865708    pgmPhysInvalidatePageMapTLBEntry(pVM, GCPhys);
    52875709
     5710#ifdef VBOX_WITH_PGM_NEM_MODE
     5711    /*
     5712     * Skip the rest if we're doing a bulk free in NEM memory mode.
     5713     */
     5714    if (!pReq)
     5715        return VINF_SUCCESS;
     5716    AssertLogRelReturn(!pVM->pgm.s.fNemMode, VERR_PGM_NOT_SUPPORTED_FOR_NEM_MODE);
     5717#endif
     5718
     5719#ifdef VBOX_WITH_NATIVE_NEM
    52885720    /* Notify NEM. */
    5289     /** @todo consider doing batch NEM notifications. */
     5721    /** @todo Remove this one? */
    52905722    if (VM_IS_NEM_ENABLED(pVM))
    52915723    {
    52925724        uint8_t u2State = PGM_PAGE_GET_NEM_STATE(pPage);
    5293         NEMHCNotifyPhysPageChanged(pVM, GCPhys, HCPhysPrev, pVM->pgm.s.HCPhysZeroPg,
     5725        NEMHCNotifyPhysPageChanged(pVM, GCPhys, HCPhysPrev, pVM->pgm.s.HCPhysZeroPg, pVM->pgm.s.pvZeroPgR3,
    52945726                                   pgmPhysPageCalcNemProtection(pPage, enmNewType), enmNewType, &u2State);
    52955727        PGM_PAGE_SET_NEM_STATE(pPage, u2State);
    52965728    }
     5729#endif
    52975730
    52985731    /*
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