PGMAllHandler.cpp revision ff36bf7f3839ea1c6fb3d3eb9ddc966183edaf1f
f1c89cb4f5c72c54bb67dc48cd6f2b332eab9e92Automatic Updater * PGM - Page Manager / Monitor, Access Handlers.
f1c89cb4f5c72c54bb67dc48cd6f2b332eab9e92Automatic Updater * Copyright (C) 2006-2007 Sun Microsystems, Inc.
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * This file is part of VirtualBox Open Source Edition (OSE), as
83a28ca274521e15086fc39febde507bcc4e145eMark Andrews * available from http://www.virtualbox.org. This file is free software;
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrews * you can redistribute it and/or modify it under the terms of the GNU
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * General Public License (GPL) as published by the Free Software
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrews * Foundation, in version 2 as it comes in the "COPYING" file of the
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrews * Clara, CA 95054 USA or visit http://www.sun.com if you need
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrews * additional information or have any questions.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt/*******************************************************************************
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrews* Header Files *
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt*******************************************************************************/
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt/*******************************************************************************
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt* Internal Functions *
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt*******************************************************************************/
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrewsstatic int pgmHandlerPhysicalSetRamFlagsAndFlushShadowPTs(PVM pVM, PPGMPHYSHANDLER pCur, PPGMRAMRANGE pRam);
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Huntstatic void pgmHandlerPhysicalDeregisterNotifyREM(PVM pVM, PPGMPHYSHANDLER pCur);
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Huntstatic void pgmHandlerPhysicalResetRamFlags(PVM pVM, PPGMPHYSHANDLER pCur);
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * Register a access handler for a physical range.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * @returns VBox status code.
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * @retval VINF_SUCCESS when successfully installed.
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * @retval VINF_PGM_GCPHYS_ALIASED when the shadow PTs could be updated because
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * the guest page aliased or/and mapped by multiple PTs. A CR3 sync has been
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * flagged together with a pool clearing.
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * @retval VERR_PGM_HANDLER_PHYSICAL_CONFLICT if the range conflicts with an existing
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * one. A debug assertion is raised.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * @param pVM VM Handle.
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrews * @param enmType Handler type. Any of the PGMPHYSHANDLERTYPE_PHYSICAL* enums.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * @param GCPhys Start physical address.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * @param GCPhysLast Last physical address. (inclusive)
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * @param pfnHandlerR3 The R3 handler.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * @param pvUserR3 User argument to the R3 handler.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * @param pfnHandlerR0 The R0 handler.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * @param pvUserR0 User argument to the R0 handler.
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * @param pfnHandlerGC The GC handler.
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrews * @param pvUserGC User argument to the GC handler.
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * This must be a GC pointer because it will be relocated!
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrews * @param pszDesc Pointer to description string. This must not be freed.
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark AndrewsPGMDECL(int) PGMHandlerPhysicalRegisterEx(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast,
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrews R3PTRTYPE(PFNPGMR3PHYSHANDLER) pfnHandlerR3, RTR3PTR pvUserR3,
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrews R0PTRTYPE(PFNPGMR0PHYSHANDLER) pfnHandlerR0, RTR0PTR pvUserR0,
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt RCPTRTYPE(PFNPGMGCPHYSHANDLER) pfnHandlerGC, RCPTRTYPE(void *) pvUserGC,
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt Log(("PGMHandlerPhysicalRegisterEx: enmType=%d GCPhys=%VGp GCPhysLast=%VGp pfnHandlerR3=%VHv pvUserR3=%VHv pfnHandlerR0=%VHv pvUserR0=%VHv pfnHandlerGC=%VRv pvUserGC=%VRv pszDesc=%s\n",
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt enmType, GCPhys, GCPhysLast, pfnHandlerR3, pvUserR3, pfnHandlerR0, pvUserR0, pfnHandlerGC, pvUserGC, R3STRING(pszDesc)));
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * Validate input.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt AssertMsgFailed(("GCPhys >= GCPhysLast (%#x >= %#x)\n", GCPhys, GCPhysLast));
87002e151b8507e2deb8a72e475b77a87cb35045Automatic Updater AssertMsgFailed(("Invalid input enmType=%d!\n", enmType));
79ce3a9e82384cc31fd6b86be8f3d1474fcfd9f4Evan Hunt && MMHyperHC2GC(pVM, MMHyperGC2HC(pVM, pvUserGC)) != pvUserGC)
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrews AssertMsgFailed(("Not GC pointer! pvUserGC=%VGv\n", pvUserGC));
c6f4972c745f8903aba6dcca41f17a44c473db66Mark Andrews AssertReturn(pfnHandlerR3 || pfnHandlerR0 || pfnHandlerGC, VERR_INVALID_PARAMETER);
03f979494f5c80e05a72f876914d9d44085fbd6aEvan Hunt * We require the range to be within registered ram.
03f979494f5c80e05a72f876914d9d44085fbd6aEvan Hunt * There is no apparent need to support ranges which cover more than one ram range.
03f979494f5c80e05a72f876914d9d44085fbd6aEvan Hunt PPGMRAMRANGE pRam = CTXALLSUFF(pVM->pgm.s.pRamRanges);
79ce3a9e82384cc31fd6b86be8f3d1474fcfd9f4Evan Hunt AssertMsgFailed(("No RAM range for %VGp-%VGp\n", GCPhys, GCPhysLast));
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrews * Allocate and initialize the new entry.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt int rc = MMHyperAlloc(pVM, sizeof(*pNew), 0, MM_TAG_PGM_HANDLERS, (void **)&pNew);
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt pNew->cPages = (GCPhysLast - (GCPhys & X86_PTE_PAE_PG_MASK) + PAGE_SIZE) >> PAGE_SHIFT;
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * Try insert into list.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt if (RTAvlroGCPhysInsert(&pVM->pgm.s.CTXSUFF(pTrees)->PhysHandlers, &pNew->Core))
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt rc = pgmHandlerPhysicalSetRamFlagsAndFlushShadowPTs(pVM, pNew, pRam);
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt REMNotifyHandlerPhysicalRegister(pVM, enmType, GCPhys, GCPhysLast - GCPhys + 1, !!pfnHandlerR3);
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt REMR3NotifyHandlerPhysicalRegister(pVM, enmType, GCPhys, GCPhysLast - GCPhys + 1, !!pfnHandlerR3);
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt Log(("PGMHandlerPhysicalRegisterEx: returns %Vrc (%VGp-%VGp)\n", rc, GCPhys, GCPhysLast));
c6f4972c745f8903aba6dcca41f17a44c473db66Mark Andrews DBGFR3Info(pVM, "handlers", "phys nostats", NULL);
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrews AssertMsgFailed(("Conflict! GCPhys=%VGp GCPhysLast=%VGp pszDesc=%s\n", GCPhys, GCPhysLast, pszDesc));
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * Sets ram range flags and attempts updating shadow PTs.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * @returns VBox status code.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * @retval VINF_SUCCESS when shadow PTs was successfully updated.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * @retval VINF_PGM_GCPHYS_ALIASED when the shadow PTs could be updated because
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * the guest page aliased or/and mapped by multiple PTs.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * @param pVM The VM handle.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * @param pCur The physical handler.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * @param pRam The RAM range.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Huntstatic int pgmHandlerPhysicalSetRamFlagsAndFlushShadowPTs(PVM pVM, PPGMPHYSHANDLER pCur, PPGMRAMRANGE pRam)
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * Iterate the guest ram pages updating the flags and flushing PT entries
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * mapping the page.
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt#if defined(PGMPOOL_WITH_GCPHYS_TRACKING) || defined(PGMPOOL_WITH_CACHE)
c6f4972c745f8903aba6dcca41f17a44c473db66Mark Andrews const unsigned uState = pgmHandlerPhysicalCalcState(pCur);
c6f4972c745f8903aba6dcca41f17a44c473db66Mark Andrews RTUINT i = (pCur->Core.Key - pRam->GCPhys) >> PAGE_SHIFT;
c6f4972c745f8903aba6dcca41f17a44c473db66Mark Andrews /* Physical chunk in dynamically allocated range not present? */
c6f4972c745f8903aba6dcca41f17a44c473db66Mark Andrews if (RT_UNLIKELY(!PGM_PAGE_GET_HCPHYS(&pRam->aPages[i])))
c6f4972c745f8903aba6dcca41f17a44c473db66Mark Andrews RTGCPHYS GCPhys = pRam->GCPhys + (i << PAGE_SHIFT);
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt int rc2 = CTXALLMID(VMM, CallHost)(pVM, VMMCALLHOST_PGM_RAM_GROW_RANGE, GCPhys);
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrews /* Only do upgrades. */
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrews /* This code also makes ASSUMPTIONS about the cRefs and stuff. */
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt Assert(MM_RAM_FLAGS_IDX_SHIFT < MM_RAM_FLAGS_CREFS_SHIFT);
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt const uint16_t u16 = pRam->aPages[i].HCPhys >> MM_RAM_FLAGS_IDX_SHIFT; /** @todo PAGE FLAGS */
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt if ((u16 >> (MM_RAM_FLAGS_CREFS_SHIFT - MM_RAM_FLAGS_IDX_SHIFT)) != MM_RAM_FLAGS_CREFS_PHYSEXT)
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt u16 >> (MM_RAM_FLAGS_CREFS_SHIFT - MM_RAM_FLAGS_IDX_SHIFT));
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt else if (u16 != ((MM_RAM_FLAGS_CREFS_PHYSEXT << (MM_RAM_FLAGS_CREFS_SHIFT - MM_RAM_FLAGS_IDX_SHIFT)) | MM_RAM_FLAGS_IDX_OVERFLOWED))
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt pgmPoolTrackFlushGCPhysPTs(pVM, pPage, u16 & MM_RAM_FLAGS_IDX_MASK);
30eec077db2bdcb6f2a0dc388a3cdde2ede75ec1Mark Andrews Log(("pgmHandlerPhysicalSetRamFlagsAndFlushShadowPTs: flushing guest TLBs\n"));
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt Log(("pgmHandlerPhysicalSetRamFlagsAndFlushShadowPTs: doesn't flush guest TLBs. rc=%Vrc\n", rc));
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * Register a physical page access handler.
0b24b2d3c423560a0a4cd9a4476b9a2dcafb7ea3Evan Hunt * @returns VBox status code.
14a656f94b1fd0ababd84a772228dfa52276ba15Evan Hunt * @param pVM VM Handle.
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysRemove(&pVM->pgm.s.CTXSUFF(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->CTXSUFF(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
PGMDECL(int) PGMHandlerPhysicalModify(PVM pVM, RTGCPHYS GCPhysCurrent, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast)
int rc;
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysRemove(&pVM->pgm.s.CTXSUFF(pTrees)->PhysHandlers, GCPhysCurrent);
if (pCur)
if ( pRam
#ifndef IN_RING3
return VINF_SUCCESS;
return rc;
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTXSUFF(pTrees)->PhysHandlers, GCPhys);
if (pCur)
return rc;
return rc;
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTXSUFF(pTrees)->PhysHandlers, GCPhys);
if (pCur)
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: %VGp-%VGp split %VGp\n", pCur->Core.Key, pCur->Core.KeyLast, GCPhysSplit));
return rc;
int rc;
PPGMPHYSHANDLER pCur1 = (PPGMPHYSHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTXSUFF(pTrees)->PhysHandlers, GCPhys1);
if (pCur1)
PPGMPHYSHANDLER pCur2 = (PPGMPHYSHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTXSUFF(pTrees)->PhysHandlers, GCPhys2);
if (pCur2)
PPGMPHYSHANDLER pCur3 = (PPGMPHYSHANDLER)RTAvlroGCPhysRemove(&pVM->pgm.s.CTXSUFF(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.CTXSUFF(pTrees)->PhysHandlers, GCPhys);
if (pCur)
case PGMPHYSHANDLERTYPE_MMIO:
return rc;
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTXSUFF(pTrees)->PhysHandlers, GCPhys);
if (pCur)
#ifdef IN_RING0
return VINF_SUCCESS;
return VERR_INVALID_PARAMETER;
return VERR_PGM_HANDLER_NOT_FOUND;
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTXSUFF(pTrees)->PhysHandlers, GCPhys);
if (pCur)
return VINF_SUCCESS;
return VERR_INVALID_PARAMETER;
return VERR_PGM_HANDLER_NOT_FOUND;
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.CTXSUFF(pTrees)->PhysHandlers, GCPhys);
if (pCur)
int pgmHandlerVirtualFindByPhysAddr(PVM pVM, RTGCPHYS GCPhys, PPGMVIRTHANDLER *ppVirt, unsigned *piPage)
pCur = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysRangeGet(&CTXSUFF(pVM->pgm.s.pTrees)->PhysToVirtHandlers, GCPhys);
if (pCur)
LogFlow(("PHYS2VIRT: found match for %VGp -> %VGv *piPage=%#x\n", GCPhys, (*ppVirt)->GCPtr, *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.CTXSUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key);
LogRel(("pgmHandlerVirtualInsertAliased: %VGp-%VGp\n", pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast));
PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pHead + (pHead->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
Log(("pgmHandlerVirtualInsertAliased: %VGp-%VGp 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.CTXSUFF(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 %VGp-%VGp 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->GCPtr & PAGE_OFFSET_MASK)
if ( (pVirt->aPhysToVirt[pVirt->cPages - 1].Core.KeyLast & PAGE_OFFSET_MASK) != ((RTGCUINTPTR)pVirt->GCPtrLast & PAGE_OFFSET_MASK)
if (!pPage)
AssertMsgFailed(("virt handler state mismatch. HCPhys=%VHp GCPhysGst=%VGp iPage=%#x %VGv 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->CTXSUFF(pTrees)->PhysHandlers, State.GCPhys);
if (!pPhys)
pPhys = (PPGMPHYSHANDLER)RTAvlroGCPhysGetBestFit(&pPGM->CTXSUFF(pTrees)->PhysHandlers, State.GCPhys, true);
if ( pPhys
if (pPhys)
PPGMPHYSHANDLER pPhys2 = (PPGMPHYSHANDLER)RTAvlroGCPhysGetBestFit(&pPGM->CTXSUFF(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(&CTXSUFF(pVM->pgm.s.pTrees)->PhysToVirtHandlers,
if ( !pPhys2Virt
pPhys2Virt = (PPGMPHYS2VIRTHANDLER)((uintptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
RTAvlroGCPtrDoWithAll(CTXSUFF(&pVM->pgm.s.pTrees)->VirtHandlers, true, pgmHandlerVirtualVerifyOneByPhysAddr, &State);
AssertMsgFailed(("ram range vs virt handler flags mismatch. GCPhys=%RGp uVirtState=%#x uVirtStateFound=%#x\n",
RTAvlroGCPtrDoWithAll(CTXSUFF(&pVM->pgm.s.pTrees)->VirtHandlers, true, pgmHandlerVirtualVerifyOne, &State);