PGMR0SharedPage.cpp revision 2fb42335a74fe26c4e2bccbf16f077015e42a5e1
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * PGM - Page Manager and Monitor, Ring-0.
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2007 Oracle Corporation
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * available from http://www.virtualbox.org. This file is free software;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * you can redistribute it and/or modify it under the terms of the GNU
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * General Public License (GPL) as published by the Free Software
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/*******************************************************************************
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync* Header Files *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync*******************************************************************************/
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Check a registered module for shared page changes
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns The following VBox status codes.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pVM The VM handle.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param idCpu VCPU id
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pModule Module description
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param cRegions Number of regions
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pRegions Region array
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pGVM Pointer to the GVM instance data.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncVMMR0DECL(int) PGMR0SharedModuleCheck(PVM pVM, PGVM pGVM, VMCPUID idCpu, PGMMSHAREDMODULE pModule, uint32_t cRegions, PGMMSHAREDREGIONDESC pRegions)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync bool fFlushTLBs = false;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Log(("PGMR0SharedModuleCheck: check %s %s base=%RGv size=%x\n", pModule->szName, pModule->szVersion, pModule->Core.Key, pModule->cbModule));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* Check every region of the shared module. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync for (unsigned idxRegion = 0; idxRegion < cRegions; idxRegion++)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Assert((pRegions[idxRegion].cbRegion & 0xfff) == 0);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Assert((pRegions[idxRegion].GCRegionAddr & 0xfff) == 0);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTGCPTR GCRegion = pRegions[idxRegion].GCRegionAddr;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync unsigned cbRegion = pRegions[idxRegion].cbRegion & ~0xfff;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync unsigned idxPage = 0;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync paPageDesc = (PGMMSHAREDPAGEDESC)RTMemAlloc((cbRegion >> PAGE_SHIFT) * sizeof(*paPageDesc));
c77e7bff89c7639353778366984d51ff165ea0e3vboxsync rc = PGMGstGetPage(pVCpu, GCRegion, &fFlags, &GCPhys);
c77e7bff89c7639353778366984d51ff165ea0e3vboxsync && !(fFlags & X86_PTE_RW)) /* important as we make assumptions about this below! */
c77e7bff89c7639353778366984d51ff165ea0e3vboxsync PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);
501e3e846528298f82146d5afa36830a3f9b1267vboxsync paPageDesc[idxPage].uHCPhysPageId = PGM_PAGE_GET_PAGEID(pPage);
501e3e846528298f82146d5afa36830a3f9b1267vboxsync paPageDesc[idxPage].HCPhys = PGM_PAGE_GET_HCPHYS(pPage);
501e3e846528298f82146d5afa36830a3f9b1267vboxsync paPageDesc[idxPage].uHCPhysPageId = NIL_GMM_PAGEID;
501e3e846528298f82146d5afa36830a3f9b1267vboxsync paPageDesc[idxPage].uHCPhysPageId = NIL_GMM_PAGEID;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = GMMR0SharedModuleCheckRange(pGVM, pModule, idxRegion, idxPage, paPageDesc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync for (unsigned i = 0; i < idxPage; i++)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* Any change for this page? */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** todo: maybe cache these to prevent the nth lookup. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, paPageDesc[i].GCPhys);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* Should never happen. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Assert(pPage->uStateY == PGM_PAGE_STATE_ALLOCATED);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Log(("PGMR0SharedModuleCheck: shared page gc virt=%RGv phys %RGp host %RHp->%RHp\n", pRegions[idxRegion].GCRegionAddr + i * PAGE_SIZE, paPageDesc[i].GCPhys, PGM_PAGE_GET_HCPHYS(pPage), paPageDesc[i].HCPhys));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (paPageDesc[i].HCPhys != PGM_PAGE_GET_HCPHYS(pPage))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync bool fFlush = false;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* Page was replaced by an existing shared version of it; clear all references first. */
be9fcc1751f2ee5d873be8510fed59aad8f39a19vboxsync rc = pgmPoolTrackUpdateGCPhys(pVM, paPageDesc[i].GCPhys, pPage, true /* clear the entries */, &fFlush);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Assert(rc == VINF_SUCCESS || (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3) && (pVCpu->pgm.s.fSyncFlags & PGM_SYNC_CLEAR_PGM_POOL)));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* Update the physical address and page id now. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync PGM_PAGE_SET_PAGEID(pPage, paPageDesc[i].uHCPhysPageId);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* Invalidate page map TLB entry for this page too. */
end:
if (fFlushTLBs)
if (paPageDesc)
return rc;