PGMR0.cpp revision 73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync * PGM - Page Manager and Monitor, Ring-0.
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2007 Oracle Corporation
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync * available from http://www.virtualbox.org. This file is free software;
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync/*******************************************************************************
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync* Header Files *
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync*******************************************************************************/
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_32BIT_PROT(name)
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_PROT(name)
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_AMD64_PROT(name)
289060a0c3cb1d509f2cb01fca060796212376f6vboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_EPT_PROT(name)
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync * Worker function for PGMR3PhysAllocateHandyPages and pgmPhysEnsureHandyPage.
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync * @returns The following VBox status codes.
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync * @retval VINF_SUCCESS on success. FF cleared.
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync * @retval VINF_EM_NO_MEMORY if we're out of memory. The FF is set in this case.
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync * @param pVM The VM handle.
faf968cea88f2ab4bcc3325b17bc8b095a8e3642vboxsync * @param pVCpu The VMCPU handle.
436b5c616e019c5e62053657c52d3ab5562ecbbfvboxsync * @remarks Must be called from within the PGM critical section. The caller
436b5c616e019c5e62053657c52d3ab5562ecbbfvboxsync * must clear the new pages.
faf968cea88f2ab4bcc3325b17bc8b095a8e3642vboxsyncVMMR0DECL(int) PGMR0PhysAllocateHandyPages(PVM pVM, PVMCPU pVCpu)
faf968cea88f2ab4bcc3325b17bc8b095a8e3642vboxsync Assert(PDMCritSectIsOwnerEx(&pVM->pgm.s.CritSect, pVCpu->idCpu));
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync * Check for error injection.
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync * Try allocate a full set of handy pages.
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync AssertReturn(iFirst <= RT_ELEMENTS(pVM->pgm.s.aHandyPages), VERR_INTERNAL_ERROR);
436b5c616e019c5e62053657c52d3ab5562ecbbfvboxsync uint32_t cPages = RT_ELEMENTS(pVM->pgm.s.aHandyPages) - iFirst;
f94f82d66536c7332c347dd9a3a9f0f8c79247f4vboxsync int rc = GMMR0AllocateHandyPages(pVM, pVCpu->idCpu, cPages, cPages, &pVM->pgm.s.aHandyPages[iFirst]);
436b5c616e019c5e62053657c52d3ab5562ecbbfvboxsync for (uint32_t i = 0; i < RT_ELEMENTS(pVM->pgm.s.aHandyPages); i++)
436b5c616e019c5e62053657c52d3ab5562ecbbfvboxsync Assert(pVM->pgm.s.aHandyPages[i].idPage != NIL_GMM_PAGEID);
436b5c616e019c5e62053657c52d3ab5562ecbbfvboxsync Assert(pVM->pgm.s.aHandyPages[i].idPage <= GMM_PAGEID_LAST);
436b5c616e019c5e62053657c52d3ab5562ecbbfvboxsync Assert(pVM->pgm.s.aHandyPages[i].idSharedPage == NIL_GMM_PAGEID);
436b5c616e019c5e62053657c52d3ab5562ecbbfvboxsync Assert(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys != NIL_RTHCPHYS);
436b5c616e019c5e62053657c52d3ab5562ecbbfvboxsync Assert(!(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys & ~X86_PTE_PAE_PG_MASK));
436b5c616e019c5e62053657c52d3ab5562ecbbfvboxsync pVM->pgm.s.cHandyPages = RT_ELEMENTS(pVM->pgm.s.aHandyPages);
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync /* We're ASSUMING that GMM has updated all the entires before failing us. */
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync for (i = iFirst; i < RT_ELEMENTS(pVM->pgm.s.aHandyPages); i++)
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync Assert(pVM->pgm.s.aHandyPages[i].idPage == NIL_GMM_PAGEID);
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync Assert(pVM->pgm.s.aHandyPages[i].idSharedPage == NIL_GMM_PAGEID);
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync Assert(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys == NIL_RTHCPHYS);
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync * Reduce the number of pages until we hit the minimum limit.
f94f82d66536c7332c347dd9a3a9f0f8c79247f4vboxsync rc = GMMR0AllocateHandyPages(pVM, pVCpu->idCpu, cPages, cPages, &pVM->pgm.s.aHandyPages[iFirst]);
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync while (i-- > 0)
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync Assert(pVM->pgm.s.aHandyPages[i].idPage != NIL_GMM_PAGEID);
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync Assert(pVM->pgm.s.aHandyPages[i].idPage <= GMM_PAGEID_LAST);
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync Assert(pVM->pgm.s.aHandyPages[i].idSharedPage == NIL_GMM_PAGEID);
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync Assert(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys != NIL_RTHCPHYS);
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync Assert(!(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys & ~X86_PTE_PAE_PG_MASK));
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync for (i = cPages + iFirst; i < RT_ELEMENTS(pVM->pgm.s.aHandyPages); i++)
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync Assert(pVM->pgm.s.aHandyPages[i].idPage == NIL_GMM_PAGEID);
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync Assert(pVM->pgm.s.aHandyPages[i].idSharedPage == NIL_GMM_PAGEID);
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync Assert(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys == NIL_RTHCPHYS);
ff78b877ed7acd25e2d384570a938441455d6a95vboxsync LogRel(("PGMR0PhysAllocateHandyPages: rc=%Rrc iFirst=%d cPages=%d\n", rc, iFirst, cPages));
436b5c616e019c5e62053657c52d3ab5562ecbbfvboxsync LogFlow(("PGMR0PhysAllocateHandyPages: cPages=%d rc=%Rrc\n", cPages, rc));
30868e719f5a45ec4689ecb2616767cb1fd02c28vboxsync * Worker function for PGMR3PhysAllocateLargeHandyPage
30868e719f5a45ec4689ecb2616767cb1fd02c28vboxsync * @returns The following VBox status codes.
30868e719f5a45ec4689ecb2616767cb1fd02c28vboxsync * @retval VINF_SUCCESS on success.
30868e719f5a45ec4689ecb2616767cb1fd02c28vboxsync * @retval VINF_EM_NO_MEMORY if we're out of memory.
30868e719f5a45ec4689ecb2616767cb1fd02c28vboxsync * @param pVM The VM handle.
30868e719f5a45ec4689ecb2616767cb1fd02c28vboxsync * @param pVCpu The VMCPU handle.
30868e719f5a45ec4689ecb2616767cb1fd02c28vboxsync * @remarks Must be called from within the PGM critical section. The caller
30868e719f5a45ec4689ecb2616767cb1fd02c28vboxsync * must clear the new pages.
30868e719f5a45ec4689ecb2616767cb1fd02c28vboxsyncVMMR0DECL(int) PGMR0PhysAllocateLargeHandyPage(PVM pVM, PVMCPU pVCpu)
30868e719f5a45ec4689ecb2616767cb1fd02c28vboxsync Assert(PDMCritSectIsOwnerEx(&pVM->pgm.s.CritSect, pVCpu->idCpu));
30868e719f5a45ec4689ecb2616767cb1fd02c28vboxsync int rc = GMMR0AllocateLargePage(pVM, pVCpu->idCpu, _2M, &pVM->pgm.s.aLargeHandyPage[0].idPage, &pVM->pgm.s.aLargeHandyPage[0].HCPhysGCPhys);
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * #PF Handler for nested paging.
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @returns VBox status code (appropriate for trap handling and GC return).
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @param pVM VM Handle.
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync * @param pVCpu VMCPU Handle.
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @param enmShwPagingMode Paging mode for the nested page tables
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @param uErr The trap error code.
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @param pRegFrame Trap register frame.
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @param pvFault The fault address.
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsyncVMMR0DECL(int) PGMR0Trap0eHandlerNestedPaging(PVM pVM, PVMCPU pVCpu, PGMMODE enmShwPagingMode, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPHYS pvFault)
853e60357f021457980af0726d25a40ecd3c0107vboxsync LogFlow(("PGMTrap0eHandler: uErr=%RGx pvFault=%RGp eip=%RGv\n", uErr, pvFault, (RTGCPTR)pRegFrame->rip));
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync STAM_STATS({ pVCpu->pgm.s.CTX_SUFF(pStatTrap0eAttribution) = NULL; } );
289060a0c3cb1d509f2cb01fca060796212376f6vboxsync /* AMD uses the host's paging mode; Intel has a single mode (EPT). */
289060a0c3cb1d509f2cb01fca060796212376f6vboxsync AssertMsg(enmShwPagingMode == PGMMODE_32_BIT || enmShwPagingMode == PGMMODE_PAE || enmShwPagingMode == PGMMODE_PAE_NX || enmShwPagingMode == PGMMODE_AMD64 || enmShwPagingMode == PGMMODE_AMD64_NX || enmShwPagingMode == PGMMODE_EPT, ("enmShwPagingMode=%d\n", enmShwPagingMode));
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * Error code stats.
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync STAM_COUNTER_INC(&pVCpu->pgm.s.StatRZTrap0eUSNotPresentWrite);
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync STAM_COUNTER_INC(&pVCpu->pgm.s.StatRZTrap0eUSNotPresentRead);
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync STAM_COUNTER_INC(&pVCpu->pgm.s.StatRZTrap0eUSWrite);
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync STAM_COUNTER_INC(&pVCpu->pgm.s.StatRZTrap0eUSReserved);
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync STAM_COUNTER_INC(&pVCpu->pgm.s.StatRZTrap0eUSRead);
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync { /* Supervisor */
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync STAM_COUNTER_INC(&pVCpu->pgm.s.StatRZTrap0eSVNotPresentWrite);
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync STAM_COUNTER_INC(&pVCpu->pgm.s.StatRZTrap0eSVNotPresentRead);
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync STAM_COUNTER_INC(&pVCpu->pgm.s.StatRZTrap0eSVWrite);
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync STAM_COUNTER_INC(&pVCpu->pgm.s.StatRZTrap0eSVReserved);
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * Call the worker.
9ad5e3912962c3dbccc1afc4e7d62890fe906814vboxsync * We pretend the guest is in protected mode without paging, so we can use existing code to build the
134a71c1528b56afe4db843ab63ec5a5b849535bvboxsync * nested page tables.
0bc7c910e57c78c68e89122e2244cc073d1ef06evboxsync bool fLockTaken = false;
0bc7c910e57c78c68e89122e2244cc073d1ef06evboxsync rc = PGM_BTH_NAME_32BIT_PROT(Trap0eHandler)(pVCpu, uErr, pRegFrame, pvFault, &fLockTaken);
0bc7c910e57c78c68e89122e2244cc073d1ef06evboxsync rc = PGM_BTH_NAME_PAE_PROT(Trap0eHandler)(pVCpu, uErr, pRegFrame, pvFault, &fLockTaken);
0bc7c910e57c78c68e89122e2244cc073d1ef06evboxsync rc = PGM_BTH_NAME_AMD64_PROT(Trap0eHandler)(pVCpu, uErr, pRegFrame, pvFault, &fLockTaken);
0bc7c910e57c78c68e89122e2244cc073d1ef06evboxsync rc = PGM_BTH_NAME_EPT_PROT(Trap0eHandler)(pVCpu, uErr, pRegFrame, pvFault, &fLockTaken);
3c941112ffb137d71a8e457fcc3915f2d464ed2avboxsync /* Note: hack alert for difficult to reproduce problem. */
ae7f4100e4fa100f3ac68a77afc7cbdf89a5eb93vboxsync if ( rc == VERR_PAGE_NOT_PRESENT /* SMP only ; disassembly might fail. */
ae7f4100e4fa100f3ac68a77afc7cbdf89a5eb93vboxsync || rc == VERR_PAGE_TABLE_NOT_PRESENT /* seen with UNI & SMP */
3c941112ffb137d71a8e457fcc3915f2d464ed2avboxsync || rc == VERR_PAGE_DIRECTORY_PTR_NOT_PRESENT /* seen with SMP */
3c941112ffb137d71a8e457fcc3915f2d464ed2avboxsync || rc == VERR_PAGE_MAP_LEVEL4_NOT_PRESENT) /* precaution */
3c941112ffb137d71a8e457fcc3915f2d464ed2avboxsync Log(("WARNING: Unexpected VERR_PAGE_TABLE_NOT_PRESENT (%d) for page fault at %RGp error code %x (rip=%RGv)\n", rc, pvFault, uErr, pRegFrame->rip));
3c941112ffb137d71a8e457fcc3915f2d464ed2avboxsync /* Some kind of inconsistency in the SMP case; it's safe to just execute the instruction again; not sure about single VCPU VMs though. */
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync STAM_STATS({ if (!pVCpu->pgm.s.CTX_SUFF(pStatTrap0eAttribution))
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync pVCpu->pgm.s.CTX_SUFF(pStatTrap0eAttribution) = &pVCpu->pgm.s.StatRZTrap0eTime2Misc; });
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync STAM_PROFILE_STOP_EX(&pVCpu->pgm.s.StatRZTrap0e, pVCpu->pgm.s.CTX_SUFF(pStatTrap0eAttribution), a);
9d7fdfd90ef8d681a2d2c339339e8dc0b1fc5bd3vboxsync * Check a registered module for shared page changes
9d7fdfd90ef8d681a2d2c339339e8dc0b1fc5bd3vboxsync * @returns The following VBox status codes.
9d7fdfd90ef8d681a2d2c339339e8dc0b1fc5bd3vboxsync * @param pVM The VM handle.
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync * @param idCpu VCPU id
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync * @param pModule Module description
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync * @param pGVM Pointer to the GVM instance data.
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsyncVMMR0DECL(int) PGMR0SharedModuleCheckRegion(PVM pVM, VMCPUID idCpu, PGMMSHAREDMODULE pModule, PGVM pGVM)
e4d7b580d72e968d3753363ab36e196a968c1947vboxsync bool fFlushTLBs = false;
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync Log(("PGMR0SharedModuleCheck: check %s %s base=%RGv size=%x\n", pModule->szName, pModule->szVersion, pModule->Core.Key, pModule->cbModule));
9d7fdfd90ef8d681a2d2c339339e8dc0b1fc5bd3vboxsync /* Check every region of the shared module. */
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync Assert((pModule->aRegions[i].cbRegion & 0xfff) == 0);
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync Assert((pModule->aRegions[i].GCRegionAddr & 0xfff) == 0);
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync RTGCPTR GCRegion = pModule->aRegions[i].GCRegionAddr;
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync unsigned cbRegion = pModule->aRegions[i].cbRegion & ~0xfff;
209c11e4b5dbb310116c99a42d773163928e002bvboxsync unsigned idxPage = 0;
5879cb244b131c1e4b63ca7f27c4e026d7b96915vboxsync paPageDesc = (PGMMSHAREDPAGEDESC)RTMemAlloc((cbRegion >> PAGE_SHIFT) * sizeof(*paPageDesc));
ca74d6e1d76a5b1caf9a0b148306386821dadce8vboxsync rc = PGMGstGetPage(pVCpu, GCRegion, &fFlags, &GCPhys);
5879cb244b131c1e4b63ca7f27c4e026d7b96915vboxsync && !(fFlags & X86_PTE_RW)) /* important as we make assumptions about this below! */
9d7fdfd90ef8d681a2d2c339339e8dc0b1fc5bd3vboxsync PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);
2560ed0c999a3144e98992d4b2ee4e8803ae012avboxsync paPageDesc[idxPage].uHCPhysPageId = PGM_PAGE_GET_PAGEID(pPage);
2560ed0c999a3144e98992d4b2ee4e8803ae012avboxsync paPageDesc[idxPage].HCPhys = PGM_PAGE_GET_HCPHYS(pPage);
2560ed0c999a3144e98992d4b2ee4e8803ae012avboxsync paPageDesc[idxPage].uHCPhysPageId = NIL_GMM_PAGEID;
2560ed0c999a3144e98992d4b2ee4e8803ae012avboxsync paPageDesc[idxPage].uHCPhysPageId = NIL_GMM_PAGEID;
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync rc = GMMR0SharedModuleCheckRange(pGVM, pModule, i, idxPage, paPageDesc);
e4d7b580d72e968d3753363ab36e196a968c1947vboxsync for (unsigned i = 0; i < idxPage; i++)
e4d7b580d72e968d3753363ab36e196a968c1947vboxsync /* Any change for this page? */
e4d7b580d72e968d3753363ab36e196a968c1947vboxsync /** todo: maybe cache these to prevent the nth lookup. */
5879cb244b131c1e4b63ca7f27c4e026d7b96915vboxsync PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, paPageDesc[i].GCPhys);
e4d7b580d72e968d3753363ab36e196a968c1947vboxsync /* Should never happen. */
e7af1aba019c26bfd3e69e146884ad4b3daafa50vboxsync Log(("PGMR0SharedModuleCheck: shared page gc phys %RGp host %RHp->%RHp\n", paPageDesc[i].GCPhys, PGM_PAGE_GET_HCPHYS(pPage), paPageDesc[i].HCPhys));
5879cb244b131c1e4b63ca7f27c4e026d7b96915vboxsync if (paPageDesc[i].HCPhys != PGM_PAGE_GET_HCPHYS(pPage))
e4d7b580d72e968d3753363ab36e196a968c1947vboxsync bool fFlush = false;
5879cb244b131c1e4b63ca7f27c4e026d7b96915vboxsync /* Page was replaced by an existing shared version of it; clear all references first. */
5879cb244b131c1e4b63ca7f27c4e026d7b96915vboxsync rc = pgmPoolTrackUpdateGCPhys(pVM, paPageDesc[i].GCPhys, pPage, true /* clear the entries */, &fFlush);
e4d7b580d72e968d3753363ab36e196a968c1947vboxsync Assert(rc == VINF_SUCCESS || (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3) && (pVCpu->pgm.s.fSyncFlags & PGM_SYNC_CLEAR_PGM_POOL)));
e4d7b580d72e968d3753363ab36e196a968c1947vboxsync /* Update the physical address and page id now. */
5879cb244b131c1e4b63ca7f27c4e026d7b96915vboxsync PGM_PAGE_SET_PAGEID(pPage, paPageDesc[i].uHCPhysPageId);
bc0229fce4e9f3a2938f0e8c680c3d92f78351dcvboxsync /* Invalidate page map TLB entry for this page too. */
bc0229fce4e9f3a2938f0e8c680c3d92f78351dcvboxsync PGMPhysInvalidatePageMapTLBEntry(pVM, paPageDesc[i].GCPhys);
e4d7b580d72e968d3753363ab36e196a968c1947vboxsync /* else nothing changed (== this page is now a shared page), so no need to flush anything. */
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync * Shared module registration helper (called on the way out).
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync * @param pVM The VM handle.
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync * @param pReq Registration request info
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsyncstatic DECLCALLBACK(void) pgmR3SharedModuleRegisterHelper(PVM pVM, PGMMREGISTERSHAREDMODULEREQ pReq)
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync Assert(rc == VINF_SUCCESS || rc == VINF_PGM_SHARED_MODULE_COLLISION || rc == VINF_PGM_SHARED_MODULE_ALREADY_REGISTERED);
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync if (rc == VINF_PGM_SHARED_MODULE_ALREADY_REGISTERED)
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync /** todo count copy-on-write actions in the trap handler so we don't have to check everything all the time! */
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync /* Count the number of shared pages that were changed (copy-on-write). */
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync Assert((pReq->aRegions[i].GCRegionAddr & 0xfff) == 0);
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync uint32_t cbRegion = pReq->aRegions[i].cbRegion & ~0xfff;
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync rc = PGMGstGetPage(pVCpu, GCRegion, &fFlags, &GCPhys);
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync /* Full (re)check needed? */
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync pReq->Hdr.cbReq = RT_OFFSETOF(GMMREGISTERSHAREDMODULEREQ, aRegions[pReq->cRegions]);
73c74bb1e8e8a8c2f26c69cb20f7666fcb72b1f0vboxsync /* We must stall other VCPUs as we'd otherwise have to send IPI flush commands for every single change we make. */