PGMPhys.cpp revision 5969f9efb5f9270423119822c084afe6c67d3ade
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * PGM - Page Manager and Monitor, Physical Memory Addressing.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * available from http://www.virtualbox.org. This file is free software;
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * 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.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * additional information or have any questions.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync/*******************************************************************************
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync* Header Files *
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync*******************************************************************************/
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync/*******************************************************************************
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync* Internal Functions *
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync*******************************************************************************/
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync/*static - shut up warning */
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsyncDECLCALLBACK(int) pgmR3PhysRomWriteHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser);
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * PGMR3PhysReadU8-64
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * PGMR3PhysWriteU8-64
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * Links a new RAM range into the list.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param pVM Pointer to the shared VM structure.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param pNew Pointer to the new list entry.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param pPrev Pointer to the previous list entry. If NULL, insert as head.
31cda52093d58f5c604589fa74949c5fddcbde70vboxsyncstatic void pgmR3PhysLinkRamRange(PVM pVM, PPGMRAMRANGE pNew, PPGMRAMRANGE pPrev)
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync PPGMRAMRANGE pRam = pPrev ? pPrev->pNextR3 : pVM->pgm.s.pRamRangesR3;
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync pNew->pNextR0 = pRam ? MMHyperCCToR0(pVM, pRam) : NIL_RTR0PTR;
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync pNew->pNextRC = pRam ? MMHyperCCToRC(pVM, pRam) : NIL_RTRCPTR;
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync pVM->pgm.s.pRamRangesR0 = MMHyperCCToR0(pVM, pNew);
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync pVM->pgm.s.pRamRangesRC = MMHyperCCToRC(pVM, pNew);
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync * Unlink an existing RAM range from the list.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param pVM Pointer to the shared VM structure.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param pRam Pointer to the new list entry.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param pPrev Pointer to the previous list entry. If NULL, insert as head.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsyncstatic void pgmR3PhysUnlinkRamRange2(PVM pVM, PPGMRAMRANGE pRam, PPGMRAMRANGE pPrev)
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync Assert(pPrev ? pPrev->pNextR3 == pRam : pVM->pgm.s.pRamRangesR3 == pRam);
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync pPrev->pNextR0 = pNext ? MMHyperCCToR0(pVM, pNext) : NIL_RTR0PTR;
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync pPrev->pNextRC = pNext ? MMHyperCCToRC(pVM, pNext) : NIL_RTRCPTR;
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync pVM->pgm.s.pRamRangesR0 = pNext ? MMHyperCCToR0(pVM, pNext) : NIL_RTR0PTR;
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync pVM->pgm.s.pRamRangesRC = pNext ? MMHyperCCToRC(pVM, pNext) : NIL_RTRCPTR;
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * Unlink an existing RAM range from the list.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param pVM Pointer to the shared VM structure.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param pRam Pointer to the new list entry.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsyncstatic void pgmR3PhysUnlinkRamRange(PVM pVM, PPGMRAMRANGE pRam)
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync /* find prev. */
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * Sets up a range RAM.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * This will check for conflicting registrations, make a resource
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * reservation for the memory (with GMM), and setup the per-page
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * tracking structures (PGMPAGE).
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @returns VBox stutus code.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param pVM Pointer to the shared VM structure.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param GCPhys The physical address of the RAM.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param cb The size of the RAM.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param pszDesc The description - not copied, so, don't free or change it.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsyncVMMR3DECL(int) PGMR3PhysRegisterRam(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, const char *pszDesc)
c5d2523548cc57504b829f53f1362b848a84542cvboxsync * Validate input.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync Log(("PGMR3PhysRegisterRam: GCPhys=%RGp cb=%RGp pszDesc=%s\n", GCPhys, cb, pszDesc));
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync AssertReturn(RT_ALIGN_T(GCPhys, PAGE_SIZE, RTGCPHYS) == GCPhys, VERR_INVALID_PARAMETER);
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync AssertReturn(RT_ALIGN_T(cb, PAGE_SIZE, RTGCPHYS) == cb, VERR_INVALID_PARAMETER);
c5d2523548cc57504b829f53f1362b848a84542cvboxsync AssertMsgReturn(GCPhysLast > GCPhys, ("The range wraps! GCPhys=%RGp cb=%RGp\n", GCPhys, cb), VERR_INVALID_PARAMETER);
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * Find range location and check for conflicts.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * (We don't lock here because the locking by EMT is only required on update.)
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync AssertLogRelMsgFailedReturn(("%RGp-%RGp (%s) conflicts with existing %RGp-%RGp (%s)\n",
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * Register it with GMM (the API bitches).
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * Allocate RAM range.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync const size_t cbRamRange = RT_OFFSETOF(PGMRAMRANGE, aPages[cPages]);
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync rc = MMR3HyperAllocOnceNoRel(pVM, cbRamRange, 0, MM_TAG_PGM_PHYS, (void **)&pNew);
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync AssertLogRelMsgRCReturn(rc, ("cbRamRange=%zu\n", cbRamRange), rc);
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * Initialize the range.
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync /* Allocate memory for chunk to HC ptr lookup array. */
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync rc = MMHyperAlloc(pVM, (cb >> PGM_DYNAMIC_CHUNK_SHIFT) * sizeof(void *), 16, MM_TAG_PGM, (void **)&pNew->paChunkR3Ptrs);
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync while (iPage-- > 0)
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync PGM_PAGE_INIT_ZERO(&pNew->aPages[iPage], pVM, PGMPAGETYPE_RAM);
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync * Insert the new RAM range.
fa7c9928985ad8dc74ae6931809083c2af135250vboxsync * Notify REM.
fa7c9928985ad8dc74ae6931809083c2af135250vboxsync REMR3NotifyPhysRamRegister(pVM, GCPhys, cb, MM_RAM_FLAGS_DYNAMIC_ALLOC);
fa7c9928985ad8dc74ae6931809083c2af135250vboxsync * Resets (zeros) the RAM.
fa7c9928985ad8dc74ae6931809083c2af135250vboxsync * ASSUMES that the caller owns the PGM lock.
fa7c9928985ad8dc74ae6931809083c2af135250vboxsync * @returns VBox status code.
fa7c9928985ad8dc74ae6931809083c2af135250vboxsync * @param pVM Pointer to the shared VM structure.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * Walk the ram ranges.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync for (PPGMRAMRANGE pRam = pVM->pgm.s.pRamRangesR3; pRam; pRam = pRam->pNextR3)
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync uint32_t iPage = pRam->cb >> PAGE_SHIFT; Assert((RTGCPHYS)iPage << PAGE_SHIFT == pRam->cb);
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync /* Replace all RAM pages by ZERO pages. */
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync while (iPage-- > 0)
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync pgmPhysFreePage(pVM, pPage, pRam->GCPhys + ((RTGCPHYS)i << PAGE_SHIFT));
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync case PGMPAGETYPE_ROM_SHADOW: /* handled by pgmR3PhysRomReset. */
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync } /* for each page */
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync /* Zero the memory. */
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync while (iPage-- > 0)
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync if (pRam->aPages[iPage].HCPhys & (MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_ROM | MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_MMIO2)) /** @todo PAGE FLAGS */
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync /* shadow ram is reloaded elsewhere. */
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync Log4(("PGMR3Reset: not clearing phys page %RGp due to flags %RHp\n", pRam->GCPhys + (iPage << PAGE_SHIFT), pRam->aPages[iPage].HCPhys & (MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_ROM | MM_RAM_FLAGS_MMIO))); /** @todo PAGE FLAGS */
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync unsigned iChunk = iPage >> (PGM_DYNAMIC_CHUNK_SHIFT - PAGE_SHIFT);
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync ASMMemZero32((char *)pRam->paChunkR3Ptrs[iChunk] + ((iPage << PAGE_SHIFT) & PGM_DYNAMIC_CHUNK_OFFSET_MASK), PAGE_SIZE);
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync ASMMemZero32((char *)pRam->pvR3 + (iPage << PAGE_SHIFT), PAGE_SIZE);
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync#else /* VBOX_WITH_NEW_PHYS_CODE */
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync rc = pgmPhysPageMakeWritable(pVM, pPage, pRam->GCPhys + ((RTGCPHYS)i << PAGE_SHIFT));
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync rc = pgmPhysPageMap(pVM, pPage, pRam->GCPhys + ((RTGCPHYS)i << PAGE_SHIFT), &pMapIgnored, &pvPage);
c5d2523548cc57504b829f53f1362b848a84542cvboxsync#endif /* VBOX_WITH_NEW_PHYS_CODE */
c5d2523548cc57504b829f53f1362b848a84542cvboxsync } /* for each page */
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * This is the interface IOM is using to register an MMIO region.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * It will check for conflicts and ensure that a RAM range structure
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * is present before calling the PGMR3HandlerPhysicalRegister API to
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * register the callbacks.
38d78a770c90320c1f6da7ae2f3fa58a28b37189vboxsync * @returns VBox status code.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param pVM Pointer to the shared VM structure.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param GCPhys The start of the MMIO region.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param cb The size of the MMIO region.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param pfnHandlerR3 The address of the ring-3 handler. (IOMR3MMIOHandler)
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param pvUserR3 The user argument for R3.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param pfnHandlerR0 The address of the ring-0 handler. (IOMMMIOHandler)
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param pvUserR0 The user argument for R0.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param pfnHandlerRC The address of the RC handler. (IOMMMIOHandler)
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param pvUserRC The user argument for RC.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * @param pszDesc The description of the MMIO region.
c5d2523548cc57504b829f53f1362b848a84542cvboxsyncVMMR3DECL(int) PGMR3PhysMMIORegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb,
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync R3PTRTYPE(PFNPGMR3PHYSHANDLER) pfnHandlerR3, RTR3PTR pvUserR3,
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync R0PTRTYPE(PFNPGMR0PHYSHANDLER) pfnHandlerR0, RTR0PTR pvUserR0,
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync RCPTRTYPE(PFNPGMRCPHYSHANDLER) pfnHandlerRC, RTRCPTR pvUserRC,
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * Assert on some assumption.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync AssertReturn(!(cb & PAGE_OFFSET_MASK), VERR_INVALID_PARAMETER);
fbb3513a43135c633f7f51544c4bdfce748929bfvboxsync AssertReturn(!(GCPhys & PAGE_OFFSET_MASK), VERR_INVALID_PARAMETER);
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * Make sure there's a RAM range structure for the region.
fbb3513a43135c633f7f51544c4bdfce748929bfvboxsync bool fRamExists = false;
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync /* Simplification: all within the same range. */
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync ("%RGp-%RGp (MMIO/%s) falls partly outside %RGp-%RGp (%s)\n",
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync /* Check that it's all RAM or MMIO pages. */
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync PCPGMPAGE pPage = &pRam->aPages[(GCPhys - pRam->GCPhys) >> PAGE_SHIFT];
c5d2523548cc57504b829f53f1362b848a84542cvboxsync while (cLeft-- > 0)
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync AssertLogRelMsgReturn( PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_RAM
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync ("%RGp-%RGp (MMIO/%s): %RGp is not a RAM or MMIO page - type=%d desc=%s\n",
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync GCPhys, GCPhysLast, pszDesc, PGM_PAGE_GET_TYPE(pPage), pRam->pszDesc),
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync /* Looks good. */
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * No RAM range, insert an ad-hoc one.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * Note that we don't have to tell REM about this range because
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync * PGMHandlerPhysicalRegisterEx will do that for us.
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync Log(("PGMR3PhysMMIORegister: Adding ad-hoc MMIO range for %RGp-%RGp %s\n", GCPhys, GCPhysLast, pszDesc));
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync const size_t cbRamRange = RT_OFFSETOF(PGMRAMRANGE, aPages[cPages]);
833f83ce101b6e9168f519decc0dc7a1079d35f7vboxsync rc = MMHyperAlloc(pVM, RT_OFFSETOF(PGMRAMRANGE, aPages[cPages]), 16, MM_TAG_PGM_PHYS, (void **)&pNew);
b4f03aea544c9a58d8959658b31f7bd716a3f097vboxsync AssertLogRelMsgRCReturn(rc, ("cbRamRange=%zu\n", cbRamRange), rc);
while (iPage-- > 0)
&& !fRamExists)
return rc;
bool fAllMMIO = true;
while (cLeft-- > 0)
fAllMMIO = false;
pPage++;
if (fAllMMIO)
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)
return rc;
void *pvPages;
while (iPage-- > 0)
return VINF_SUCCESS;
return rc;
unsigned cFound = 0;
while (pCur)
cFound++;
if (pPrev)
rc2 = MMR3AdjustFixedReservation(pVM, -(int32_t)(pCur->RamRange.cb >> PAGE_SHIFT), pCur->RamRange.pszDesc);
bool fRamExists = false;
fRamExists = true;
if (fRamExists)
while (cPagesLeft-- > 0)
pPage++;
if (fRamExists)
while (cPagesLeft-- > 0)
pPageSrc++;
pPageDst++;
return VINF_SUCCESS;
#ifdef RT_STRICT
while (cPagesLeft-- > 0)
pPageDst++;
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_FLAG_SHADOWED | PGMPHYS_ROM_FLAG_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 (pRamNew)
return rc;
DECLCALLBACK(int) pgmR3PhysRomWriteHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser)
return VINF_SUCCESS;
return rc;
void *pvDstPage;
return rc;
while (iPage-- > 0)
cDirty++;
if (cDirty)
iReqPage++;
void *pvDstPage;
#ifdef VBOX_STRICT
void *pvDstPage;
return VINF_SUCCESS;
if (!cb)
return VINF_SUCCESS;
bool fFlushedPool = false;
bool fChanges = false;
iPage++)
fChanges = true;
if (!fFlushedPool)
fFlushedPool = true;
if (fChanges)
return VINF_SUCCESS;
VMMR3DECL(int) PGMR3PhysRegister(PVM pVM, void *pvRam, RTGCPHYS GCPhys, size_t cb, unsigned fFlags, const SUPPAGE *paPages, const char *pszDesc)
Assert((fFlags & (MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_DYNAMIC_ALLOC)) || paPages);
Assert((fFlags == (MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_MMIO)) || (fFlags & MM_RAM_FLAGS_DYNAMIC_ALLOC) || pvRam);
Assert(!(fFlags & ~(MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_ROM | MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_MMIO2 | MM_RAM_FLAGS_DYNAMIC_ALLOC)));
return VERR_INVALID_PARAMETER;
while (pCur)
return VERR_PGM_RAM_CONFLICT;
if (paPages)
while (iPage-- > 0)
rc = MMHyperAlloc(pVM, (cb >> PGM_DYNAMIC_CHUNK_SHIFT) * sizeof(void *), 16, MM_TAG_PGM, (void **)&pNew->paChunkR3Ptrs);
while (iPage-- > 0)
while (iPage-- > 0)
PGM_PAGE_INIT(&pNew->aPages[iPage], HCPhysDummyPage, NIL_GMM_PAGEID, PGMPAGETYPE_MMIO, PGM_PAGE_STATE_ZERO);
if (pPrev)
return rc;
#ifndef VBOX_WITH_NEW_PHYS_CODE
VMMR3DECL(int) PGMR3PhysRegisterChunk(PVM pVM, void *pvRam, RTGCPHYS GCPhys, size_t cb, unsigned fFlags, const SUPPAGE *paPages, const char *pszDesc)
Assert(!(fFlags & ~(MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_ROM | MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_MMIO2 | MM_RAM_FLAGS_DYNAMIC_ALLOC)));
return VERR_INVALID_PARAMETER;
while (pRam)
if (paPages)
while (iPage-- > 0)
pRam->aPages[off + iPage].HCPhys = (paPages[iPage].Phys & X86_PTE_PAE_PG_MASK) | fFlags; /** @todo PAGE FLAGS */
return VINF_SUCCESS;
while (pRam)
bool fRangeExists = false;
/* Note: A request made from another thread may end up in EMT after somebody else has already allocated the range. */
fRangeExists = true;
if (fRangeExists)
return VINF_SUCCESS;
void *pvRam;
int rc;
AssertMsg(!PDMCritSectIsOwner(&pVM->pgm.s.CritSect), ("We own the PGM lock -> deadlock danger!!\n"));
rc = VMR3ReqCall(pVM, VMREQDEST_ANY, &pReq, RT_INDEFINITE_WAIT, (PFNRT)PGM3PhysGrowRange, 2, pVM, &GCPhysParam);
return rc;
rc = MMR3PhysRegisterEx(pVM, pvRam, GCPhys, PGM_DYNAMIC_CHUNK_SIZE, 0, MM_PHYS_TYPE_DYNALLOC_CHUNK, "Main Memory");
return rc;
LogRel(("PGM: Out of memory while trying to allocate a guest RAM chunk at %RGp (VMstate=%s)!\n", GCPhys, VMR3GetStateName(enmVMState)));
return rc;
VMSetRuntimeError(pVM, false, "HostMemoryLow", "Unable to allocate and lock memory. The virtual machine will be paused. Please close applications to free up memory or close the VM");
/* Wait for resume event; will only return in that case. If the VM is stopped, the EMT thread will be destroyed. */
VMMR3DECL(int) PGMR3PhysSetFlags(PVM pVM, RTGCPHYS GCPhys, size_t cb, unsigned fFlags, unsigned fMask)
* (Not so important because caller is always MMR3RomRegister() and MMR3PhysReserve(), but anyway...)
Assert(!(fFlags & ~(MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_ROM | MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_MMIO2)));
if ( !pRam
return VERR_INVALID_PARAMETER;
RTHCPHYS fFullMask = ~(RTHCPHYS)(MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_ROM | MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_MMIO2)
| fMask;
pRam->aPages[iPage].HCPhys = (pRam->aPages[iPage].HCPhys & fFullMask) | fFlags; /** @todo PAGE FLAGS */
return VINF_SUCCESS;
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;
PPGMCHUNKR3MAP pChunk = (PPGMCHUNKR3MAP)MMR3HeapAlloc(pVM, MM_TAG_PGM_CHUNK_MAPPING, sizeof(*pChunk));
PPGMCHUNKR3MAP pUnmappedChunk = (PPGMCHUNKR3MAP)RTAvlU32Remove(&pVM->pgm.s.ChunkR3Map.pTree, Req.idChunkUnmap);
return rc;
void *pvChunk;
return rc;
#if 0 /** @todo looks like the system ROM is registered incorrectly, 0xfe000 claims to be a zero page. */
rc = VERR_PGM_PHYS_TLB_UNASSIGNED; /** @todo VBOX_WITH_NEW_PHYS_CODE: remap it to a writeable page. */
AssertMsg(PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_RAM, ("GCPhys=%RGp type=%d\n", GCPhys, PGM_PAGE_GET_TYPE(pPage)));
AssertMsg(PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_RAM || PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_MMIO2, ("GCPhys=%RGp type=%d\n", GCPhys, PGM_PAGE_GET_TYPE(pPage)));
return rc;