PGMAllPhys.cpp revision 30a97c179f003a662c7d3f513c972f9fd48d8c77
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * PGM - Page Manager and Monitor, Physical Memory Addressing.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * available from http://www.virtualbox.org. This file is free software;
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * you can redistribute it and/or modify it under the terms of the GNU
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * General Public License (GPL) as published by the Free Software
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * additional information or have any questions.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync/*******************************************************************************
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync* Defined Constants And Macros *
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync*******************************************************************************/
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync/** @def PGM_IGNORE_RAM_FLAGS_RESERVED
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * Don't respect the MM_RAM_FLAGS_RESERVED flag when converting to HC addresses.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * Since this flag is currently incorrectly kept set for ROM regions we will
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * have to ignore it for now so we don't break stuff.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @todo this has been fixed now I believe, remove this hack.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync/*******************************************************************************
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync* Header Files *
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync*******************************************************************************/
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * \#PF Handler callback for Guest ROM range write access.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * We simply ignore the writes or fall back to the recompiler if we don't support the instruction.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @returns VBox status code (appropritate for trap handling and GC return).
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @param pVM VM Handle.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @param uErrorCode CPU Error code.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @param pRegFrame Trap register frame.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @param pvFault The fault address (cr2).
4bfa7b58e362a1bca0628643c352c137900bf01avboxsync * @param GCPhysFault The GC physical address corresponding to pvFault.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @param pvUser User argument. Pointer to the ROM range structure.
d82d7a8b44b27420e50f410d8ee5b990bb8b8f12vboxsyncVMMDECL(int) pgmPhysRomWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser)
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync uint32_t iPage = (GCPhysFault - pRom->GCPhys) >> PAGE_SHIFT;
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * If it's a simple instruction which doesn't change the cpu state
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * we will simply skip it. Otherwise we'll have to defer it to REM.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync rc = EMInterpretDisasOne(pVM, pRegFrame, &Cpu, &cbOp);
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync && Cpu.mode == CPUMODE_32BIT /** @todo why does this matter? */
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync && !(Cpu.prefix & (PREFIX_REPNE | PREFIX_REP | PREFIX_SEG)))
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync /** @todo Find other instructions we can safely skip, possibly
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * adding this kind of detection to DIS or EM. */
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatRZGuestROMWriteHandled);
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync rc = PGMHandlerPhysicalPageTempOff(pVM, pRom->GCPhys, GCPhysFault & X86_PTE_PG_MASK);
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync break; /** @todo Must restart the instruction, not use the interpreter! */
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync /* Handle it in ring-3 because it's *way* easier there. */
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync AssertMsgFailedReturn(("enmProt=%d iPage=%d GCPhysFault=%RGp\n",
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatRZGuestROMWriteUnhandled);
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync#endif /* IN_RING3 */
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * Checks if Address Gate 20 is enabled or not.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @returns true if enabled.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @returns false if disabled.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @param pVM VM handle.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync LogFlow(("PGMPhysIsA20Enabled %d\n", pVM->pgm.s.fA20Enabled));
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync return !!pVM->pgm.s.fA20Enabled ; /* stupid MS compiler doesn't trust me. */
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * Validates a GC physical address.
d82d7a8b44b27420e50f410d8ee5b990bb8b8f12vboxsync * @returns true if valid.
d82d7a8b44b27420e50f410d8ee5b990bb8b8f12vboxsync * @returns false if invalid.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @param pVM The VM handle.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @param GCPhys The physical address to validate.
d82d7a8b44b27420e50f410d8ee5b990bb8b8f12vboxsyncVMMDECL(bool) PGMPhysIsGCPhysValid(PVM pVM, RTGCPHYS GCPhys)
d82d7a8b44b27420e50f410d8ee5b990bb8b8f12vboxsync PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * Checks if a GC physical address is a normal page,
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * i.e. not ROM, MMIO or reserved.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @returns true if normal.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @returns false if invalid, ROM, MMIO or reserved page.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @param pVM The VM handle.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @param GCPhys The physical address to check.
39cac49f62afd27b0ffdbb779c7c64211939030cvboxsyncVMMDECL(bool) PGMPhysIsGCPhysNormal(PVM pVM, RTGCPHYS GCPhys)
39cac49f62afd27b0ffdbb779c7c64211939030cvboxsync PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);
d82d7a8b44b27420e50f410d8ee5b990bb8b8f12vboxsync && !(pPage->HCPhys & (MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_ROM | MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_MMIO2));
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * Converts a GC physical address to a HC physical address.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @returns VINF_SUCCESS on success.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @returns VERR_PGM_PHYS_PAGE_RESERVED it it's a valid GC physical
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * page but has no physical backing.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @returns VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if it's not a valid
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * GC physical address.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @param pVM The VM handle.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @param GCPhys The GC physical address to convert.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @param pHCPhys Where to store the HC physical address on success.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsyncVMMDECL(int) PGMPhysGCPhys2HCPhys(PVM pVM, RTGCPHYS GCPhys, PRTHCPHYS pHCPhys)
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync int rc = pgmPhysGetPageEx(&pVM->pgm.s, GCPhys, &pPage);
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync if (RT_UNLIKELY(pPage->HCPhys & MM_RAM_FLAGS_RESERVED)) /** @todo PAGE FLAGS */
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync *pHCPhys = PGM_PAGE_GET_HCPHYS(pPage) | (GCPhys & PAGE_OFFSET_MASK);
d82d7a8b44b27420e50f410d8ee5b990bb8b8f12vboxsync * Invalidates the GC page mapping TLB.
d82d7a8b44b27420e50f410d8ee5b990bb8b8f12vboxsync * @param pVM The VM handle.
d82d7a8b44b27420e50f410d8ee5b990bb8b8f12vboxsyncVMMDECL(void) PGMPhysInvalidatePageGCMapTLB(PVM pVM)
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync /* later */
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * Invalidates the ring-0 page mapping TLB.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @param pVM The VM handle.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsyncVMMDECL(void) PGMPhysInvalidatePageR0MapTLB(PVM pVM)
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * Invalidates the ring-3 page mapping TLB.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync * @param pVM The VM handle.
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsyncVMMDECL(void) PGMPhysInvalidatePageR3MapTLB(PVM pVM)
d82d7a8b44b27420e50f410d8ee5b990bb8b8f12vboxsync for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.PhysTlbHC.aEntries); i++)
078c5b8c5c814755aab943bf62cadef7e91c419cvboxsync pVM->pgm.s.PhysTlbHC.aEntries[i].GCPhys = NIL_RTGCPHYS;
AssertMsg(pVM->pgm.s.cHandyPages <= RT_ELEMENTS(pVM->pgm.s.aHandyPages), ("%d\n", pVM->pgm.s.cHandyPages));
#ifdef IN_RING3
Log(("PGM: cHandyPages=%u out of %u -> allocate more\n", pVM->pgm.s.cHandyPages, RT_ELEMENTS(pVM->pgm.s.aHandyPages)));
#ifdef IN_RING3
return VERR_EM_NO_MEMORY;
#ifdef IN_RING3
#ifndef IN_RING3
Log(("PGM: VM_FF_TO_R3 - cHandyPages=%u out of %u\n", pVM->pgm.s.cHandyPages - 1, RT_ELEMENTS(pVM->pgm.s.aHandyPages)));
return VINF_SUCCESS;
AssertMsg(PGM_PAGE_IS_ZERO(pPage) || PGM_PAGE_IS_SHARED(pPage), ("%R[pgmpage] %RGp\n", pPage, GCPhys));
bool fFlushTLBs = false;
if (fFlushTLBs)
return rc2;
AssertMsg(PGM_PAGE_IS_ZERO(pPage) || PGM_PAGE_IS_SHARED(pPage), ("%R[pgmpage] %RGp\n", pPage, GCPhys));
AssertMsgFailed(("TODO: copy shared page content")); /** @todo err.. what about copying the page content? */
Log2(("PGM: Replaced zero page %RGp with %#x / %RHp\n", GCPhys, pVM->pgm.s.aHandyPages[iHandyPage].idPage, HCPhys));
if ( fFlushTLBs
return rc;
case PGM_PAGE_STATE_ALLOCATED:
return VINF_SUCCESS;
case PGM_PAGE_STATE_ZERO:
return VERR_PGM_PHYS_PAGE_RESERVED;
case PGM_PAGE_STATE_SHARED:
return rc;
#ifdef IN_RC
if (!pMap)
# ifdef IN_RING0
return rc;
return VINF_SUCCESS;
return VINF_SUCCESS;
AssertMsgReturn(PGM_PAGE_GET_PAGEID(pPage) == NIL_GMM_PAGEID, ("pPage=%R[pgmpage]\n", pPage), VERR_INTERNAL_ERROR);
AssertMsgReturn(pRam || !pRam->pvR3, ("pRam=%p pPage=%R[pgmpage]\n", pRam, pPage), VERR_INTERNAL_ERROR);
return VINF_SUCCESS;
if (!pMap)
#ifdef IN_RING0
return rc;
return VINF_SUCCESS;
if (!pRam)
void *pv;
return rc;
return VINF_SUCCESS;
void *pv;
return rc;
return VINF_SUCCESS;
int rc;
return rc;
return rc;
return VINF_SUCCESS;
*ppv = pgmDynMapHCPageOff(&pVM->pgm.s, PGM_PAGE_GET_HCPHYS(pPage) | (GCPhys & PAGE_OFFSET_MASK)); /** @todo add a read only flag? */
return rc;
return VINF_SUCCESS;
#ifdef VBOX_WITH_NEW_PHYS_CODE
*ppv = pgmDynMapHCPageOff(&pVM->pgm.s, PGM_PAGE_GET_HCPHYS(pPage) | (GCPhys & PAGE_OFFSET_MASK)); /** @todo add a read only flag? */
return rc;
VMMDECL(int) PGMPhysGCPhys2CCPtrReadOnly(PVM pVM, RTGCPHYS GCPhys, void const **ppv, PPGMPAGEMAPLOCK pLock)
return rc;
VMMDECL(int) PGMPhysGCPtr2CCPtrReadOnly(PVM pVM, RTGCPTR GCPtr, void const **ppv, PPGMPAGEMAPLOCK pLock)
return rc;
#ifdef VBOX_WITH_NEW_PHYS_CODE
if (!pMap)
#ifdef VBOX_WITH_NEW_PHYS_CODE
LogAlways(("PGMPhysGCPhys2R3Ptr(,%RGp,%#x,): dont use this API!\n", GCPhys, cbRange)); /** @todo eliminate this API! */
return rc;
return rc;
#ifndef PGM_IGNORE_RAM_FLAGS_RESERVED
return VERR_PGM_PHYS_PAGE_RESERVED;
#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0) /* ASSUMES this is a rare occurence */
return VERR_PGM_PHYS_PAGE_RESERVED;
return VINF_SUCCESS;
#ifdef VBOX_STRICT
return R3Ptr;
return NIL_RTR3PTR;
return rc;
return rc;
#ifdef VBOX_WITH_NEW_PHYS_CODE
rc = PGMPhysGCPhys2R3Ptr(pVM, GCPhys | ((RTGCUINTPTR)GCPtr & PAGE_OFFSET_MASK), 1 /* we always stay within one page */, pR3Ptr);
return rc;
#ifdef IN_RING3
#ifdef VBOX_WITH_NEW_PHYS_CODE
AssertLogRelMsgFailed(("pgmPhysGCPhys2CCPtrInternalReadOnly failed on %RGp / %R[pgmpage] -> %Rrc\n",
#ifdef IN_RING3
PPGMPHYSHANDLER pPhys = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys);
Log5(("pgmPhysReadHandler: GCPhys=%RGp cb=%#x pPage=%R[pgmpage] phys %s\n", GCPhys, cb, pPage, R3STRING(pPhys->pszDesc) ));
rc = pPhys->CTX_SUFF(pfnHandler)(pVM, GCPhys, (void *)pvSrc, pvBuf, cb, PGMACCESSTYPE_READ, pPhys->CTX_SUFF(pvUser));
AssertLogRelMsg(rc == VINF_SUCCESS || rc == VINF_PGM_HANDLER_DO_DEFAULT, ("rc=%Rrc GCPhys=%RGp\n", rc, GCPhys));
unsigned iPage;
Assert(GCPhys >= pVirt->aPhysToVirt[iPage].Core.Key && GCPhys <= pVirt->aPhysToVirt[iPage].Core.KeyLast);
#ifdef IN_RING3
if (!pPhys)
Log5(("pgmPhysWriteHandler: GCPhys=%RGp cb=%#x pPage=%R[pgmpage] virt %s\n", GCPhys, cb, pPage, R3STRING(pVirt->pszDesc) ));
Log(("pgmPhysWriteHandler: GCPhys=%RGp cb=%#x pPage=%R[pgmpage] phys/virt %s/%s\n", GCPhys, cb, pPage, R3STRING(pVirt->pszDesc), R3STRING(pPhys->pszDesc) ));
rc2 = pVirt->CTX_SUFF(pfnHandler)(pVM, GCPtr, (void *)pvSrc, pvBuf, cb, PGMACCESSTYPE_READ, /*pVirt->CTX_SUFF(pvUser)*/ NULL);
AssertLogRelMsg(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_HANDLER_DO_DEFAULT, ("rc=%Rrc GCPhys=%RGp pPage=%R[pgmpage] %s\n", rc2, GCPhys, pPage, pVirt->pszDesc));
Log5(("pgmPhysWriteHandler: GCPhys=%RGp cb=%#x pPage=%R[pgmpage] virt %s [no handler]\n", GCPhys, cb, pPage, R3STRING(pVirt->pszDesc) ));
const void *pvSrc;
AssertLogRelMsgFailed(("pgmPhysGCPhys2CCPtrInternalReadOnly failed on %RGp / %R[pgmpage] -> %Rrc\n",
if (!pRam)
#ifdef IN_RING3
bool fGrabbedLock = false;
if (cbRead == 0)
#ifdef IN_RING3
fGrabbedLock = true;
goto l_End;
PPGMPHYSHANDLER pNode = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.pTreesR3->PhysHandlers, GCPhys);
/* Note! Dangerous assumption that HC handlers don't do anything that really requires an EMT lock! */
void *pvSrc = pgmDynMapHCPageOff(&pVM->pgm.s, PGM_PAGE_GET_HCPHYS(pPage) + (off & PAGE_OFFSET_MASK));
goto l_End;
goto l_End;
unsigned iPage;
/* Note! Dangerous assumption that HC handlers don't do anything that really requires an EMT lock! */
void *pvSrc = pgmDynMapHCPageOff(&pVM->pgm.s, PGM_PAGE_GET_HCPHYS(pPage) + (off & PAGE_OFFSET_MASK));
goto l_End;
goto l_End;
switch (pPage->HCPhys & (MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_ROM)) /** @todo PAGE FLAGS */
case MM_RAM_FLAGS_ROM:
void *pvSrc = pgmDynMapHCPageOff(&pVM->pgm.s, PGM_PAGE_GET_HCPHYS(pPage) + (off & PAGE_OFFSET_MASK));
goto l_End;
case MM_RAM_FLAGS_RESERVED:
goto l_End;
goto l_End;
AssertReleaseMsgFailed(("Unknown read at %RGp size %u implement the complex physical reading case %RHp\n",
pPage->HCPhys & (MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_ROM))); /** @todo PAGE FLAGS */
if ( !pRam
goto l_End;
#ifdef IN_RING3
if (fGrabbedLock)
#ifdef VBOX_WITH_NEW_PHYS_CODE
static void pgmPhysWriteHandler(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys, void const *pvBuf, size_t cbWrite)
int rc;
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys);
if (pCur)
#ifdef IN_RING3
Log5(("pgmPhysWriteHandler: GCPhys=%RGp cbRange=%#x pPage=%R[pgmpage] phys %s\n", GCPhys, cbRange, pPage, R3STRING(pCur->pszDesc) ));
rc = pCur->CTX_SUFF(pfnHandler)(pVM, GCPhys, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE, pCur->CTX_SUFF(pvUser));
AssertLogRelMsg(rc == VINF_SUCCESS, ("rc=%Rrc GCPhys=%RGp pPage=%R[pgmpage] %s\n", rc, GCPhys, pPage, pCur->pszDesc));
AssertLogRelMsgFailedReturnVoid(("pgmPhysGCPhys2CCPtrInternal failed on %RGp / %R[pgmpage] -> %Rrc\n",
unsigned iPage;
#ifdef IN_RING3
Log5(("pgmPhysWriteHandler: GCPhys=%RGp cbRange=%#x pPage=%R[pgmpage] virt %s\n", GCPhys, cbRange, pPage, R3STRING(pCur->pszDesc) ));
rc = pCur->CTX_SUFF(pfnHandler)(pVM, GCPtr, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE, /*pCur->CTX_SUFF(pvUser)*/ NULL);
AssertLogRelMsg(rc == VINF_SUCCESS, ("rc=%Rrc GCPhys=%RGp pPage=%R[pgmpage] %s\n", rc, GCPhys, pPage, pCur->pszDesc));
AssertLogRelMsgFailedReturnVoid(("pgmPhysGCPhys2CCPtrInternal failed on %RGp / %R[pgmpage] -> %Rrc\n",
if (!pvDst)
unsigned iVirtPage = 0;
offVirt = 0;
offVirtLast = (pVirt->aPhysToVirt[iVirtPage].Core.KeyLast & PAGE_OFFSET_MASK) - (GCPhys & PAGE_OFFSET_MASK);
pVirtPhys = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGetBestFit(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers,
if ( pVirtPhys
fMoreVirt = false;
if (pPhys)
offPhys = 0;
if ( pPhys
fMorePhys = false;
Log5(("pgmPhysWriteHandler: GCPhys=%RGp cbRange=%#x pPage=%R[pgmpage] miss\n", GCPhys, cbRange, pPage));
#ifdef IN_RING3
Log5(("pgmPhysWriteHandler: GCPhys=%RGp cbRange=%#x pPage=%R[pgmpage] phys %s\n", GCPhys, cbRange, pPage, R3STRING(pPhys->pszDesc) ));
rc = pPhys->CTX_SUFF(pfnHandler)(pVM, GCPhys, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE, pPhys->CTX_SUFF(pvUser));
AssertLogRelMsg(rc == VINF_SUCCESS || rc == VINF_PGM_HANDLER_DO_DEFAULT, ("rc=%Rrc GCPhys=%RGp pPage=%R[pgmpage] %s\n", rc, GCPhys, pPage, pPhys->pszDesc));
#ifdef IN_RING3
Log5(("pgmPhysWriteHandler: GCPhys=%RGp cbRange=%#x pPage=%R[pgmpage] phys %s\n", GCPhys, cbRange, pPage, R3STRING(pVirt->pszDesc) ));
rc = pVirt->CTX_SUFF(pfnHandler)(pVM, GCPtr, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE, /*pCur->CTX_SUFF(pvUser)*/ NULL);
AssertLogRelMsg(rc == VINF_SUCCESS || rc == VINF_PGM_HANDLER_DO_DEFAULT, ("rc=%Rrc GCPhys=%RGp pPage=%R[pgmpage] %s\n", rc, GCPhys, pPage, pVirt->pszDesc));
#ifdef IN_RING3
Log(("pgmPhysWriteHandler: overlapping phys and virt handlers at %RGp %R[pgmpage]; cbRange=%#x\n", GCPhys, pPage, cbRange));
Log5(("pgmPhysWriteHandler: GCPhys=%RGp cbRange=%#x pPage=%R[pgmpage] phys/virt %s/%s\n", GCPhys, cbRange, pPage, R3STRING(pPhys->pszDesc), R3STRING(pVirt->pszDesc) ));
rc = pPhys->CTX_SUFF(pfnHandler)(pVM, GCPhys, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE, pPhys->CTX_SUFF(pvUser));
AssertLogRelMsg(rc == VINF_SUCCESS || rc == VINF_PGM_HANDLER_DO_DEFAULT, ("rc=%Rrc GCPhys=%RGp pPage=%R[pgmpage] %s\n", rc, GCPhys, pPage, pPhys->pszDesc));
int rc2 = pVirt->CTX_SUFF(pfnHandler)(pVM, GCPtr, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE, /*pCur->CTX_SUFF(pvUser)*/ NULL);
AssertLogRelMsg(rc2 != VINF_SUCCESS && rc2 != VINF_PGM_HANDLER_DO_DEFAULT, ("rc=%Rrc GCPhys=%RGp pPage=%R[pgmpage] %s\n", rc, GCPhys, pPage, pVirt->pszDesc));
void *pvDst;
if (!pRam)
#ifdef IN_RING3
bool fGrabbedLock = false;
if (cbWrite == 0)
#ifdef IN_RING3
fGrabbedLock = true;
int rc;
#ifdef IN_RING3
if (fGrabbedLock)
PGMPhysWrite(pVM, GCPhys, pvBuf, cbWrite); /* try again; can't assume pRam is still valid (paranoia) */
goto l_End;
PPGMPHYSHANDLER pPhysNode = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.pTreesR3->PhysHandlers, GCPhys);
/* Note! Dangerous assumption that R3 handlers don't do anything that really requires an EMT lock! */
rc = pPhysNode->pfnHandlerR3(pVM, GCPhys, pvDst, (void *)pvBuf, cb, PGMACCESSTYPE_WRITE, pPhysNode->pvUserR3);
unsigned iPage;
/* Note! Dangerous assumption that R3 handlers don't do anything that really requires an EMT lock! */
rc2 = pVirtNode->pfnHandlerR3(pVM, (RTGCPTR)GCPtr, pvDst, (void *)pvBuf, cb, PGMACCESSTYPE_WRITE, 0);
void *pvDst = pgmDynMapHCPageOff(&pVM->pgm.s, PGM_PAGE_GET_HCPHYS(pPage) + (off & PAGE_OFFSET_MASK));
goto l_End;
goto l_End;
#ifdef IN_RING3
unsigned iPage;
/* Note! Dangerous assumption that R3 handlers don't do anything that really requires an EMT lock! */
void *pvDst = pgmDynMapHCPageOff(&pVM->pgm.s, PGM_PAGE_GET_HCPHYS(pPage) + (off & PAGE_OFFSET_MASK));
goto l_End;
goto l_End;
PPGMPHYSHANDLER pNode = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.pTreesR3->PhysHandlers, GCPhys);
/** @todo Dangerous assumption that HC handlers don't do anything that really requires an EMT lock! */
rc = pNode->pfnHandlerR3(pVM, GCPhys, pvDst, (void *)pvBuf, cb, PGMACCESSTYPE_WRITE, pNode->pvUserR3);
void *pvDst = pgmDynMapHCPageOff(&pVM->pgm.s, PGM_PAGE_GET_HCPHYS(pPage) + (off & PAGE_OFFSET_MASK));
goto l_End;
goto l_End;
switch (pPage->HCPhys & (MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_MMIO2)) /** @todo PAGE FLAGS */
case MM_RAM_FLAGS_MMIO2:
void *pvDst = pgmDynMapHCPageOff(&pVM->pgm.s, PGM_PAGE_GET_HCPHYS(pPage) + (off & PAGE_OFFSET_MASK));
goto l_End;
case MM_RAM_FLAGS_RESERVED:
goto l_End;
goto l_End;
AssertReleaseMsgFailed(("Unknown write at %RGp size %u implement the complex physical writing case %RHp\n",
(pPage->HCPhys & (MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_MMIO2)))); /** @todo PAGE FLAGS */
if ( !pRam
goto l_End;
#ifdef IN_RING3
if (fGrabbedLock)
if (!cb)
return VINF_SUCCESS;
void const *pvSrc;
return rc;
return VINF_SUCCESS;
return rc;
return VINF_SUCCESS;
if (!cb)
return VINF_SUCCESS;
void *pvDst;
return rc;
return VINF_SUCCESS;
return rc;
return VINF_SUCCESS;
if (!cb)
return VINF_SUCCESS;
void const *pvSrc;
return rc;
return VINF_SUCCESS;
return rc;
return VINF_SUCCESS;
if (!cb)
return VINF_SUCCESS;
void *pvDst;
return rc;
return VINF_SUCCESS;
return rc;
return VINF_SUCCESS;
if (!cb)
return VINF_SUCCESS;
void *pvDst;
return rc;
rc = PGMGstModifyPage(pVM, GCPtrDst, 1, X86_PTE_A | X86_PTE_D, ~(uint64_t)(X86_PTE_A | X86_PTE_D)); AssertRC(rc);
return VINF_SUCCESS;
rc = PGMGstModifyPage(pVM, GCPtrDst, 1, X86_PTE_A | X86_PTE_D, ~(uint64_t)(X86_PTE_A | X86_PTE_D)); AssertRC(rc);
return rc;
rc = PGMGstModifyPage(pVM, GCPtrDst, 1, X86_PTE_A | X86_PTE_D, ~(uint64_t)(X86_PTE_A | X86_PTE_D)); AssertRC(rc);
return VINF_SUCCESS;
rc = PGMGstModifyPage(pVM, GCPtrDst, 1, X86_PTE_A | X86_PTE_D, ~(uint64_t)(X86_PTE_A | X86_PTE_D)); AssertRC(rc);
int rc;
if (!cb)
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
int rc;
if (!cb)
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
VMMDECL(int) PGMPhysInterpretedRead(PVM pVM, PCPUMCTXCORE pCtxCore, void *pvDst, RTGCUINTPTR GCPtrSrc, size_t cb)
int rc;
void *pvSrc;
switch (rc)
case VINF_SUCCESS:
Log(("PGMPhysInterpretedRead: pvDst=%p pvSrc=%p cb=%d\n", pvDst, (uint8_t *)pvSrc + (GCPtrSrc & PAGE_OFFSET_MASK), cb));
return rc;
return VINF_SUCCESS;
void *pvSrc1;
switch (rc)
case VINF_SUCCESS:
return rc;
void *pvSrc2;
switch (rc)
case VINF_SUCCESS:
return rc;
return VINF_SUCCESS;
switch (rc)
case VINF_SUCCESS:
case VERR_PAGE_NOT_PRESENT:
return rc;
VMMDECL(int) PGMPhysInterpretedReadNoHandlers(PVM pVM, PCPUMCTXCORE pCtxCore, void *pvDst, RTGCUINTPTR GCPtrSrc, size_t cb, bool fRaiseTrap)
int rc;
const void *pvSrc;
switch (rc)
case VINF_SUCCESS:
return rc;
return VINF_SUCCESS;
const void *pvSrc;
switch (rc)
case VINF_SUCCESS:
return rc;
switch (rc)
case VINF_SUCCESS:
return rc;
return VINF_SUCCESS;
switch (rc)
case VINF_SUCCESS:
case VERR_PAGE_NOT_PRESENT:
return rc;
if (fRaiseTrap)
Log(("PGMPhysInterpretedReadNoHandlers: GCPtrSrc=%RGv cb=%#x -> Raised #PF(%#x)\n", GCPtrSrc, cb, uErr));
Log(("PGMPhysInterpretedReadNoHandlers: GCPtrSrc=%RGv cb=%#x -> #PF(%#x) [!raised]\n", GCPtrSrc, cb, uErr));
return rc;
VMMDECL(int) PGMPhysInterpretedWriteNoHandlers(PVM pVM, PCPUMCTXCORE pCtxCore, RTGCPTR GCPtrDst, const void *pvSrc, size_t cb, bool fRaiseTrap)
int rc;
&& CPUMGetGuestCPL(pVM, pCtxCore) <= 2) ) /** @todo it's 2, right? Check cpl check below as well. */
void *pvDst;
switch (rc)
case VINF_SUCCESS:
return rc;
rc = PGM_GST_PFN(ModifyPage,pVM)(pVM, GCPtrDst, 1, X86_PTE_A | X86_PTE_D, ~(uint64_t)(X86_PTE_A | X86_PTE_D));
return VINF_SUCCESS;
void *pvDst;
switch (rc)
case VINF_SUCCESS:
return rc;
switch (rc)
case VINF_SUCCESS:
return rc;
rc = PGM_GST_PFN(ModifyPage,pVM)(pVM, GCPtrDst, 1, (X86_PTE_A | X86_PTE_RW), ~(uint64_t)(X86_PTE_A | X86_PTE_RW));
rc = PGM_GST_PFN(ModifyPage,pVM)(pVM, GCPtrDst + cb1, 1, (X86_PTE_A | X86_PTE_RW), ~(uint64_t)(X86_PTE_A | X86_PTE_RW));
return VINF_SUCCESS;
switch (rc)
case VINF_SUCCESS:
case VERR_ACCESS_DENIED:
case VERR_PAGE_NOT_PRESENT:
return rc;
if (fRaiseTrap)
Log(("PGMPhysInterpretedWriteNoHandlers: GCPtrDst=%RGv cb=%#x -> Raised #PF(%#x)\n", GCPtrDst, cb, uErr));
Log(("PGMPhysInterpretedWriteNoHandlers: GCPtrDst=%RGv cb=%#x -> #PF(%#x) [!raised]\n", GCPtrDst, cb, uErr));
return rc;