PGMPhys.cpp revision 6df00073ea59fecb0201aa42d8c3fccbe48ca10f
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * PGM - Page Manager and Monitor, Physical Memory Addressing.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * available from http://www.virtualbox.org. This file is free software;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * you can redistribute it and/or modify it under the terms of the GNU
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * General Public License (GPL) as published by the Free Software
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * additional information or have any questions.
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync/*******************************************************************************
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync* Header Files *
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync*******************************************************************************/
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/*******************************************************************************
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync* Defined Constants And Macros *
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync*******************************************************************************/
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/** The number of pages to free in one batch. */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/*******************************************************************************
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync* Internal Functions *
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync*******************************************************************************/
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncstatic DECLCALLBACK(int) pgmR3PhysRomWriteHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncstatic int pgmPhysFreePage(PVM pVM, PGMMFREEPAGESREQ pReq, uint32_t *pcPendingPages, PPGMPAGE pPage, RTGCPHYS GCPhys);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * PGMR3PhysReadU8-64
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * PGMR3PhysWriteU8-64
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * EMT worker for PGMR3PhysReadExternal.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncstatic DECLCALLBACK(int) pgmR3PhysReadExternalEMT(PVM pVM, PRTGCPHYS pGCPhys, void *pvBuf, size_t cbRead)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Write to physical memory, external users.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @returns VBox status code.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @retval VINF_SUCCESS.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @param pVM VM Handle.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @param GCPhys Physical address to write to.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @param pvBuf What to write.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @param cbWrite How many bytes to write.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @thread Any but EMTs.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncVMMR3DECL(int) PGMR3PhysReadExternal(PVM pVM, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync AssertMsgReturn(cbRead > 0, ("don't even think about reading zero bytes!\n"), VINF_SUCCESS);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync LogFlow(("PGMR3PhysReadExternal: %RGp %d\n", GCPhys, cbRead));
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Copy loop on ram ranges.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync PPGMRAMRANGE pRam = pVM->pgm.s.CTX_SUFF(pRamRanges);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync /* Find range. */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync /* Inside range or not? */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Must work our way thru this page by page.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * If the page has an ALL access handler, we'll have to
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * delegate the job to EMT.
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)pgmR3PhysReadExternalEMT, 4,
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * Simple stuff, go ahead.
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync const void *pvSrc;
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync int rc = pgmPhysGCPhys2CCPtrInternalReadOnly(pVM, pPage, pRam->GCPhys + off, &pvSrc);
2bb12e589d2c280ad042e4e70635ae7224c7eceevboxsync AssertLogRelMsgFailed(("pgmPhysGCPhys2CCPtrInternalReadOnly failed on %RGp / %R[pgmpage] -> %Rrc\n",
044af0d1e6474076366759db86f101778c5f20ccvboxsync /* next page */
044af0d1e6474076366759db86f101778c5f20ccvboxsync } /* walk pages in ram range. */
044af0d1e6474076366759db86f101778c5f20ccvboxsync LogFlow(("PGMPhysRead: Unassigned %RGp size=%u\n", GCPhys, cbRead));
044af0d1e6474076366759db86f101778c5f20ccvboxsync * Unassigned address space.
044af0d1e6474076366759db86f101778c5f20ccvboxsync } /* Ram range walk */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * EMT worker for PGMR3PhysWriteExternal.
172ae196da38208e5f1e3485715a89f2d53c6880vboxsyncstatic DECLCALLBACK(int) pgmR3PhysWriteExternalEMT(PVM pVM, PRTGCPHYS pGCPhys, const void *pvBuf, size_t cbWrite)
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync /** @todo VERR_EM_NO_MEMORY */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * Write to physical memory, external users.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @returns VBox status code.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @retval VINF_SUCCESS.
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync * @retval VERR_EM_NO_MEMORY.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @param pVM VM Handle.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @param GCPhys Physical address to write to.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @param pvBuf What to write.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @param cbWrite How many bytes to write.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @thread Any but EMTs.
044af0d1e6474076366759db86f101778c5f20ccvboxsyncVMMDECL(int) PGMR3PhysWriteExternal(PVM pVM, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
044af0d1e6474076366759db86f101778c5f20ccvboxsync AssertMsg(!pVM->pgm.s.fNoMorePhysWrites, ("Calling PGMR3PhysWriteExternal after pgmR3Save()!\n"));
044af0d1e6474076366759db86f101778c5f20ccvboxsync AssertMsgReturn(cbWrite > 0, ("don't even think about writing zero bytes!\n"), VINF_SUCCESS);
044af0d1e6474076366759db86f101778c5f20ccvboxsync LogFlow(("PGMR3PhysWriteExternal: %RGp %d\n", GCPhys, cbWrite));
044af0d1e6474076366759db86f101778c5f20ccvboxsync * Copy loop on ram ranges, stop when we hit something difficult.
044af0d1e6474076366759db86f101778c5f20ccvboxsync PPGMRAMRANGE pRam = pVM->pgm.s.CTX_SUFF(pRamRanges);
044af0d1e6474076366759db86f101778c5f20ccvboxsync /* Find range. */
a1df400bbe9d64aad400442e56eb637019300a5evboxsync /* Inside range or not? */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Must work our way thru this page by page.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * It the page is in any way problematic, we have to
a1df400bbe9d64aad400442e56eb637019300a5evboxsync * do the work on the EMT. Anything that needs to be made
a1df400bbe9d64aad400442e56eb637019300a5evboxsync * writable or involves access handlers is problematic.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync || PGM_PAGE_GET_STATE(pPage) != PGM_PAGE_STATE_ALLOCATED)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync return VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)pgmR3PhysWriteExternalEMT, 4,
044af0d1e6474076366759db86f101778c5f20ccvboxsync * Simple stuff, go ahead.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync int rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, pRam->GCPhys + off, &pvDst);
a1df400bbe9d64aad400442e56eb637019300a5evboxsync AssertLogRelMsgFailed(("pgmPhysGCPhys2CCPtrInternal failed on %RGp / %R[pgmpage] -> %Rrc\n",
044af0d1e6474076366759db86f101778c5f20ccvboxsync /* next page */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync } /* walk pages in ram range */
044af0d1e6474076366759db86f101778c5f20ccvboxsync * Unassigned address space, skip it.
044af0d1e6474076366759db86f101778c5f20ccvboxsync } /* Ram range walk */
044af0d1e6474076366759db86f101778c5f20ccvboxsync * VMR3ReqCall worker for PGMR3PhysGCPhys2CCPtrExternal to make pages writable.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @returns see PGMR3PhysGCPhys2CCPtrExternal
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @param pVM The VM handle.
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * @param pGCPhys Pointer to the guest physical address.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @param ppv Where to store the mapping address.
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * @param pLock Where to store the lock.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncstatic DECLCALLBACK(int) pgmR3PhysGCPhys2CCPtrDelegated(PVM pVM, PRTGCPHYS pGCPhys, void **ppv, PPGMPAGEMAPLOCK pLock)
044af0d1e6474076366759db86f101778c5f20ccvboxsync * Just hand it to PGMPhysGCPhys2CCPtr and check that it's not a page with
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * an access handler after it succeeds.
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync rc = PGMPhysGCPhys2CCPtr(pVM, *pGCPhys, ppv, pLock);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync int rc2 = pgmPhysPageQueryTlbe(&pVM->pgm.s, *pGCPhys, &pTlbe);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync /* We *must* flush any corresponding pgm pool page here, otherwise we'll
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * not be informed about writes and keep bogus gst->shw mappings around.
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync /** @todo r=bird: return VERR_PGM_PHYS_PAGE_RESERVED here if it still has
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync * active handlers, see the PGMR3PhysGCPhys2CCPtrExternal docs. */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * Requests the mapping of a guest page into ring-3, external threads.
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync * When you're done with the page, call PGMPhysReleasePageMappingLock() ASAP to
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync * release it.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * This API will assume your intention is to write to the page, and will
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync * therefore replace shared and zero pages. If you do not intend to modify the
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * page, use the PGMR3PhysGCPhys2CCPtrReadOnlyExternal() API.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @returns VBox status code.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @retval VINF_SUCCESS on success.
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync * @retval VERR_PGM_PHYS_PAGE_RESERVED it it's a valid page but has no physical
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * backing or if the page has any active access handlers. The caller
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync * must fall back on using PGMR3PhysWriteExternal.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if it's not a valid physical address.
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync * @param pVM The VM handle.
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync * @param GCPhys The guest physical address of the page that should be mapped.
172ae196da38208e5f1e3485715a89f2d53c6880vboxsync * @param ppv Where to store the address corresponding to GCPhys.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @param pLock Where to store the lock information that PGMPhysReleasePageMappingLock needs.
72a6fe3989272cb2d409b50caca25e1edbca9398vboxsync * @remark Avoid calling this API from within critical sections (other than the
7af218a7441de38fc9e814919db04bae3e917664vboxsync * PGM one) because of the deadlock risk when we have to delegating the
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * task to an EMT.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @thread Any.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncVMMR3DECL(int) PGMR3PhysGCPhys2CCPtrExternal(PVM pVM, RTGCPHYS GCPhys, void **ppv, PPGMPAGEMAPLOCK pLock)
if (pMap)
# ifdef PGM_PAGE_WITH_LOCKS
if (pMap)
return rc;
VMMR3DECL(int) PGMR3PhysGCPhys2CCPtrReadOnlyExternal(PVM pVM, RTGCPHYS GCPhys, void const **ppv, PPGMPAGEMAPLOCK pLock)
if (pMap)
# ifdef PGM_PAGE_WITH_LOCKS
AssertMsgFailed(("%RGp / %R[pgmpage] is entering permanent readonly locked state!\n", GCPhys, pPage));
if (pMap)
return rc;
#ifdef VBOX_STRICT
if (pCur)
if (pPrev)
if (pPrev)
static int pgmR3PhysFreePageRange(PVM pVM, PPGMRAMRANGE pRam, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast, uint8_t uType)
while (cPagesLeft-- > 0)
pPageDst++;
if (cPendingPages)
return rc;
static void pgmR3PhysInitAndLinkRamRange(PVM pVM, PPGMRAMRANGE pNew, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast,
while (iPage-- > 0)
static DECLCALLBACK(bool) pgmR3PhysRamRangeRelocate(PVM pVM, RTGCPTR GCPtrOld, RTGCPTR GCPtrNew, PGMRELOCATECALL enmMode, void *pvUser)
switch (enmMode)
case PGMRELOCATECALL_SUGGEST:
case PGMRELOCATECALL_RELOCATE:
AssertFailedReturn(false);
? pszDesc
size_t const cChunkPages = RT_ALIGN_Z(RT_UOFFSETOF(PGMRAMRANGE, aPages[cRamPages]), PAGE_SIZE) >> PAGE_SHIFT;
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
NULL,
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
rc = PGMR3MapPT(pVM, GCPtrChunkMap, cbChunk, 0 /*fFlags*/, pgmR3PhysRamRangeRelocate, pNew, pszDescChunk);
return rc;
AssertMsgReturn(GCPhysLast > GCPhys, ("The range wraps! GCPhys=%RGp cb=%RGp\n", GCPhys, cb), VERR_INVALID_PARAMETER);
return rc;
while (cPagesLeft > 0)
rc = pgmR3PhysRegisterHighRamChunk(pVM, GCPhysChunk, cPagesInChunk, cbChunk, iChunk, pszDesc, &pPrev);
iChunk++;
pgmR3PhysInitAndLinkRamRange(pVM, pNew, GCPhys, GCPhysLast, NIL_RTRCPTR, NIL_RTR0PTR, pszDesc, pPrev);
return VINF_SUCCESS;
while (cLeft-- > 0)
case PGM_PAGE_STATE_ZERO:
LogRel(("PGM: RAM Pre-allocation failed at %RGp (in %s) with rc=%Rrc\n", GCPhys, pRam->pszDesc, rc));
return rc;
cPages++;
case PGM_PAGE_STATE_ALLOCATED:
case PGM_PAGE_STATE_SHARED:
pPage++;
return VINF_SUCCESS;
AssertMsg(((RTGCPHYS)iPage << PAGE_SHIFT) == pRam->cb, ("%RGp %RGp\n", (RTGCPHYS)iPage << PAGE_SHIFT, pRam->cb));
while (iPage-- > 0)
case PGMPAGETYPE_RAM:
rc = pgmPhysFreePage(pVM, pReq, &cPendingPages, pPage, pRam->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT));
case PGMPAGETYPE_MMIO2:
case PGMPAGETYPE_ROM:
case PGMPAGETYPE_MMIO:
AssertFailed();
while (iPage-- > 0)
case PGMPAGETYPE_RAM:
case PGM_PAGE_STATE_ZERO:
case PGM_PAGE_STATE_SHARED:
case PGM_PAGE_STATE_ALLOCATED:
void *pvPage;
case PGMPAGETYPE_MMIO2:
case PGMPAGETYPE_ROM_SHADOW:
case PGMPAGETYPE_ROM:
case PGMPAGETYPE_MMIO:
AssertFailed();
if (cPendingPages)
return VINF_SUCCESS;
int rc;
bool fRamExists = false;
while (cLeft-- > 0)
pPage++;
fRamExists = true;
if (fRamExists)
Log(("PGMR3PhysMMIORegister: Adding ad hoc MMIO range for %RGp-%RGp %s\n", GCPhys, GCPhysLast, pszDesc));
rc = MMHyperAlloc(pVM, RT_OFFSETOF(PGMRAMRANGE, aPages[cPages]), 16, MM_TAG_PGM_PHYS, (void **)&pNew);
while (iPage-- > 0)
&& !fRamExists)
return rc;
bool fAllMMIO = true;
while (cLeft-- > 0)
fAllMMIO = false;
pPage++;
if (fAllMMIO)
* Range match? It will all be within one range (see PGMAllHandler.cpp).
while (cLeft--)
AssertMsg(PGM_PAGE_IS_MMIO(pPage), ("%RGp %R[pgmpage]\n", pRam->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT), pPage));
AssertMsg(PGM_PAGE_IS_ZERO(pPage), ("%RGp %R[pgmpage]\n", pRam->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT), pPage));
return rc;
return pCur;
return NULL;
VMMR3DECL(int) PGMR3PhysMMIO2Register(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc)
if (!pszDesc)
return VERR_NO_MEMORY;
void *pvPages;
while (iPage-- > 0)
return VINF_SUCCESS;
return rc;
unsigned cFound = 0;
while (pCur)
cFound++;
if (pPrev)
#ifdef VBOX_STRICT
bool fRamExists = false;
fRamExists = true;
if (fRamExists)
while (cPagesLeft-- > 0)
pPage++;
if (fRamExists)
while (cPagesLeft-- > 0)
pPageSrc++;
pPageDst++;
if (cPendingPages)
return VINF_SUCCESS;
bool fInformREM;
while (cPagesLeft-- > 0)
pPageDst++;
fInformREM = false;
fInformREM = true;
if (fInformREM)
return VINF_SUCCESS;
VMMR3DECL(int) PGMR3PhysMMIO2GetHCPhys(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, PRTHCPHYS pHCPhys)
return VINF_SUCCESS;
VMMR3DECL(int) PGMR3PhysMMIO2MapKernel(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb,
return rc;
Log(("PGMR3PhysRomRegister: pDevIns=%p GCPhys=%RGp(-%RGp) cb=%RGp pvBinary=%p fFlags=%#x pszDesc=%s\n",
AssertReturn(!(fFlags & ~(PGMPHYS_ROM_FLAGS_SHADOWED | PGMPHYS_ROM_FLAGS_PERMANENT_BINARY)), VERR_INVALID_PARAMETER);
bool fRamExists = false;
fRamExists = true;
if (fRamExists)
while (cPagesLeft-- > 0)
pPage++;
if (cExtraBaseCost)
return rc;
return rc;
rc = MMHyperAlloc(pVM, RT_OFFSETOF(PGMROMRANGE, aPages[cPages]), 0, MM_TAG_PGM_PHYS, (void **)&pRomNew);
if (!fRamExists)
rc = MMHyperAlloc(pVM, RT_OFFSETOF(PGMRAMRANGE, aPages[cPages]), sizeof(PGMPAGE), MM_TAG_PGM_PHYS, (void **)&pRamNew);
if (!fRamExists)
void *pvDstPage;
if (pRomPrev)
return VINF_SUCCESS;
if (!fRamExists)
return rc;
static DECLCALLBACK(int) pgmR3PhysRomWriteHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser)
Log5(("pgmR3PhysRomWriteHandler: %d %c %#08RGp %#04zx\n", pRomPage->enmProt, enmAccessType == PGMACCESSTYPE_READ ? 'R' : 'W', GCPhys, cbBuf));
return VINF_PGM_HANDLER_DO_DEFAULT;
return VINF_SUCCESS;
void *pvDstPage;
return rc;
rc = pgmPhysFreePage(pVM, pReq, &cPendingPages, &pRom->aPages[iPage].Shadow, pRom->GCPhys + (iPage << PAGE_SHIFT));
if (cPendingPages)
void *pvDstPage;
#ifdef VBOX_STRICT
void const *pvDstPage;
return VINF_SUCCESS;
if (!cb)
return VINF_SUCCESS;
bool fFlushTLB = false;
bool fChanges = false;
iPage++)
fChanges = true;
if (fChanges)
return rc;
if (fFlushTLB)
return rc;
RTAvlU32DoWithAll(&pVM->pgm.s.ChunkR3Map.pTree, true /*fFromLeft*/, pgmR3PhysChunkAgeingRolloverCallback, pVM);
RTAvlU32DoWithAll(&pVM->pgm.s.ChunkR3Map.pTree, true /*fFromLeft*/, pgmR3PhysChunkAgeingCallback, pVM);
typedef struct PGMR3PHYSCHUNKUNMAPCB
if (pChunk)
if (pChunk)
/* next with the same age - this version of the AVL API doesn't enumerate the list, so we have to do it. */
} while (pNode);
if (RTAvllU32DoWithAll(&pVM->pgm.s.ChunkR3Map.pAgeTree, true /*fFromLeft*/, pgmR3PhysChunkUnmapCandidateCallback, pVM))
return INT32_MAX;
int rc;
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
PPGMCHUNKR3MAP pChunk = (PPGMCHUNKR3MAP)MMR3HeapAlloc(pVM, MM_TAG_PGM_CHUNK_MAPPING, sizeof(*pChunk));
PPGMCHUNKR3MAP pChunk = (PPGMCHUNKR3MAP)MMR3UkHeapAlloc(pVM, MM_TAG_PGM_CHUNK_MAPPING, sizeof(*pChunk), NULL);
PPGMCHUNKR3MAP pUnmappedChunk = (PPGMCHUNKR3MAP)RTAvlU32Remove(&pVM->pgm.s.ChunkR3Map.pTree, Req.idChunkUnmap);
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
return rc;
int rc;
return rc;
* in EM.cpp and shouldn't be propagated outside TRPM, HWACCM, EM and
AssertMsgReturn(iClear <= RT_ELEMENTS(pVM->pgm.s.aHandyPages), ("%d", iClear), VERR_INTERNAL_ERROR);
void *pvChunk;
void *pv;
AssertLogRelMsgBreak(RT_SUCCESS(rc), ("idPage=%#x HCPhysGCPhys=%RHp rc=%Rrc", pPage->idPage, pPage->HCPhysGCPhys, rc));
iClear++;
Log3(("PGMR3PhysAllocateHandyPages: idPage=%#x HCPhys=%RGp\n", pPage->idPage, pPage->HCPhysGCPhys));
pRam;
return rc;
static int pgmPhysFreePage(PVM pVM, PGMMFREEPAGESREQ pReq, uint32_t *pcPendingPages, PPGMPAGE pPage, RTGCPHYS GCPhys)
return VMSetError(pVM, VERR_PGM_PHYS_NOT_RAM, RT_SRC_POS, "GCPhys=%RGp type=%d", GCPhys, PGM_PAGE_GET_TYPE(pPage));
return VINF_SUCCESS;
return VMSetError(pVM, VERR_PGM_PHYS_INVALID_PAGE_ID, RT_SRC_POS, "GCPhys=%RGp idPage=%#x", GCPhys, pPage);
return VINF_SUCCESS;
*pcPendingPages = 0;
return rc;
/** @todo Handle TLB loads of virtual handlers so ./test.sh can be made to work
if (fWritable)
int rc2;
case PGM_PAGE_STATE_ALLOCATED:
case PGM_PAGE_STATE_ZERO:
case PGM_PAGE_STATE_SHARED:
Log6(("PGMR3PhysTlbGCPhys2Ptr: GCPhys=%RGp rc=%Rrc pPage=%R[pgmpage] *ppv=%p\n", GCPhys, rc, pPage, *ppv));
return rc;