PGMAllHandler.cpp revision c3447567c90bea0102b6decbaea688efbb47ff84
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * PGM - Page Manager / Monitor, Access Handlers.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * available from http://www.virtualbox.org. This file is free software;
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * you can redistribute it and/or modify it under the terms of the GNU
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * General Public License (GPL) as published by the Free Software
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * additional information or have any questions.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync/*******************************************************************************
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync* Header Files *
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync*******************************************************************************/
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync/*******************************************************************************
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync* Internal Functions *
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync*******************************************************************************/
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsyncstatic int pgmHandlerPhysicalSetRamFlagsAndFlushShadowPTs(PVM pVM, PPGMPHYSHANDLER pCur, PPGMRAMRANGE pRam);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsyncstatic void pgmHandlerPhysicalDeregisterNotifyREM(PVM pVM, PPGMPHYSHANDLER pCur);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsyncstatic void pgmHandlerPhysicalResetRamFlags(PVM pVM, PPGMPHYSHANDLER pCur);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * Register a access handler for a physical range.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @returns VBox status code.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @retval VINF_SUCCESS when successfully installed.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @retval VINF_PGM_GCPHYS_ALIASED when the shadow PTs could be updated because
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * the guest page aliased or/and mapped by multiple PTs. A CR3 sync has been
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * flagged together with a pool clearing.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @retval VERR_PGM_HANDLER_PHYSICAL_CONFLICT if the range conflicts with an existing
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * one. A debug assertion is raised.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @param pVM VM Handle.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @param enmType Handler type. Any of the PGMPHYSHANDLERTYPE_PHYSICAL* enums.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @param GCPhys Start physical address.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @param GCPhysLast Last physical address. (inclusive)
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @param pfnHandlerR3 The R3 handler.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @param pvUserR3 User argument to the R3 handler.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @param pfnHandlerR0 The R0 handler.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @param pvUserR0 User argument to the R0 handler.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @param pfnHandlerGC The RC handler.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @param pvUserRC User argument to the RC handler. This can be a value
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * less that 0x10000 or a (non-null) pointer that is
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * automatically relocatated.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @param pszDesc Pointer to description string. This must not be freed.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsyncVMMDECL(int) PGMHandlerPhysicalRegisterEx(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast,
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync R3PTRTYPE(PFNPGMR3PHYSHANDLER) pfnHandlerR3, RTR3PTR pvUserR3,
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync R0PTRTYPE(PFNPGMR0PHYSHANDLER) pfnHandlerR0, RTR0PTR pvUserR0,
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync RCPTRTYPE(PFNPGMRCPHYSHANDLER) pfnHandlerRC, RTRCPTR pvUserRC,
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync Log(("PGMHandlerPhysicalRegisterEx: enmType=%d GCPhys=%RGp GCPhysLast=%RGp pfnHandlerR3=%RHv pvUserR3=%RHv pfnHandlerR0=%RHv pvUserR0=%RHv pfnHandlerGC=%RRv pvUserGC=%RRv pszDesc=%s\n",
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync enmType, GCPhys, GCPhysLast, pfnHandlerR3, pvUserR3, pfnHandlerR0, pvUserR0, pfnHandlerRC, pvUserRC, R3STRING(pszDesc)));
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * Validate input.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync AssertMsgReturn(GCPhys < GCPhysLast, ("GCPhys >= GCPhysLast (%#x >= %#x)\n", GCPhys, GCPhysLast), VERR_INVALID_PARAMETER);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync AssertMsgFailed(("Invalid input enmType=%d!\n", enmType));
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync || MMHyperR3ToRC(pVM, MMHyperRCToR3(pVM, pvUserRC)) == pvUserRC,
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync AssertReturn(pfnHandlerR3 || pfnHandlerR0 || pfnHandlerRC, VERR_INVALID_PARAMETER);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * We require the range to be within registered ram.
660fd430a3a8cfa16505d04c7c577acf89d45a40vboxsync * There is no apparent need to support ranges which cover more than one ram range.
89dfdbb56cf9dddad3c7685b41bda1e4e4c1d6f9vboxsync PPGMRAMRANGE pRam = pVM->pgm.s.CTX_SUFF(pRamRanges);
89dfdbb56cf9dddad3c7685b41bda1e4e4c1d6f9vboxsync AssertMsgFailed(("No RAM range for %RGp-%RGp\n", GCPhys, GCPhysLast));
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * Allocate and initialize the new entry.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync int rc = MMHyperAlloc(pVM, sizeof(*pNew), 0, MM_TAG_PGM_HANDLERS, (void **)&pNew);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync pNew->cPages = (GCPhysLast - (GCPhys & X86_PTE_PAE_PG_MASK) + PAGE_SIZE) >> PAGE_SHIFT;
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * Try insert into list.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync if (RTAvlroGCPhysInsert(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, &pNew->Core))
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync rc = pgmHandlerPhysicalSetRamFlagsAndFlushShadowPTs(pVM, pNew, pRam);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync REMNotifyHandlerPhysicalRegister(pVM, enmType, GCPhys, GCPhysLast - GCPhys + 1, !!pfnHandlerR3);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync REMR3NotifyHandlerPhysicalRegister(pVM, enmType, GCPhys, GCPhysLast - GCPhys + 1, !!pfnHandlerR3);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync Log(("PGMHandlerPhysicalRegisterEx: returns %Rrc (%RGp-%RGp)\n", rc, GCPhys, GCPhysLast));
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync AssertMsgFailed(("Conflict! GCPhys=%RGp GCPhysLast=%RGp pszDesc=%s\n", GCPhys, GCPhysLast, pszDesc));
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * Sets ram range flags and attempts updating shadow PTs.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @returns VBox status code.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @retval VINF_SUCCESS when shadow PTs was successfully updated.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @retval VINF_PGM_GCPHYS_ALIASED when the shadow PTs could be updated because
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * the guest page aliased or/and mapped by multiple PTs.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @param pVM The VM handle.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @param pCur The physical handler.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * @param pRam The RAM range.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsyncstatic int pgmHandlerPhysicalSetRamFlagsAndFlushShadowPTs(PVM pVM, PPGMPHYSHANDLER pCur, PPGMRAMRANGE pRam)
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * Iterate the guest ram pages updating the flags and flushing PT entries
89dfdbb56cf9dddad3c7685b41bda1e4e4c1d6f9vboxsync * mapping the page.
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync bool fFlushTLBs = false;
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync#if defined(PGMPOOL_WITH_GCPHYS_TRACKING) || defined(PGMPOOL_WITH_CACHE)
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync const unsigned uState = pgmHandlerPhysicalCalcState(pCur);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync RTUINT i = (pCur->Core.Key - pRam->GCPhys) >> PAGE_SHIFT;
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync /* Physical chunk in dynamically allocated range not present? */
f9e38e609bea9e849b27173024dc82d93bcbf5fcvboxsync if (RT_UNLIKELY(!PGM_PAGE_GET_HCPHYS(&pRam->aPages[i])))
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync RTGCPHYS GCPhys = pRam->GCPhys + (i << PAGE_SHIFT);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync int rc2 = CTXALLMID(VMM, CallHost)(pVM, VMMCALLHOST_PGM_RAM_GROW_RANGE, GCPhys);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync /* Only do upgrades. */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync /* This code also makes ASSUMPTIONS about the cRefs and stuff. */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync Assert(MM_RAM_FLAGS_IDX_SHIFT < MM_RAM_FLAGS_CREFS_SHIFT);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync const uint16_t u16 = pRam->aPages[i].HCPhys >> MM_RAM_FLAGS_IDX_SHIFT; /** @todo PAGE FLAGS */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync /* Start a subset here because pgmPoolTrackFlushGCPhysPTsSlow and pgmPoolTrackFlushGCPhysPTs
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync will/may kill the pool otherwise. */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync uint32_t iPrevSubset = PGMDynMapPushAutoSubset(pVCpu);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync if ((u16 >> (MM_RAM_FLAGS_CREFS_SHIFT - MM_RAM_FLAGS_IDX_SHIFT)) != MM_RAM_FLAGS_CREFS_PHYSEXT)
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync u16 >> (MM_RAM_FLAGS_CREFS_SHIFT - MM_RAM_FLAGS_IDX_SHIFT));
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync else if (u16 != ((MM_RAM_FLAGS_CREFS_PHYSEXT << (MM_RAM_FLAGS_CREFS_SHIFT - MM_RAM_FLAGS_IDX_SHIFT)) | MM_RAM_FLAGS_IDX_OVERFLOWED))
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync pgmPoolTrackFlushGCPhysPTs(pVM, pPage, u16 & MM_RAM_FLAGS_IDX_MASK);
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync /* Start a subset here because pgmPoolTrackFlushGCPhysPTsSlow kill the pool otherwise. */
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync uint32_t iPrevSubset = PGMDynMapPushAutoSubset(pVCpu);
f9e38e609bea9e849b27173024dc82d93bcbf5fcvboxsync Log(("pgmHandlerPhysicalSetRamFlagsAndFlushShadowPTs: flushing guest TLBs\n"));
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync Log(("pgmHandlerPhysicalSetRamFlagsAndFlushShadowPTs: doesn't flush guest TLBs. rc=%Rrc\n", rc));
9e5c26690d45216629b5f588aced8fcfb68c23b6vboxsync * Register a physical page access handler.
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysRemove(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys);
if (pCur)
return VINF_SUCCESS;
return VERR_PGM_HANDLER_NOT_FOUND;
if ( pPage
if ( pPage
#ifndef IN_RING3
REMNotifyHandlerPhysicalDeregister(pVM, pCur->enmType, GCPhysStart, GCPhysLast - GCPhysStart + 1, !!pCur->pfnHandlerR3, fRestoreAsRAM);
REMR3NotifyHandlerPhysicalDeregister(pVM, pCur->enmType, GCPhysStart, GCPhysLast - GCPhysStart + 1, !!pCur->pfnHandlerR3, fRestoreAsRAM);
DECLINLINE(void) pgmHandlerPhysicalRecalcPageState(PPGM pPGM, RTGCPHYS GCPhys, bool fAbove, PPGMRAMRANGE *ppRamHint)
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysGetBestFit(&pPGM->CTX_SUFF(pTrees)->PhysHandlers, GCPhys, fAbove);
if ( !pCur
if (--cPages == 0)
* For all return codes other than VERR_PGM_HANDLER_NOT_FOUND and VINF_SUCCESS the range is deregistered
VMMDECL(int) PGMHandlerPhysicalModify(PVM pVM, RTGCPHYS GCPhysCurrent, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast)
int rc;
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysRemove(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhysCurrent);
if (pCur)
if ( pRam
#ifndef IN_RING3
return VINF_SUCCESS;
return rc;
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys);
if (pCur)
return rc;
return rc;
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys);
pNew->cPages = (pNew->Core.KeyLast - (pNew->Core.Key & X86_PTE_PAE_PG_MASK) + PAGE_SIZE) >> PAGE_SHIFT;
pCur->cPages = (pCur->Core.KeyLast - (pCur->Core.Key & X86_PTE_PAE_PG_MASK) + PAGE_SIZE) >> PAGE_SHIFT;
return VINF_SUCCESS;
AssertMsgFailed(("outside range: %RGp-%RGp split %RGp\n", pCur->Core.Key, pCur->Core.KeyLast, GCPhysSplit));
return rc;
int rc;
PPGMPHYSHANDLER pCur1 = (PPGMPHYSHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys1);
PPGMPHYSHANDLER pCur2 = (PPGMPHYSHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys2);
PPGMPHYSHANDLER pCur3 = (PPGMPHYSHANDLER)RTAvlroGCPhysRemove(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys2);
pCur1->cPages = (pCur1->Core.KeyLast - (pCur1->Core.Key & X86_PTE_PAE_PG_MASK) + PAGE_SIZE) >> PAGE_SHIFT;
return VINF_SUCCESS;
return rc;
int rc;
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys);
case PGMPHYSHANDLERTYPE_MMIO:
return rc;
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys);
#ifndef IN_RC
return VINF_SUCCESS;
return VERR_INVALID_PARAMETER;
return VERR_PGM_HANDLER_NOT_FOUND;
VMMDECL(int) PGMHandlerPhysicalPageAlias(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysPage, RTGCPHYS GCPhysPageRemap)
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys);
/* Do the actual remapping here. This page now serves as an alias for the backing memory specified. */
LogFlow(("PGMHandlerPhysicalPageAlias %RGp -> %RGp - %RHp\n", GCPhysPage, GCPhysPageRemap, pPageRemap->HCPhys));
#ifndef IN_RC
return VINF_SUCCESS;
return VERR_INVALID_PARAMETER;
return VERR_PGM_HANDLER_NOT_FOUND;
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys);
#ifndef IN_RC
return VINF_SUCCESS;
return VERR_INVALID_PARAMETER;
return VERR_PGM_HANDLER_NOT_FOUND;
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys);
if (pCur)
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys);
PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrGet(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, GCPtr);
int pgmHandlerVirtualFindByPhysAddr(PVM pVM, RTGCPHYS GCPhys, PPGMVIRTHANDLER *ppVirt, unsigned *piPage)
pCur = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, GCPhys);
if (pCur)
LogFlow(("PHYS2VIRT: found match for %RGp -> %RGv *piPage=%#x\n", GCPhys, (*ppVirt)->Core.Key, *piPage));
return VINF_SUCCESS;
return VERR_PGM_HANDLER_NOT_FOUND;
/** @todo Deal with partial overlapping. (Unlikly situation, so I'm too lazy to do anything about it now.) */
* and I'm too lazy to implement this now as it will require sorting the list and stuff like that. */
PPGMPHYS2VIRTHANDLER pHead = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key);
LogRel(("pgmHandlerVirtualInsertAliased: %RGp-%RGp\n", pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast));
PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pHead + (pHead->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
Log(("pgmHandlerVirtualInsertAliased: %RGp-%RGp offNextAlias=%#RX32\n", pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offNextAlias));
* when there have been registration/deregistrations). For this reason this
AssertReleaseMsg(RTAvlroGCPhysGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key) == &pPhys2Virt->Core,
pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offNextAlias, R3STRING(pCur->pszDesc)));
offPage = 0;
static DECLCALLBACK(int) pgmHandlerVirtualDumpPhysPagesCallback(PAVLROGCPHYSNODECORE pNode, void *pvUser)
Log(("PHYS2VIRT: Range %RGp-%RGp for virtual handler: %s\n", pCur->Core.Key, pCur->Core.KeyLast, pVirt->pszDesc));
#ifdef VBOX_STRICT
typedef struct PGMAHAFIS
unsigned uVirtStateFound;
unsigned uVirtState;
unsigned cErrors;
static DECLCALLBACK(int) pgmHandlerVirtualVerifyOneByPhysAddr(PAVLROGCPTRNODECORE pNode, void *pvUser)
case PGMVIRTHANDLERTYPE_WRITE:
case PGMVIRTHANDLERTYPE_ALL:
if ( (pVirt->aPhysToVirt[0].Core.Key & PAGE_OFFSET_MASK) != ((RTGCUINTPTR)pVirt->Core.Key & PAGE_OFFSET_MASK)
if ( (pVirt->aPhysToVirt[pVirt->cPages - 1].Core.KeyLast & PAGE_OFFSET_MASK) != ((RTGCUINTPTR)pVirt->Core.KeyLast & PAGE_OFFSET_MASK)
pVirt->aPhysToVirt[pVirt->cPages - 1].Core.KeyLast, pVirt->Core.KeyLast, R3STRING(pVirt->pszDesc)));
if (!pPage)
AssertMsgFailed(("virt handler state mismatch. HCPhys=%RHp GCPhysGst=%RGp iPage=%#x %RGv state=%d expected>=%d %s\n",
pPage->HCPhys, GCPhysGst, iPage, GCPtr, PGM_PAGE_GET_HNDL_VIRT_STATE(pPage), uState, R3STRING(pVirt->pszDesc)));
PPGMPHYSHANDLER pPhys = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pPGM->CTX_SUFF(pTrees)->PhysHandlers, State.GCPhys);
if (!pPhys)
pPhys = (PPGMPHYSHANDLER)RTAvlroGCPhysGetBestFit(&pPGM->CTX_SUFF(pTrees)->PhysHandlers, State.GCPhys, true);
if ( pPhys
if (pPhys)
PPGMPHYSHANDLER pPhys2 = (PPGMPHYSHANDLER)RTAvlroGCPhysGetBestFit(&pPGM->CTX_SUFF(pTrees)->PhysHandlers,
if ( !pPhys2
#ifdef IN_RING3
&& (pPage->HCPhys & (MM_RAM_FLAGS_ROM | MM_RAM_FLAGS_MMIO2)) != (MM_RAM_FLAGS_ROM | MM_RAM_FLAGS_MMIO2))
AssertMsgFailed(("ram range vs phys handler mismatch. no handler for GCPhys=%RGp\n", State.GCPhys));
PPGMPHYS2VIRTHANDLER pPhys2Virt = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGetBestFit(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers,
if ( !pPhys2Virt
pPhys2Virt = (PPGMPHYS2VIRTHANDLER)((uintptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
RTAvlroGCPtrDoWithAll(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, true, pgmHandlerVirtualVerifyOneByPhysAddr, &State);
AssertMsgFailed(("ram range vs virt handler flags mismatch. GCPhys=%RGp uVirtState=%#x uVirtStateFound=%#x\n",
RTAvlroGCPtrDoWithAll(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, true, pgmHandlerVirtualVerifyOne, &State);