VirtualBox

Changeset 91848 in vbox


Ignore:
Timestamp:
Oct 19, 2021 11:18:13 PM (3 years ago)
Author:
vboxsync
Message:

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

Location:
trunk
Files:
17 edited

Legend:

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

    r91587 r91848  
    653653/** One or more PAE PDPEs are invalid due to reserved bits being set. */
    654654#define VERR_PGM_PAE_PDPE_RSVD                  (-1688)
     655/** Attemted illegal operation in simplified memory management mode. */
     656#define VERR_PGM_NOT_SUPPORTED_FOR_NEM_MODE     (-1689)
    655657/** @} */
    656658
  • trunk/include/VBox/vmm/nem.h

    r91676 r91848  
    6262VMMR3_INT_DECL(void) NEMR3NotifyFF(PVM pVM, PVMCPU pVCpu, uint32_t fFlags);
    6363
    64 VMMR3_INT_DECL(int)  NEMR3NotifyPhysRamRegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb);
    65 VMMR3_INT_DECL(int)  NEMR3NotifyPhysMmioExMap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags, void *pvMmio2);
    66 VMMR3_INT_DECL(int)  NEMR3NotifyPhysMmioExUnmap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags);
     64VMMR3_INT_DECL(int)  NEMR3NotifyPhysRamRegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, void *pvR3);
     65VMMR3_INT_DECL(int)  NEMR3NotifyPhysMmioExMapEarly(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags,
     66                                                   void *pvRam, void *pvMmio2, uint8_t *pu2State);
     67VMMR3_INT_DECL(int)  NEMR3NotifyPhysMmioExMapLate(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags,
     68                                                  void *pvRam, void *pvMmio2);
     69VMMR3_INT_DECL(int)  NEMR3NotifyPhysMmioExUnmap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags,
     70                                                void *pvRam, void *pvMmio2, uint8_t *pu2State);
    6771/** @name Flags for NEMR3NotifyPhysMmioExMap and NEMR3NotifyPhysMmioExUnmap.
    6872 * @{ */
     
    7377/** @} */
    7478
    75 VMMR3_INT_DECL(int)  NEMR3NotifyPhysRomRegisterEarly(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags);
    76 VMMR3_INT_DECL(int)  NEMR3NotifyPhysRomRegisterLate(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags);
     79/**
     80 * Called very early during ROM registration, basically so an existing RAM range
     81 * can be adjusted if desired.
     82 *
     83 * It will be succeeded by a number of NEMHCNotifyPhysPageProtChanged()
     84 * calls and finally a call to NEMR3NotifyPhysRomRegisterLate().
     85 *
     86 * @returns VBox status code
     87 * @param   pVM             The cross context VM structure.
     88 * @param   GCPhys          The ROM address (page aligned).
     89 * @param   cb              The size (page aligned).
     90 * @param   pvPages         Pointer to the ROM (RAM) pages in simplified mode
     91 *                          when NEM_NOTIFY_PHYS_ROM_F_REPLACE is set, otherwise
     92 *                          NULL.
     93 * @param   fFlags          NEM_NOTIFY_PHYS_ROM_F_XXX.
     94 * @param   pu2State        New page state or UINT8_MAX to leave as-is.
     95 */
     96VMMR3_INT_DECL(int)  NEMR3NotifyPhysRomRegisterEarly(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, void *pvPages,
     97                                                     uint32_t fFlags, uint8_t *pu2State);
     98
     99/**
     100 * Called after the ROM range has been fully completed.
     101 *
     102 * This will be preceeded by a NEMR3NotifyPhysRomRegisterEarly() call as well a
     103 * number of NEMHCNotifyPhysPageProtChanged calls.
     104 *
     105 * @returns VBox status code
     106 * @param   pVM             The cross context VM structure.
     107 * @param   GCPhys          The ROM address (page aligned).
     108 * @param   cb              The size (page aligned).
     109 * @param   pvPages         Pointer to the ROM pages.
     110 * @param   fFlags          NEM_NOTIFY_PHYS_ROM_F_XXX.
     111 * @param   pu2State        Where to return the new NEM page state, UINT8_MAX
     112 *                          for unchanged.
     113 */
     114VMMR3_INT_DECL(int)  NEMR3NotifyPhysRomRegisterLate(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, void *pvPages,
     115                                                    uint32_t fFlags, uint8_t *pu2State);
     116
    77117/** @name Flags for NEMR3NotifyPhysRomRegisterEarly and NEMR3NotifyPhysRomRegisterLate.
    78118 * @{ */
     
    117157VMM_INT_DECL(void) NEMHCNotifyHandlerPhysicalRegister(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhys, RTGCPHYS cb);
    118158VMM_INT_DECL(void) NEMHCNotifyHandlerPhysicalDeregister(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhys, RTGCPHYS cb,
    119                                                         int fRestoreAsRAM, bool fRestoreAsRAM2);
     159                                                        RTR3PTR pvMemR3, uint8_t *pu2State);
    120160VMM_INT_DECL(void) NEMHCNotifyHandlerPhysicalModify(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhysOld,
    121161                                                    RTGCPHYS GCPhysNew, RTGCPHYS cb, bool fRestoreAsRAM);
     
    123163VMM_INT_DECL(int)  NEMHCNotifyPhysPageAllocated(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint32_t fPageProt,
    124164                                                PGMPAGETYPE enmType, uint8_t *pu2State);
    125 VMM_INT_DECL(void) NEMHCNotifyPhysPageProtChanged(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint32_t fPageProt,
     165VMM_INT_DECL(void) NEMHCNotifyPhysPageProtChanged(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, RTR3PTR pvR3, uint32_t fPageProt,
    126166                                                  PGMPAGETYPE enmType, uint8_t *pu2State);
    127167VMM_INT_DECL(void) NEMHCNotifyPhysPageChanged(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhysPrev, RTHCPHYS HCPhysNew,
    128                                               uint32_t fPageProt, PGMPAGETYPE enmType, uint8_t *pu2State);
     168                                              RTR3PTR pvNewR3, uint32_t fPageProt, PGMPAGETYPE enmType, uint8_t *pu2State);
    129169/** @name NEM_PAGE_PROT_XXX - Page protection
    130170 * @{ */
  • trunk/include/VBox/vmm/pgm.h

    r91580 r91848  
    692692 * @{
    693693 */
     694VMMR3_INT_DECL(void)    PGMR3EnableNemMode(PVM pVM);
    694695VMMR3DECL(int)      PGMR3Init(PVM pVM);
    695696VMMR3DECL(int)      PGMR3InitDynMap(PVM pVM);
     
    730731 * @{ */
    731732/** Inidicates that ROM shadowing should be enabled. */
    732 #define PGMPHYS_ROM_FLAGS_SHADOWED                  RT_BIT_32(0)
     733#define PGMPHYS_ROM_FLAGS_SHADOWED                  UINT8_C(0x01)
    733734/** Indicates that what pvBinary points to won't go away
    734735 * and can be used for strictness checks. */
    735 #define PGMPHYS_ROM_FLAGS_PERMANENT_BINARY          RT_BIT_32(1)
     736#define PGMPHYS_ROM_FLAGS_PERMANENT_BINARY          UINT8_C(0x02)
    736737/** Indicates that the ROM is allowed to be missing from saved state.
    737738 * @note This is a hack for EFI, see @bugref{6940}   */
    738 #define PGMPHYS_ROM_FLAGS_MAYBE_MISSING_FROM_STATE  RT_BIT_32(2)
     739#define PGMPHYS_ROM_FLAGS_MAYBE_MISSING_FROM_STATE  UINT8_C(0x04)
    739740/** Valid flags.   */
    740 #define PGMPHYS_ROM_FLAGS_VALID_MASK                UINT32_C(0x00000007)
     741#define PGMPHYS_ROM_FLAGS_VALID_MASK                UINT8_C(0x07)
    741742/** @} */
    742743
    743744VMMR3DECL(int)      PGMR3PhysRomRegister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPHYS cb,
    744                                          const void *pvBinary, uint32_t cbBinary, uint32_t fFlags, const char *pszDesc);
     745                                         const void *pvBinary, uint32_t cbBinary, uint8_t fFlags, const char *pszDesc);
    745746VMMR3DECL(int)      PGMR3PhysRomProtect(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, PGMROMPROT enmProt);
    746747VMMR3DECL(int)      PGMR3PhysRegister(PVM pVM, void *pvRam, RTGCPHYS GCPhys, size_t cb, unsigned fFlags, const SUPPAGE *paPages, const char *pszDesc);
  • trunk/src/VBox/VMM/Config.kmk

    r91786 r91848  
    6969ifdef VBOX_WITH_NATIVE_NEM
    7070 if1of ($(KBUILD_TARGET).$(KBUILD_TARGET_ARCH), win.amd64)
    71   VMM_COMMON_DEFS += VBOX_WITH_NATIVE_NEM VBOX_WITH_NEM_R0
     71  VMM_COMMON_DEFS += VBOX_WITH_NATIVE_NEM VBOX_WITH_NEM_R0 #VBOX_WITH_PGM_NEM_MODE
    7272 endif
    7373endif
  • trunk/src/VBox/VMM/VMMAll/NEMAll.cpp

    r82968 r91848  
    6363
    6464
    65 VMM_INT_DECL(void) NEMHCNotifyHandlerPhysicalDeregister(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhys, RTGCPHYS cb,
    66                                                         int fRestoreAsRAM, bool fRestoreAsRAM2)
    67 {
    68 #ifdef VBOX_WITH_NATIVE_NEM
    69     if (VM_IS_NEM_ENABLED(pVM))
    70         nemHCNativeNotifyHandlerPhysicalDeregister(pVM, enmKind, GCPhys, cb, fRestoreAsRAM, fRestoreAsRAM2);
    71 #else
    72     RT_NOREF(pVM, enmKind, GCPhys, cb, fRestoreAsRAM, fRestoreAsRAM2);
    73 #endif
    74 }
    75 
    76 
    7765VMM_INT_DECL(void) NEMHCNotifyHandlerPhysicalModify(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhysOld,
    7866                                                    RTGCPHYS GCPhysNew, RTGCPHYS cb, bool fRestoreAsRAM)
     
    9684    RT_NOREF(pVM, GCPhys, HCPhys, fPageProt, enmType, pu2State);
    9785    return VINF_SUCCESS;
    98 #endif
    99 }
    100 
    101 
    102 VMM_INT_DECL(void) NEMHCNotifyPhysPageProtChanged(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint32_t fPageProt,
    103                                                   PGMPAGETYPE enmType, uint8_t *pu2State)
    104 {
    105     Assert(VM_IS_NEM_ENABLED(pVM));
    106 #ifdef VBOX_WITH_NATIVE_NEM
    107     nemHCNativeNotifyPhysPageProtChanged(pVM, GCPhys, HCPhys, fPageProt, enmType, pu2State);
    108 #else
    109     RT_NOREF(pVM, GCPhys, HCPhys, fPageProt, enmType, pu2State);
    110 #endif
    111 }
    112 
    113 
    114 VMM_INT_DECL(void) NEMHCNotifyPhysPageChanged(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhysPrev, RTHCPHYS HCPhysNew,
    115                                               uint32_t fPageProt, PGMPAGETYPE enmType, uint8_t *pu2State)
    116 {
    117     Assert(VM_IS_NEM_ENABLED(pVM));
    118 #ifdef VBOX_WITH_NATIVE_NEM
    119     nemHCNativeNotifyPhysPageChanged(pVM, GCPhys, HCPhysPrev, HCPhysNew, fPageProt, enmType, pu2State);
    120 #else
    121     RT_NOREF(pVM, GCPhys, HCPhysPrev, HCPhysNew, fPageProt, enmType, pu2State);
    12286#endif
    12387}
  • trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h

    r91702 r91848  
    45924592
    45934593
    4594 void nemHCNativeNotifyHandlerPhysicalDeregister(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhys, RTGCPHYS cb,
    4595                                                 int fRestoreAsRAM, bool fRestoreAsRAM2)
    4596 {
    4597     Log5(("nemHCNativeNotifyHandlerPhysicalDeregister: %RGp LB %RGp enmKind=%d fRestoreAsRAM=%d fRestoreAsRAM2=%d\n",
    4598           GCPhys, cb, enmKind, fRestoreAsRAM, fRestoreAsRAM2));
    4599     NOREF(pVM); NOREF(enmKind); NOREF(GCPhys); NOREF(cb); NOREF(fRestoreAsRAM); NOREF(fRestoreAsRAM2);
     4594VMM_INT_DECL(void) NEMHCNotifyHandlerPhysicalDeregister(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhys, RTGCPHYS cb,
     4595                                                        RTR3PTR pvMemR3, uint8_t *pu2State)
     4596{
     4597    Log5(("NEMHCNotifyHandlerPhysicalDeregister: %RGp LB %RGp enmKind=%d pvMemR3=%p pu2State=%p (%d)\n",
     4598          GCPhys, cb, enmKind, pvMemR3, pu2State, *pu2State));
     4599
     4600    *pu2State = UINT8_MAX;
     4601#if !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) && defined(VBOX_WITH_PGM_NEM_MODE) && defined(IN_RING3)
     4602    if (pvMemR3)
     4603    {
     4604        HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, pvMemR3, GCPhys, cb,
     4605                                     WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagExecute | WHvMapGpaRangeFlagWrite);
     4606        if (SUCCEEDED(hrc))
     4607            *pu2State = NEM_WIN_PAGE_STATE_WRITABLE;
     4608        else
     4609            AssertLogRelMsgFailed(("NEMHCNotifyHandlerPhysicalDeregister: WHvMapGpaRange(,%p,%RGp,%RGp,) -> %Rhrc\n",
     4610                                   pvMemR3, GCPhys, cb, hrc));
     4611    }
     4612    RT_NOREF(enmKind);
     4613#else
     4614    RT_NOREF(pVM, enmKind, GCPhys, cb, pvMemR3);
     4615#endif
    46004616}
    46014617
     
    49574973
    49584974
    4959 void nemHCNativeNotifyPhysPageProtChanged(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint32_t fPageProt,
    4960                                           PGMPAGETYPE enmType, uint8_t *pu2State)
    4961 {
    4962     Log5(("nemHCNativeNotifyPhysPageProtChanged: %RGp HCPhys=%RHp fPageProt=%#x enmType=%d *pu2State=%d\n",
     4975VMM_INT_DECL(void) NEMHCNotifyPhysPageProtChanged(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, RTR3PTR pvR3, uint32_t fPageProt,
     4976                                                  PGMPAGETYPE enmType, uint8_t *pu2State)
     4977{
     4978    Log5(("NEMHCNotifyPhysPageProtChanged: %RGp HCPhys=%RHp fPageProt=%#x enmType=%d *pu2State=%d\n",
    49634979          GCPhys, HCPhys, fPageProt, enmType, *pu2State));
    4964     RT_NOREF_PV(HCPhys); RT_NOREF_PV(enmType);
     4980    Assert(VM_IS_NEM_ENABLED(pVM));
     4981    RT_NOREF(HCPhys, enmType, pvR3);
    49654982
    49664983#ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
     
    49885005
    49895006
    4990 void nemHCNativeNotifyPhysPageChanged(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhysPrev, RTHCPHYS HCPhysNew,
    4991                                      uint32_t fPageProt, PGMPAGETYPE enmType, uint8_t *pu2State)
    4992 {
    4993     Log5(("nemHCNativeNotifyPhysPageChanged: %RGp HCPhys=%RHp->%RHp fPageProt=%#x enmType=%d *pu2State=%d\n",
    4994           GCPhys, HCPhysPrev, HCPhysNew, fPageProt, enmType, *pu2State));
    4995     RT_NOREF_PV(HCPhysPrev); RT_NOREF_PV(HCPhysNew); RT_NOREF_PV(enmType);
     5007VMM_INT_DECL(void) NEMHCNotifyPhysPageChanged(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhysPrev, RTHCPHYS HCPhysNew,
     5008                                              RTR3PTR pvNewR3, uint32_t fPageProt, PGMPAGETYPE enmType, uint8_t *pu2State)
     5009{
     5010    Log5(("nemHCNativeNotifyPhysPageChanged: %RGp HCPhys=%RHp->%RHp pvNewR3=%p fPageProt=%#x enmType=%d *pu2State=%d\n",
     5011          GCPhys, HCPhysPrev, HCPhysNew, pvNewR3, fPageProt, enmType, *pu2State));
     5012    Assert(VM_IS_NEM_ENABLED(pVM));
     5013    RT_NOREF(HCPhysPrev, HCPhysNew, pvNewR3, enmType);
    49965014
    49975015#ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
  • trunk/src/VBox/VMM/VMMAll/PGMAllHandler.cpp

    r91733 r91848  
    5050*********************************************************************************************************************************/
    5151static int  pgmHandlerPhysicalSetRamFlagsAndFlushShadowPTs(PVMCC pVM, PPGMPHYSHANDLER pCur, PPGMRAMRANGE pRam);
    52 static void pgmHandlerPhysicalDeregisterNotifyREMAndNEM(PVMCC pVM, PPGMPHYSHANDLER pCur, int fRestoreRAM);
     52static void pgmHandlerPhysicalDeregisterNotifyNEM(PVMCC pVM, PPGMPHYSHANDLER pCur);
    5353static void pgmHandlerPhysicalResetRamFlags(PVMCC pVM, PPGMPHYSHANDLER pCur);
    5454
     
    394394                rc = rc2;
    395395
     396#ifdef VBOX_WITH_NATIVE_NEM
    396397            /* Tell NEM about the protection update. */
    397398            if (VM_IS_NEM_ENABLED(pVM))
     
    400401                PGMPAGETYPE enmType = (PGMPAGETYPE)PGM_PAGE_GET_TYPE(pPage);
    401402                NEMHCNotifyPhysPageProtChanged(pVM, GCPhysPage, PGM_PAGE_GET_HCPHYS(pPage),
     403                                               PGM_RAMRANGE_CALC_PAGE_R3PTR(pRam, GCPhysPage),
    402404                                               pgmPhysPageCalcNemProtection(pPage, enmType), enmType, &u2State);
    403405                PGM_PAGE_SET_NEM_STATE(pPage, u2State);
    404406            }
     407#endif
    405408        }
    406409
     
    429432 * @param   pVM             The cross context VM structure.
    430433 * @param   pPhysHandler    The handler to deregister (but not free).
    431  * @param   fRestoreAsRAM   How this will likely be restored, if we know (true,
    432  *                          false, or if we don't know -1).
    433  */
    434 int pgmHandlerPhysicalExDeregister(PVMCC pVM, PPGMPHYSHANDLER pPhysHandler, int fRestoreAsRAM)
     434 */
     435int pgmHandlerPhysicalExDeregister(PVMCC pVM, PPGMPHYSHANDLER pPhysHandler)
    435436{
    436437    LogFlow(("pgmHandlerPhysicalExDeregister: Removing Range %RGp-%RGp %s fRestoreAsRAM=%d\n",
    437              pPhysHandler->Core.Key, pPhysHandler->Core.KeyLast, R3STRING(pPhysHandler->pszDesc), fRestoreAsRAM));
     438             pPhysHandler->Core.Key, pPhysHandler->Core.KeyLast, R3STRING(pPhysHandler->pszDesc)));
    438439    AssertReturn(pPhysHandler->Core.Key != NIL_RTGCPHYS, VERR_PGM_HANDLER_NOT_FOUND);
    439440
     
    451452         */
    452453        pgmHandlerPhysicalResetRamFlags(pVM, pPhysHandler);
    453         pgmHandlerPhysicalDeregisterNotifyREMAndNEM(pVM, pPhysHandler, fRestoreAsRAM);
     454        if (VM_IS_NEM_ENABLED(pVM))
     455            pgmHandlerPhysicalDeregisterNotifyNEM(pVM, pPhysHandler);
    454456        pVM->pgm.s.pLastPhysHandlerR0 = 0;
    455457        pVM->pgm.s.pLastPhysHandlerR3 = 0;
     
    529531         */
    530532        pgmHandlerPhysicalResetRamFlags(pVM, pRemoved);
    531         pgmHandlerPhysicalDeregisterNotifyREMAndNEM(pVM, pRemoved, -1);
     533        if (VM_IS_NEM_ENABLED(pVM))
     534            pgmHandlerPhysicalDeregisterNotifyNEM(pVM, pRemoved);
    532535        pVM->pgm.s.pLastPhysHandlerR0 = 0;
    533536        pVM->pgm.s.pLastPhysHandlerR3 = 0;
     
    550553 * Shared code with modify.
    551554 */
    552 static void pgmHandlerPhysicalDeregisterNotifyREMAndNEM(PVMCC pVM, PPGMPHYSHANDLER pCur, int fRestoreAsRAM)
     555static void pgmHandlerPhysicalDeregisterNotifyNEM(PVMCC pVM, PPGMPHYSHANDLER pCur)
    553556{
    554557    PPGMPHYSHANDLERTYPEINT  pCurType    = PGMPHYSHANDLER_GET_TYPE(pVM, pCur);
     
    604607
    605608    /*
    606      * Tell REM and NEM.
    607      */
    608     const bool fRestoreAsRAM2 = pCurType->pfnHandlerR3
    609                              && pCurType->enmKind != PGMPHYSHANDLERKIND_MMIO; /** @todo this isn't entirely correct. */
    610     /** @todo do we need this notification? */
    611     NEMHCNotifyHandlerPhysicalDeregister(pVM, pCurType->enmKind, GCPhysStart, GCPhysLast - GCPhysStart + 1,
    612                                          fRestoreAsRAM, fRestoreAsRAM2);
     609     * Tell NEM.
     610     */
     611    PPGMRAMRANGE const pRam    = pgmPhysGetRange(pVM, GCPhysStart);
     612    RTGCPHYS const     cb      = GCPhysLast - GCPhysStart + 1;
     613    uint8_t            u2State = UINT8_MAX;
     614    NEMHCNotifyHandlerPhysicalDeregister(pVM, pCurType->enmKind, GCPhysStart, cb,
     615                                         pRam ? PGM_RAMRANGE_CALC_PAGE_R3PTR(pRam, GCPhysStart) : NULL, &u2State);
     616    if (u2State != UINT8_MAX && pRam)
     617        pgmPhysSetNemStateForPages(&pRam->aPages[(GCPhysStart - pRam->GCPhys) >> PAGE_SHIFT], cb >> PAGE_SHIFT, u2State);
    613618}
    614619
     
    662667                AssertRC(rc);
    663668
     669#ifdef VBOX_WITH_NATIVE_NEM
    664670            /* Tell NEM about the protection update. */
    665671            if (VM_IS_NEM_ENABLED(pVM))
     
    668674                PGMPAGETYPE enmType = (PGMPAGETYPE)PGM_PAGE_GET_TYPE(pPage);
    669675                NEMHCNotifyPhysPageProtChanged(pVM, GCPhys, PGM_PAGE_GET_HCPHYS(pPage),
     676                                               PGM_RAMRANGE_CALC_PAGE_R3PTR(*ppRamHint, GCPhys),
    670677                                               pgmPhysPageCalcNemProtection(pPage, enmType), enmType, &u2State);
    671678                PGM_PAGE_SET_NEM_STATE(pPage, u2State);
    672679            }
     680#endif
    673681        }
    674682        else
     
    684692 * @param   pPage           The page.
    685693 * @param   GCPhysPage      The page address in case it comes in handy.
     694 * @param   pRam            The RAM range the page is associated with (for NEM
     695 *                          notifications).
    686696 * @param   fDoAccounting   Whether to perform accounting.  (Only set during
    687697 *                          reset where pgmR3PhysRamReset doesn't have the
    688698 *                          handler structure handy.)
    689699 */
    690 void pgmHandlerPhysicalResetAliasedPage(PVMCC pVM, PPGMPAGE pPage, RTGCPHYS GCPhysPage, bool fDoAccounting)
     700void pgmHandlerPhysicalResetAliasedPage(PVMCC pVM, PPGMPAGE pPage, RTGCPHYS GCPhysPage, PPGMRAMRANGE pRam, bool fDoAccounting)
    691701{
    692702    Assert(   PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_MMIO2_ALIAS_MMIO
     
    730740    }
    731741
     742#ifdef VBOX_WITH_NATIVE_NEM
    732743    /*
    733744     * Tell NEM about the protection change.
     
    737748        uint8_t u2State = PGM_PAGE_GET_NEM_STATE(pPage);
    738749        NEMHCNotifyPhysPageChanged(pVM, GCPhysPage, HCPhysPrev, pVM->pgm.s.HCPhysZeroPg,
     750                                   PGM_RAMRANGE_CALC_PAGE_R3PTR(pRam, GCPhysPage),
    739751                                   NEM_PAGE_PROT_NONE, PGMPAGETYPE_MMIO, &u2State);
    740752        PGM_PAGE_SET_NEM_STATE(pPage, u2State);
    741753    }
     754#endif
    742755}
    743756
     
    776789            {
    777790                Assert(pCur->cAliasedPages > 0);
    778                 pgmHandlerPhysicalResetAliasedPage(pVM, pPage, GCPhys, false /*fDoAccounting*/);
     791                pgmHandlerPhysicalResetAliasedPage(pVM, pPage, GCPhys, pRamHint, false /*fDoAccounting*/);
    779792                pCur->cAliasedPages--;
    780793                fNemNotifiedAlready = true;
     
    786799            PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, PGM_PAGE_HNDL_PHYS_STATE_NONE);
    787800
     801#ifdef VBOX_WITH_NATIVE_NEM
    788802            /* Tell NEM about the protection change. */
    789803            if (VM_IS_NEM_ENABLED(pVM) && !fNemNotifiedAlready)
     
    792806                PGMPAGETYPE enmType = (PGMPAGETYPE)PGM_PAGE_GET_TYPE(pPage);
    793807                NEMHCNotifyPhysPageProtChanged(pVM, GCPhys, PGM_PAGE_GET_HCPHYS(pPage),
     808                                               PGM_RAMRANGE_CALC_PAGE_R3PTR(pRamHint, GCPhys),
    794809                                               pgmPhysPageCalcNemProtection(pPage, enmType), enmType, &u2State);
    795810                PGM_PAGE_SET_NEM_STATE(pPage, u2State);
    796811            }
     812#endif
     813            RT_NOREF(fNemNotifiedAlready);
    797814        }
    798815        else
     
    818835
    819836
     837#if 0 /* unused */
    820838/**
    821839 * Modify a physical page access handler.
     
    907925         * We've only gotta notify REM and free the memory.
    908926         */
    909         pgmHandlerPhysicalDeregisterNotifyREMAndNEM(pVM, pCur, -1);
     927        if (VM_IS_NEM_ENABLED(pVM))
     928            pgmHandlerPhysicalDeregisterNotifyNEM(pVM, pCur);
    910929        pVM->pgm.s.pLastPhysHandlerR0 = 0;
    911930        pVM->pgm.s.pLastPhysHandlerR3 = 0;
     
    922941    return rc;
    923942}
     943#endif /* unused */
    924944
    925945
     
    959979}
    960980
     981#if 0 /* unused */
    961982
    962983/**
     
    11011122}
    11021123
     1124#endif /* unused */
    11031125
    11041126/**
     
    11621184                            {
    11631185                                Assert(pCur->cAliasedPages > 0);
    1164                                 pgmHandlerPhysicalResetAliasedPage(pVM, pPage, GCPhysPage, false /*fDoAccounting*/);
     1186                                pgmHandlerPhysicalResetAliasedPage(pVM, pPage, GCPhysPage, pRam, false /*fDoAccounting*/);
    11651187                                --pCur->cAliasedPages;
    11661188#ifndef VBOX_STRICT
     
    12551277             * Change the page status.
    12561278             */
    1257             PPGMPAGE pPage;
    1258             int rc = pgmPhysGetPageEx(pVM, GCPhysPage, &pPage);
     1279            PPGMPAGE     pPage;
     1280            PPGMRAMRANGE pRam;
     1281            int rc = pgmPhysGetPageAndRangeEx(pVM, GCPhysPage, &pPage, &pRam);
    12591282            AssertReturnStmt(RT_SUCCESS_NP(rc), PGM_UNLOCK(pVM), rc);
    12601283            if (PGM_PAGE_GET_HNDL_PHYS_STATE(pPage) != PGM_PAGE_HNDL_PHYS_STATE_DISABLED)
     
    12631286                pCur->cTmpOffPages++;
    12641287
     1288#ifdef VBOX_WITH_NATIVE_NEM
    12651289                /* Tell NEM about the protection change (VGA is using this to track dirty pages). */
    12661290                if (VM_IS_NEM_ENABLED(pVM))
     
    12691293                    PGMPAGETYPE enmType = (PGMPAGETYPE)PGM_PAGE_GET_TYPE(pPage);
    12701294                    NEMHCNotifyPhysPageProtChanged(pVM, GCPhysPage, PGM_PAGE_GET_HCPHYS(pPage),
     1295                                                   PGM_RAMRANGE_CALC_PAGE_R3PTR(pRam, GCPhysPage),
    12711296                                                   pgmPhysPageCalcNemProtection(pPage, enmType), enmType, &u2State);
    12721297                    PGM_PAGE_SET_NEM_STATE(pPage, u2State);
    12731298                }
     1299#endif
    12741300            }
    12751301            PGM_UNLOCK(pVM);
     
    13821408                                               PPDMDEVINS pDevIns, PGMMMIO2HANDLE hMmio2, RTGCPHYS offMmio2PageRemap)
    13831409{
     1410#ifdef VBOX_WITH_PGM_NEM_MODE
     1411    AssertReturn(!VM_IS_NEM_ENABLED(pVM) || !pVM->pgm.s.fNemMode, VERR_PGM_NOT_SUPPORTED_FOR_NEM_MODE);
     1412#endif
    13841413    PGM_LOCK_VOID(pVM);
    13851414
     
    14151444             * Validate the page.
    14161445             */
    1417             PPGMPAGE pPage;
    1418             int rc = pgmPhysGetPageEx(pVM, GCPhysPage, &pPage);
     1446            PPGMPAGE     pPage;
     1447            PPGMRAMRANGE pRam;
     1448            int rc = pgmPhysGetPageAndRangeEx(pVM, GCPhysPage, &pPage, &pRam);
    14191449            AssertReturnStmt(RT_SUCCESS_NP(rc), PGM_UNLOCK(pVM), rc);
    14201450            if (PGM_PAGE_GET_TYPE(pPage) != PGMPAGETYPE_MMIO)
     
    14351465                Log(("PGMHandlerPhysicalPageAliasMmio2: GCPhysPage=%RGp (%R[pgmpage]; %RHp -> %RHp\n",
    14361466                     GCPhysPage, pPage, PGM_PAGE_GET_HCPHYS(pPage), PGM_PAGE_GET_HCPHYS(pPageRemap)));
    1437                 pgmHandlerPhysicalResetAliasedPage(pVM, pPage, GCPhysPage, false /*fDoAccounting*/);
     1467                pgmHandlerPhysicalResetAliasedPage(pVM, pPage, GCPhysPage, pRam, false /*fDoAccounting*/);
    14381468                pCur->cAliasedPages--;
    14391469            }
     
    14571487            pgmPhysInvalidatePageMapTLBEntry(pVM, GCPhysPage);
    14581488
     1489#ifdef VBOX_WITH_NATIVE_NEM
    14591490            /* Tell NEM about the backing and protection change. */
    14601491            if (VM_IS_NEM_ENABLED(pVM))
     
    14621493                uint8_t u2State = PGM_PAGE_GET_NEM_STATE(pPage);
    14631494                NEMHCNotifyPhysPageChanged(pVM, GCPhysPage, pVM->pgm.s.HCPhysZeroPg, PGM_PAGE_GET_HCPHYS(pPage),
     1495                                           PGM_RAMRANGE_CALC_PAGE_R3PTR(pRam, GCPhysPage),
    14641496                                           pgmPhysPageCalcNemProtection(pPage, PGMPAGETYPE_MMIO2_ALIAS_MMIO),
    14651497                                           PGMPAGETYPE_MMIO2_ALIAS_MMIO, &u2State);
    14661498                PGM_PAGE_SET_NEM_STATE(pPage, u2State);
    14671499            }
     1500#endif
    14681501            LogFlow(("PGMHandlerPhysicalPageAliasMmio2: => %R[pgmpage]\n", pPage));
    14691502            PGM_UNLOCK(pVM);
     
    15171550{
    15181551///    Assert(!IOMIsLockOwner(pVM)); /* We mustn't own any other locks when calling this */
     1552#ifdef VBOX_WITH_PGM_NEM_MODE
     1553    AssertReturn(!VM_IS_NEM_ENABLED(pVM) || !pVM->pgm.s.fNemMode, VERR_PGM_NOT_SUPPORTED_FOR_NEM_MODE);
     1554#endif
    15191555    PGM_LOCK_VOID(pVM);
    15201556
     
    15671603            pgmPhysInvalidatePageMapTLBEntry(pVM, GCPhysPage);
    15681604
     1605#ifdef VBOX_WITH_NATIVE_NEM
    15691606            /* Tell NEM about the backing and protection change. */
    15701607            if (VM_IS_NEM_ENABLED(pVM))
    15711608            {
    1572                 uint8_t u2State = PGM_PAGE_GET_NEM_STATE(pPage);
     1609                PPGMRAMRANGE pRam    = pgmPhysGetRange(pVM, GCPhysPage);
     1610                uint8_t      u2State = PGM_PAGE_GET_NEM_STATE(pPage);
    15731611                NEMHCNotifyPhysPageChanged(pVM, GCPhysPage, pVM->pgm.s.HCPhysZeroPg, PGM_PAGE_GET_HCPHYS(pPage),
     1612                                           PGM_RAMRANGE_CALC_PAGE_R3PTR(pRam, GCPhysPage),
    15741613                                           pgmPhysPageCalcNemProtection(pPage, PGMPAGETYPE_SPECIAL_ALIAS_MMIO),
    15751614                                           PGMPAGETYPE_SPECIAL_ALIAS_MMIO, &u2State);
    15761615                PGM_PAGE_SET_NEM_STATE(pPage, u2State);
    15771616            }
     1617#endif
    15781618            LogFlow(("PGMHandlerPhysicalPageAliasHC: => %R[pgmpage]\n", pPage));
    15791619            PGM_UNLOCK(pVM);
  • trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp

    r91587 r91848  
    282282                {
    283283                    pShadowPage = pgmPhysGetPage(pVM, GCPhys);
    284                     AssertLogRelReturn(pShadowPage, VERR_PGM_PHYS_PAGE_GET_IPE);
     284                    AssertLogRelMsgReturnStmt(pShadowPage, ("%RGp\n", GCPhys), PGM_UNLOCK(pVM), VERR_PGM_PHYS_PAGE_GET_IPE);
    285285                }
    286286
    287287                void *pvDstPage;
    288                 int rc = pgmPhysPageMakeWritableAndMap(pVM, pShadowPage, GCPhys & X86_PTE_PG_MASK, &pvDstPage);
     288                int rc;
     289#if defined(VBOX_WITH_PGM_NEM_MODE) && defined(IN_RING3)
     290                if (PGM_IS_IN_NEM_MODE(pVM) && PGMROMPROT_IS_ROM(pRomPage->enmProt))
     291                {
     292                    pvDstPage = &pRom->pbR3Alternate[GCPhys - pRom->GCPhys];
     293                    rc = VINF_SUCCESS;
     294                }
     295                else
     296#endif
     297                {
     298                    rc = pgmPhysPageMakeWritableAndMap(pVM, pShadowPage, GCPhys & X86_PTE_PG_MASK, &pvDstPage);
     299                    if (RT_SUCCESS(rc))
     300                        pvDstPage = (uint8_t *)pvDstPage + (GCPhys & PAGE_OFFSET_MASK);
     301                }
    289302                if (RT_SUCCESS(rc))
    290303                {
     
    10591072    pVM->pgm.s.cWrittenToPages++;
    10601073
     1074#ifdef VBOX_WITH_NATIVE_NEM
    10611075    /*
    10621076     * Notify NEM about the protection change so we won't spin forever.
     
    10671081    if (VM_IS_NEM_ENABLED(pVM) && GCPhys != NIL_RTGCPHYS)
    10681082    {
    1069         uint8_t     u2State = PGM_PAGE_GET_NEM_STATE(pPage);
    1070         PGMPAGETYPE enmType = (PGMPAGETYPE)PGM_PAGE_GET_TYPE(pPage);
     1083        uint8_t      u2State = PGM_PAGE_GET_NEM_STATE(pPage);
     1084        PGMPAGETYPE  enmType = (PGMPAGETYPE)PGM_PAGE_GET_TYPE(pPage);
     1085        PPGMRAMRANGE pRam    = pgmPhysGetRange(pVM, GCPhys);
    10711086        NEMHCNotifyPhysPageProtChanged(pVM, GCPhys, PGM_PAGE_GET_HCPHYS(pPage),
     1087                                       pRam ? PGM_RAMRANGE_CALC_PAGE_R3PTR(pRam, GCPhys) : NULL,
    10721088                                       pgmPhysPageCalcNemProtection(pPage, enmType), enmType, &u2State);
    10731089        PGM_PAGE_SET_NEM_STATE(pPage, u2State);
    10741090    }
     1091#endif
    10751092}
    10761093
     
    12441261# endif
    12451262    }
     1263
     1264# ifdef VBOX_WITH_PGM_NEM_MODE
     1265    if (pVM->pgm.s.fNemMode)
     1266    {
     1267#  ifdef IN_RING3
     1268        /*
     1269         * Find the corresponding RAM range and use that to locate the mapping address.
     1270         */
     1271        /** @todo Use the page ID for some kind of indexing as we do with MMIO2 above. */
     1272        PPGMRAMRANGE const pRam = pgmPhysGetRange(pVM, GCPhys);
     1273        AssertLogRelMsgReturn(pRam, ("%RTGp\n", GCPhys), VERR_INTERNAL_ERROR_3);
     1274        size_t const idxPage = (GCPhys - pRam->GCPhys) >> PAGE_SHIFT;
     1275        Assert(pPage == &pRam->aPages[idxPage]);
     1276        *ppMap = NULL;
     1277        *ppv   = (uint8_t *)pRam->pvR3 + (idxPage << PAGE_SHIFT);
     1278        return VINF_SUCCESS;
     1279#  else
     1280        AssertFailedReturn(VERR_INTERNAL_ERROR_2);
     1281#  endif
     1282    }
     1283# endif
    12461284
    12471285    const uint32_t idChunk = PGM_PAGE_GET_CHUNKID(pPage);
     
    43514389}
    43524390
     4391#ifdef VBOX_WITH_NATIVE_NEM
    43534392
    43544393/**
     
    44944533}
    44954534
     4535
     4536/**
     4537 * Helper for setting the NEM state for a range of pages.
     4538 *
     4539 * @param   paPages     Array of pages to modify.
     4540 * @param   cPages      How many pages to modify.
     4541 * @param   u2State     The new state value.
     4542 */
     4543void pgmPhysSetNemStateForPages(PPGMPAGE paPages, RTGCPHYS cPages, uint8_t u2State)
     4544{
     4545    PPGMPAGE pPage = paPages;
     4546    while (cPages-- > 0)
     4547    {
     4548        PGM_PAGE_SET_NEM_STATE(pPage, u2State);
     4549        pPage++;
     4550    }
     4551}
     4552
     4553#endif /* VBOX_WITH_NATIVE_NEM */
     4554
     4555
  • trunk/src/VBox/VMM/VMMR3/NEMR3.cpp

    r86117 r91848  
    441441
    442442
    443 
    444 
    445 VMMR3_INT_DECL(int)  NEMR3NotifyPhysRamRegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb)
    446 {
    447     int rc = VINF_SUCCESS;
    448 #ifdef VBOX_WITH_NATIVE_NEM
    449     if (pVM->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API)
    450         rc = nemR3NativeNotifyPhysRamRegister(pVM, GCPhys, cb);
    451 #else
    452     NOREF(pVM); NOREF(GCPhys); NOREF(cb);
    453 #endif
    454     return rc;
    455 }
    456 
    457 
    458 VMMR3_INT_DECL(int)  NEMR3NotifyPhysMmioExMap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags, void *pvMmio2)
    459 {
    460     int rc = VINF_SUCCESS;
    461 #ifdef VBOX_WITH_NATIVE_NEM
    462     if (pVM->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API)
    463         rc = nemR3NativeNotifyPhysMmioExMap(pVM, GCPhys, cb, fFlags, pvMmio2);
    464 #else
    465     NOREF(pVM); NOREF(GCPhys); NOREF(cb); NOREF(fFlags); NOREF(pvMmio2);
    466 #endif
    467     return rc;
    468 }
    469 
    470 
    471 VMMR3_INT_DECL(int)  NEMR3NotifyPhysMmioExUnmap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags)
    472 {
    473     int rc = VINF_SUCCESS;
    474 #ifdef VBOX_WITH_NATIVE_NEM
    475     if (pVM->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API)
    476         rc = nemR3NativeNotifyPhysMmioExUnmap(pVM, GCPhys, cb, fFlags);
    477 #else
    478     NOREF(pVM); NOREF(GCPhys); NOREF(cb); NOREF(fFlags);
    479 #endif
    480     return rc;
    481 }
    482 
    483 
    484 VMMR3_INT_DECL(int)  NEMR3NotifyPhysRomRegisterEarly(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags)
    485 {
    486     int rc = VINF_SUCCESS;
    487 #ifdef VBOX_WITH_NATIVE_NEM
    488     if (pVM->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API)
    489         rc = nemR3NativeNotifyPhysRomRegisterEarly(pVM, GCPhys, cb, fFlags);
    490 #else
    491     NOREF(pVM); NOREF(GCPhys); NOREF(cb); NOREF(fFlags);
    492 #endif
    493     return rc;
    494 }
    495 
    496 
    497 /**
    498  * Called after the ROM range has been fully completed.
    499  *
    500  * This will be preceeded by a NEMR3NotifyPhysRomRegisterEarly() call as well a
    501  * number of NEMHCNotifyPhysPageProtChanged calls.
    502  *
    503  * @returns VBox status code
    504  * @param   pVM             The cross context VM structure.
    505  * @param   GCPhys          The ROM address (page aligned).
    506  * @param   cb              The size (page aligned).
    507  * @param   fFlags          NEM_NOTIFY_PHYS_ROM_F_XXX.
    508  */
    509 VMMR3_INT_DECL(int)  NEMR3NotifyPhysRomRegisterLate(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags)
    510 {
    511     int rc = VINF_SUCCESS;
    512 #ifdef VBOX_WITH_NATIVE_NEM
    513     if (pVM->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API)
    514         rc = nemR3NativeNotifyPhysRomRegisterLate(pVM, GCPhys, cb, fFlags);
    515 #else
    516     NOREF(pVM); NOREF(GCPhys); NOREF(cb); NOREF(fFlags);
    517 #endif
    518     return rc;
    519 }
    520 
    521 
    522443VMMR3_INT_DECL(void) NEMR3NotifySetA20(PVMCPU pVCpu, bool fEnabled)
    523444{
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp

    r91702 r91848  
    13361336                    if (RT_SUCCESS(rc))
    13371337                    {
     1338                        /*
     1339                         * Set ourselves as the execution engine and make config adjustments.
     1340                         */
    13381341                        VM_SET_MAIN_EXECUTION_ENGINE(pVM, VM_EXEC_ENGINE_NATIVE_API);
    13391342                        Log(("NEM: Marked active!\n"));
    13401343                        nemR3WinDisableX2Apic(pVM);
    1341 
    1342                         /* Register release statistics */
     1344#if !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) && defined(VBOX_WITH_PGM_NEM_MODE)
     1345                        PGMR3EnableNemMode(pVM);
     1346#endif
     1347
     1348                        /*
     1349                         * Register release statistics
     1350                         */
    13431351                        STAMR3Register(pVM, (void *)&pVM->nem.s.cMappedPages, STAMTYPE_U32, STAMVISIBILITY_ALWAYS,
    13441352                                       "/NEM/PagesCurrentlyMapped", STAMUNIT_PAGES, "Number guest pages currently mapped by the VM");
     
    14031411                                              STAMUNIT_PAGES, STAM_REFRESH_GRP_NEM, "Pages in use by hypervisor",
    14041412                                              "/NEM/R0Stats/cPagesInUse");
     1413
    14051414                    }
    14061415                }
     
    19421951
    19431952
    1944 int nemR3NativeNotifyPhysRamRegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb)
    1945 {
    1946     Log5(("nemR3NativeNotifyPhysRamRegister: %RGp LB %RGp\n", GCPhys, cb));
    1947     NOREF(pVM); NOREF(GCPhys); NOREF(cb);
     1953VMMR3_INT_DECL(int) NEMR3NotifyPhysRamRegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, void *pvR3)
     1954{
     1955    Log5(("NEMR3NotifyPhysRamRegister: %RGp LB %RGp, pvR3=%p\n", GCPhys, cb, pvR3));
     1956#if !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) && defined(VBOX_WITH_PGM_NEM_MODE)
     1957    if (pvR3)
     1958    {
     1959        HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, pvR3, GCPhys, cb,
     1960                                     WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagWrite | WHvMapGpaRangeFlagExecute);
     1961        if (SUCCEEDED(hrc))
     1962        { /* likely */ }
     1963        else
     1964        {
     1965            LogRel(("NEMR3NotifyPhysRamRegister: GCPhys=%RGp LB %RGp pvR3=%p hrc=%Rhrc (%#x) Last=%#x/%u\n",
     1966                    GCPhys, cb, pvR3, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
     1967            return VERR_NEM_MAP_PAGES_FAILED;
     1968        }
     1969    }
     1970#else
     1971    RT_NOREF(pVM, GCPhys, cb, pvR3);
     1972#endif
    19481973    return VINF_SUCCESS;
    19491974}
    19501975
    19511976
    1952 int nemR3NativeNotifyPhysMmioExMap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags, void *pvMmio2)
    1953 {
    1954     Log5(("nemR3NativeNotifyPhysMmioExMap: %RGp LB %RGp fFlags=%#x pvMmio2=%p\n", GCPhys, cb, fFlags, pvMmio2));
    1955     NOREF(pVM); NOREF(GCPhys); NOREF(cb); NOREF(fFlags); NOREF(pvMmio2);
     1977VMMR3_INT_DECL(int) NEMR3NotifyPhysMmioExMapEarly(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags,
     1978                                                  void *pvRam, void *pvMmio2, uint8_t *pu2State)
     1979{
     1980    Log5(("NEMR3NotifyPhysMmioExMapEarly: %RGp LB %RGp fFlags=%#x pvRam=%p pvMmio2=%p pu2State=%p (%d)\n",
     1981          GCPhys, cb, fFlags, pvRam, pvMmio2, pu2State, *pu2State));
     1982
     1983#if !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) && defined(VBOX_WITH_PGM_NEM_MODE)
     1984    /*
     1985     * Unmap the RAM we're replacing.
     1986     */
     1987    if (fFlags & NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE)
     1988    {
     1989        HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, cb);
     1990        if (SUCCEEDED(hrc))
     1991        { /* likely */ }
     1992        else if (pvMmio2)
     1993            LogRel(("NEMR3NotifyPhysMmioExMapEarly: GCPhys=%RGp LB %RGp fFlags=%#x: Unmap -> hrc=%Rhrc (%#x) Last=%#x/%u (ignored)\n",
     1994                    GCPhys, cb, fFlags, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
     1995        else
     1996        {
     1997            LogRel(("NEMR3NotifyPhysMmioExMapEarly: GCPhys=%RGp LB %RGp fFlags=%#x: Unmap -> hrc=%Rhrc (%#x) Last=%#x/%u\n",
     1998                    GCPhys, cb, fFlags, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
     1999            return VERR_NEM_UNMAP_PAGES_FAILED;
     2000        }
     2001    }
     2002
     2003    /*
     2004     * Map MMIO2 if any.
     2005     */
     2006    if (pvMmio2)
     2007    {
     2008        Assert(fFlags & NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2);
     2009        HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, pvMmio2, GCPhys, cb,
     2010                                     WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagWrite | WHvMapGpaRangeFlagExecute);
     2011        if (SUCCEEDED(hrc))
     2012            *pu2State = NEM_WIN_PAGE_STATE_WRITABLE;
     2013        else
     2014        {
     2015            LogRel(("NEMR3NotifyPhysMmioExMapEarly: GCPhys=%RGp LB %RGp fFlags=%#x pvMmio2=%p: Map -> hrc=%Rhrc (%#x) Last=%#x/%u\n",
     2016                    GCPhys, cb, fFlags, pvMmio2, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
     2017            return VERR_NEM_MAP_PAGES_FAILED;
     2018        }
     2019    }
     2020    else
     2021    {
     2022        Assert(!(fFlags & NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2));
     2023        *pu2State = NEM_WIN_PAGE_STATE_UNMAPPED;
     2024    }
     2025
     2026#else
     2027    RT_NOREF(pVM, GCPhys, cb, pvRam, pvMmio2);
     2028    *pu2State = (fFlags & NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE) ? UINT8_MAX : NEM_WIN_PAGE_STATE_UNMAPPED;
     2029#endif
    19562030    return VINF_SUCCESS;
    19572031}
    19582032
    19592033
    1960 int nemR3NativeNotifyPhysMmioExUnmap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags)
    1961 {
    1962     Log5(("nemR3NativeNotifyPhysMmioExUnmap: %RGp LB %RGp fFlags=%#x\n", GCPhys, cb, fFlags));
    1963     NOREF(pVM); NOREF(GCPhys); NOREF(cb); NOREF(fFlags);
     2034VMMR3_INT_DECL(int) NEMR3NotifyPhysMmioExMapLate(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags,
     2035                                                 void *pvRam, void *pvMmio2)
     2036{
     2037    RT_NOREF(pVM, GCPhys, cb, fFlags, pvRam, pvMmio2);
    19642038    return VINF_SUCCESS;
    19652039}
    19662040
    19672041
    1968 /**
    1969  * Called early during ROM registration, right after the pages have been
    1970  * allocated and the RAM range updated.
    1971  *
    1972  * This will be succeeded by a number of NEMHCNotifyPhysPageProtChanged() calls
    1973  * and finally a NEMR3NotifyPhysRomRegisterEarly().
    1974  *
    1975  * @returns VBox status code
    1976  * @param   pVM             The cross context VM structure.
    1977  * @param   GCPhys          The ROM address (page aligned).
    1978  * @param   cb              The size (page aligned).
    1979  * @param   fFlags          NEM_NOTIFY_PHYS_ROM_F_XXX.
    1980  */
    1981 int nemR3NativeNotifyPhysRomRegisterEarly(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags)
    1982 {
    1983     Log5(("nemR3NativeNotifyPhysRomRegisterEarly: %RGp LB %RGp fFlags=%#x\n", GCPhys, cb, fFlags));
     2042VMMR3_INT_DECL(int) NEMR3NotifyPhysMmioExUnmap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags, void *pvRam,
     2043                                               void *pvMmio2, uint8_t *pu2State)
     2044{
     2045    Log5(("NEMR3NotifyPhysMmioExUnmap: %RGp LB %RGp fFlags=%#x pvRam=%p pvMmio2=%p pu2State=%p\n",
     2046          GCPhys, cb, fFlags, pvRam, pvMmio2, pu2State));
     2047
     2048    int rc = VINF_SUCCESS;
     2049#if !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) && defined(VBOX_WITH_PGM_NEM_MODE)
     2050    /*
     2051     * Unmap the MMIO2 pages.
     2052     */
     2053    /** @todo If we implement aliasing (MMIO2 page aliased into MMIO range),
     2054     *        we may have more stuff to unmap even in case of pure MMIO... */
     2055    if (fFlags & NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2)
     2056    {
     2057        HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, cb);
     2058        if (FAILED(hrc))
     2059        {
     2060            LogRel2(("NEMR3NotifyPhysMmioExUnmap: GCPhys=%RGp LB %RGp fFlags=%#x: Unmap -> hrc=%Rhrc (%#x) Last=%#x/%u (ignored)\n",
     2061                     GCPhys, cb, fFlags, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
     2062            rc = VERR_NEM_UNMAP_PAGES_FAILED;
     2063        }
     2064    }
     2065
     2066    /*
     2067     * Restore the RAM we replaced.
     2068     */
     2069    if (fFlags & NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE)
     2070    {
     2071        AssertPtr(pvRam);
     2072        HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, pvRam, GCPhys, cb,
     2073                                     WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagWrite | WHvMapGpaRangeFlagExecute);
     2074        if (SUCCEEDED(hrc))
     2075        { /* likely */ }
     2076        else
     2077        {
     2078            LogRel(("NEMR3NotifyPhysMmioExUnmap: GCPhys=%RGp LB %RGp pvMmio2=%p hrc=%Rhrc (%#x) Last=%#x/%u\n",
     2079                    GCPhys, cb, pvMmio2, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
     2080            rc = VERR_NEM_MAP_PAGES_FAILED;
     2081        }
     2082        if (pu2State)
     2083            *pu2State = NEM_WIN_PAGE_STATE_WRITABLE;
     2084    }
     2085    /* Mark the pages as unmapped if relevant. */
     2086    else if (pu2State)
     2087        *pu2State = NEM_WIN_PAGE_STATE_UNMAPPED;
     2088
     2089    RT_NOREF(pvMmio2);
     2090#else
     2091    RT_NOREF(pVM, GCPhys, cb, fFlags, pvRam, pvMmio2, pu2State);
     2092    if (pu2State)
     2093        *pu2State = UINT8_MAX;
     2094#endif
     2095    return rc;
     2096}
     2097
     2098
     2099VMMR3_INT_DECL(int)  NEMR3NotifyPhysRomRegisterEarly(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, void *pvPages, uint32_t fFlags,
     2100                                                     uint8_t *pu2State)
     2101{
     2102    Log5(("nemR3NativeNotifyPhysRomRegisterEarly: %RGp LB %RGp pvPages=%p fFlags=%#x\n", GCPhys, cb, pvPages, fFlags));
     2103    *pu2State = UINT8_MAX;
     2104
    19842105#if 0 /* Let's not do this after all.  We'll protection change notifications for each page and if not we'll map them lazily. */
    19852106    RTGCPHYS const cPages = cb >> X86_PAGE_SHIFT;
     
    20072128        }
    20082129    }
     2130    RT_NOREF_PV(fFlags);
    20092131#else
    2010     NOREF(pVM); NOREF(GCPhys); NOREF(cb);
    2011 #endif
    2012     RT_NOREF_PV(fFlags);
     2132    RT_NOREF(pVM, GCPhys, cb, pvPages, fFlags);
     2133#endif
    20132134    return VINF_SUCCESS;
    20142135}
    20152136
    20162137
    2017 /**
    2018  * Called after the ROM range has been fully completed.
    2019  *
    2020  * This will be preceeded by a NEMR3NotifyPhysRomRegisterEarly() call as well a
    2021  * number of NEMHCNotifyPhysPageProtChanged calls.
    2022  *
    2023  * @returns VBox status code
    2024  * @param   pVM             The cross context VM structure.
    2025  * @param   GCPhys          The ROM address (page aligned).
    2026  * @param   cb              The size (page aligned).
    2027  * @param   fFlags          NEM_NOTIFY_PHYS_ROM_F_XXX.
    2028  */
    2029 int nemR3NativeNotifyPhysRomRegisterLate(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags)
    2030 {
    2031     Log5(("nemR3NativeNotifyPhysRomRegisterLate: %RGp LB %RGp fFlags=%#x\n", GCPhys, cb, fFlags));
    2032     NOREF(pVM); NOREF(GCPhys); NOREF(cb); NOREF(fFlags);
     2138VMMR3_INT_DECL(int)  NEMR3NotifyPhysRomRegisterLate(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, void *pvPages,
     2139                                                    uint32_t fFlags, uint8_t *pu2State)
     2140{
     2141    Log5(("nemR3NativeNotifyPhysRomRegisterLate: %RGp LB %RGp pvPages=%p fFlags=%#x pu2State=%p\n",
     2142          GCPhys, cb, pvPages, fFlags, pu2State));
     2143    *pu2State = UINT8_MAX;
     2144
     2145#if !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) && defined(VBOX_WITH_PGM_NEM_MODE)
     2146    /*
     2147     * (Re-)map readonly.
     2148     */
     2149    AssertPtrReturn(pvPages, VERR_INVALID_POINTER);
     2150    HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, pvPages, GCPhys, cb, WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagExecute);
     2151    if (SUCCEEDED(hrc))
     2152        *pu2State = NEM_WIN_PAGE_STATE_READABLE;
     2153    else
     2154    {
     2155        LogRel(("nemR3NativeNotifyPhysRomRegisterEarly: GCPhys=%RGp LB %RGp pvPages=%p fFlags=%#x hrc=%Rhrc (%#x) Last=%#x/%u\n",
     2156                GCPhys, cb, pvPages, fFlags, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
     2157        return VERR_NEM_MAP_PAGES_FAILED;
     2158    }
     2159    RT_NOREF(fFlags);
     2160#else
     2161    RT_NOREF(pVM, GCPhys, cb, pvPages, fFlags);
     2162#endif
    20332163    return VINF_SUCCESS;
    20342164}
  • trunk/src/VBox/VMM/VMMR3/PGM.cpp

    r91580 r91848  
    736736
    737737
     738#ifdef VBOX_WITH_PGM_NEM_MODE
     739/**
     740 * Interface that NEM uses to switch PGM into simplified memory managment mode.
     741 *
     742 * This call occurs before PGMR3Init.
     743 *
     744 * @param   pVM     The cross context VM structure.
     745 */
     746VMMR3_INT_DECL(void) PGMR3EnableNemMode(PVM pVM)
     747{
     748    AssertFatal(!PDMCritSectIsInitialized(&pVM->pgm.s.CritSectX));
     749    pVM->pgm.s.fNemMode = true;
     750}
     751#endif
    738752
    739753
     
    810824    pVM->pgm.s.enmHostMode      = SUPPAGINGMODE_INVALID;
    811825    pVM->pgm.s.GCPhys4MBPSEMask = RT_BIT_64(32) - 1; /* default; checked later */
     826#ifndef PGM_WITHOUT_MAPPINGS
    812827    pVM->pgm.s.GCPtrPrevRamRangeMapping = MM_HYPER_AREA_ADDRESS;
     828#endif
    813829
    814830    rc = CFGMR3QueryBoolDef(CFGMR3GetRoot(pVM), "RamPreAlloc", &pVM->pgm.s.fRamPreAlloc,
  • trunk/src/VBox/VMM/VMMR3/PGMHandler.cpp

    r90439 r91848  
    252252            PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, PGM_PAGE_HNDL_PHYS_STATE_NONE);
    253253
     254#ifdef VBOX_WITH_NATIVE_NEM
    254255            /* Tell NEM about the protection change. */
    255256            if (VM_IS_NEM_ENABLED(pVM))
     
    258259                PGMPAGETYPE enmType = (PGMPAGETYPE)PGM_PAGE_GET_TYPE(pPage);
    259260                NEMHCNotifyPhysPageProtChanged(pVM, GCPhys, PGM_PAGE_GET_HCPHYS(pPage),
     261                                               PGM_RAMRANGE_CALC_PAGE_R3PTR(pRamHint, GCPhys),
    260262                                               pgmPhysPageCalcNemProtection(pPage, enmType), enmType, &u2State);
    261263                PGM_PAGE_SET_NEM_STATE(pPage, u2State);
    262264            }
     265#endif
    263266        }
    264267        else
     
    296299            PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, uState);
    297300
     301#ifdef VBOX_WITH_NATIVE_NEM
    298302            /* Tell NEM about the protection change. */
    299303            if (VM_IS_NEM_ENABLED(pVM))
     
    302306                PGMPAGETYPE enmType = (PGMPAGETYPE)PGM_PAGE_GET_TYPE(pPage);
    303307                NEMHCNotifyPhysPageProtChanged(pVM, GCPhys, PGM_PAGE_GET_HCPHYS(pPage),
     308                                               PGM_RAMRANGE_CALC_PAGE_R3PTR(pRamHint, GCPhys),
    304309                                               pgmPhysPageCalcNemProtection(pPage, enmType), enmType, &u2State);
    305310                PGM_PAGE_SET_NEM_STATE(pPage, u2State);
    306311            }
     312#endif
    307313        }
    308314        else
  • 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    /*
  • trunk/src/VBox/VMM/VMMR3/PGMSavedState.cpp

    r90439 r91848  
    27002700                        if (   PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_ROM
    27012701                            || PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_ROM_SHADOW
     2702#ifdef VBOX_WITH_PGM_NEM_MODE
     2703                            || pVM->pgm.s.fNemMode
     2704#endif
    27022705                            || pVM->pgm.s.fRamPreAlloc)
    27032706                        {
  • trunk/src/VBox/VMM/include/NEMInternal.h

    r91702 r91848  
    4242 */
    4343
     44#if defined(VBOX_WITH_PGM_NEM_MODE) && !defined(VBOX_WITH_NATIVE_NEM)
     45# error "VBOX_WITH_PGM_NEM_MODE requires VBOX_WITH_NATIVE_NEM to be defined"
     46#endif
     47
    4448
    4549#ifdef RT_OS_WINDOWS
     
    6064# if defined(NEM_WIN_WITH_RING0_RUNLOOP) && !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES)
    6165#  error "NEM_WIN_WITH_RING0_RUNLOOP requires NEM_WIN_USE_HYPERCALLS_FOR_PAGES"
     66# endif
     67# if defined(VBOX_WITH_PGM_NEM_MODE) && defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES)
     68#  error "VBOX_WITH_PGM_NEM_MODE cannot be used together with NEM_WIN_USE_HYPERCALLS_FOR_PAGES"
    6269# endif
    6370
     
    451458void            nemR3NativeNotifyFF(PVM pVM, PVMCPU pVCpu, uint32_t fFlags);
    452459
    453 int     nemR3NativeNotifyPhysRamRegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb);
    454 int     nemR3NativeNotifyPhysMmioExMap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags, void *pvMmio2);
    455 int     nemR3NativeNotifyPhysMmioExUnmap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags);
    456 int     nemR3NativeNotifyPhysRomRegisterEarly(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags);
    457 int     nemR3NativeNotifyPhysRomRegisterLate(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags);
    458460void    nemR3NativeNotifySetA20(PVMCPU pVCpu, bool fEnabled);
    459461#endif
    460462
    461463void    nemHCNativeNotifyHandlerPhysicalRegister(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhys, RTGCPHYS cb);
    462 void    nemHCNativeNotifyHandlerPhysicalDeregister(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhys, RTGCPHYS cb,
    463                                                    int fRestoreAsRAM, bool fRestoreAsRAM2);
    464464void    nemHCNativeNotifyHandlerPhysicalModify(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhysOld,
    465465                                               RTGCPHYS GCPhysNew, RTGCPHYS cb, bool fRestoreAsRAM);
    466466int     nemHCNativeNotifyPhysPageAllocated(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint32_t fPageProt,
    467467                                           PGMPAGETYPE enmType, uint8_t *pu2State);
    468 void    nemHCNativeNotifyPhysPageProtChanged(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint32_t fPageProt,
    469                                              PGMPAGETYPE enmType, uint8_t *pu2State);
    470 void    nemHCNativeNotifyPhysPageChanged(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhysPrev, RTHCPHYS HCPhysNew, uint32_t fPageProt,
    471                                          PGMPAGETYPE enmType, uint8_t *pu2State);
    472468
    473469
  • trunk/src/VBox/VMM/include/PGMInline.h

    r91247 r91848  
    346346    }
    347347
     348#ifdef VBOX_WITH_NATIVE_NEM
    348349    /* Tell NEM. */
    349350    if (VM_IS_NEM_ENABLED(pVM))
    350351    {
    351         uint8_t     u2State = PGM_PAGE_GET_NEM_STATE(pPage);
    352         PGMPAGETYPE enmType = (PGMPAGETYPE)PGM_PAGE_GET_TYPE(pPage);
     352        uint8_t      u2State = PGM_PAGE_GET_NEM_STATE(pPage);
     353        PGMPAGETYPE  enmType = (PGMPAGETYPE)PGM_PAGE_GET_TYPE(pPage);
     354        PPGMRAMRANGE pRam    = pgmPhysGetRange(pVM, GCPhysPage);
    353355        NEMHCNotifyPhysPageProtChanged(pVM, GCPhysPage, PGM_PAGE_GET_HCPHYS(pPage),
     356                                       pRam ? PGM_RAMRANGE_CALC_PAGE_R3PTR(pRam, GCPhysPage) : NULL,
    354357                                       pgmPhysPageCalcNemProtection(pPage, enmType), enmType, &u2State);
    355358        PGM_PAGE_SET_NEM_STATE(pPage, u2State);
    356359    }
     360#endif
    357361}
    358362
  • trunk/src/VBox/VMM/include/PGMInternal.h

    r91712 r91848  
    159159 * only making them writable when getting a write access \#PF. */
    160160#define VBOX_WITH_REAL_WRITE_MONITORED_PAGES
     161
     162/** @def VBOX_WITH_PGM_NEM_MODE
     163 * Enabled the NEM memory management mode in PGM.  See PGM::fNemMode for
     164 * details. */
     165#ifdef DOXYGEN_RUNNING
     166# define VBOX_WITH_PGM_NEM_MODE
     167#endif
    161168
    162169/** @} */
     
    12761283    /** Last address in the range (inclusive). Page aligned (-1). */
    12771284    RTGCPHYS                            GCPhysLast;
    1278     /** Start of the HC mapping of the range. This is only used for MMIO2. */
     1285    /** Start of the HC mapping of the range. This is only used for MMIO2 and in NEM mode. */
    12791286    R3PTRTYPE(void *)                   pvR3;
    12801287    /** Live save per page tracking data. */
     
    13351342#define PGM_RAMRANGE_TLB_IDX(a_GCPhys)      ( ((a_GCPhys) >> 20) & (PGM_RAMRANGE_TLB_ENTRIES - 1) )
    13361343
     1344/**
     1345 * Calculates the ring-3 address for a_GCPhysPage if the RAM range has a
     1346 * mapping address.
     1347 */
     1348#define PGM_RAMRANGE_CALC_PAGE_R3PTR(a_pRam, a_GCPhysPage) \
     1349    ( (a_pRam)->pvR3 ? (R3PTRTYPE(uint8_t *))(a_pRam)->pvR3 + (a_GCPhysPage) - (a_pRam)->GCPhys : NULL )
    13371350
    13381351
     
    13951408    RTGCPHYS                            cb;
    13961409    /** The flags (PGMPHYS_ROM_FLAGS_*). */
    1397     uint32_t                            fFlags;
     1410    uint8_t                             fFlags;
    13981411    /** The saved state range ID. */
    13991412    uint8_t                             idSavedState;
    14001413    /** Alignment padding. */
    1401     uint8_t                             au8Alignment[3];
    1402     /** Alignment padding ensuring that aPages is sizeof(PGMROMPAGE) aligned. */
    1403     uint32_t                            au32Alignemnt[HC_ARCH_BITS == 32 ? 5 : 1];
     1414    uint8_t                             au8Alignment[2];
    14041415    /** The size bits pvOriginal points to. */
    14051416    uint32_t                            cbOriginal;
     
    14091420    /** The ROM description. */
    14101421    R3PTRTYPE(const char *)             pszDesc;
     1422#ifdef VBOX_WITH_PGM_NEM_MODE
     1423    /** In simplified memory mode this provides alternate backing for shadowed ROMs.
     1424     * - PGMROMPROT_READ_ROM_WRITE_IGNORE:  Shadow
     1425     * - PGMROMPROT_READ_ROM_WRITE_RAM:     Shadow
     1426     * - PGMROMPROT_READ_RAM_WRITE_IGNORE:  ROM
     1427     * - PGMROMPROT_READ_RAM_WRITE_RAM:     ROM  */
     1428    R3PTRTYPE(uint8_t *)                pbR3Alternate;
     1429    RTR3PTR                             pvAlignment2;
     1430#endif
    14111431    /** The per page tracking structures. */
    14121432    PGMROMPAGE                          aPages[1];
     
    29192939     */
    29202940    bool                            fRamPreAlloc;
     2941#ifdef VBOX_WITH_PGM_NEM_MODE
     2942    /** Set if we're operating in NEM memory mode.
     2943     *
     2944     * NEM mode implies that memory is allocated in big chunks for each RAM range
     2945     * rather than on demand page by page.  Memory is also not locked and PGM has
     2946     * therefore no physical addresses for them.  Page sharing is out of the
     2947     * question.  Ballooning depends on the native execution engine, but probably
     2948     * pointless as well.  */
     2949    bool                            fNemMode;
     2950# define PGM_IS_IN_NEM_MODE(a_pVM)  ((a_pVM)->pgm.s.fNemMode)
     2951#else
     2952# define PGM_IS_IN_NEM_MODE(a_pVM)  (false)
     2953#endif
    29212954    /** Indicates whether write monitoring is currently in use.
    29222955     * This is used to prevent conflicts between live saving and page sharing
     
    29322965     * change this later on. */
    29332966    bool                            fNestedPaging;
    2934     /** The host paging mode. (This is what SUPLib reports.) */
    2935     SUPPAGINGMODE                   enmHostMode;
    29362967    /** We're not in a state which permits writes to guest memory.
    29372968     * (Only used in strict builds.) */
     
    29552986    bool                            fUseLargePages;
    29562987    /** Alignment padding. */
    2957     bool                            afAlignment3[6];
     2988#ifndef VBOX_WITH_PGM_NEM_MODE
     2989    bool                            afAlignment3[1];
     2990#endif
     2991    /** The host paging mode. (This is what SUPLib reports.) */
     2992    SUPPAGINGMODE                   enmHostMode;
     2993    bool                            fAlignment3b;
    29582994
    29592995    /** Indicates that PGMR3FinalizeMappings has been called and that further
     
    29753011     * This is valid if either fMappingsFixed or fMappingsFixedRestored is set. */
    29763012    RTGCPTR                         GCPtrMappingFixed;
     3013#ifndef PGM_WITHOUT_MAPPINGS
    29773014    /** The address of the previous RAM range mapping. */
    29783015    RTGCPTR                         GCPtrPrevRamRangeMapping;
     3016#else
     3017    RTGCPTR                         Unused0;
     3018#endif
    29793019
    29803020    /** Physical access handler type for ROM protection. */
     
    37223762int             pgmHandlerPhysicalExDup(PVMCC pVM, PPGMPHYSHANDLER pPhysHandlerSrc, PPGMPHYSHANDLER *ppPhysHandler);
    37233763int             pgmHandlerPhysicalExRegister(PVMCC pVM, PPGMPHYSHANDLER pPhysHandler, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast);
    3724 int             pgmHandlerPhysicalExDeregister(PVMCC pVM, PPGMPHYSHANDLER pPhysHandler, int fRestoreAsRAM);
     3764int             pgmHandlerPhysicalExDeregister(PVMCC pVM, PPGMPHYSHANDLER pPhysHandler);
    37253765int             pgmHandlerPhysicalExDestroy(PVMCC pVM, PPGMPHYSHANDLER pHandler);
    37263766void            pgmR3HandlerPhysicalUpdateAll(PVM pVM);
    37273767bool            pgmHandlerPhysicalIsAll(PVMCC pVM, RTGCPHYS GCPhys);
    3728 void            pgmHandlerPhysicalResetAliasedPage(PVMCC pVM, PPGMPAGE pPage, RTGCPHYS GCPhysPage, bool fDoAccounting);
     3768void            pgmHandlerPhysicalResetAliasedPage(PVMCC pVM, PPGMPAGE pPage, RTGCPHYS GCPhysPage, PPGMRAMRANGE pRam, bool fDoAccounting);
    37293769DECLCALLBACK(void) pgmR3InfoHandlers(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
    37303770int             pgmR3InitSavedState(PVM pVM, uint64_t cbRam);
     
    37633803int             pgmPhysGetPageExSlow(PVM pVM, RTGCPHYS GCPhys, PPPGMPAGE ppPage);
    37643804int             pgmPhysGetPageAndRangeExSlow(PVM pVM, RTGCPHYS GCPhys, PPPGMPAGE ppPage, PPGMRAMRANGE *ppRam);
     3805#ifdef VBOX_WITH_NATIVE_NEM
     3806void            pgmPhysSetNemStateForPages(PPGMPAGE paPages, RTGCPHYS cPages, uint8_t u2State);
     3807#endif
    37653808
    37663809#ifdef IN_RING3
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