PGMAllPhys.cpp revision b74ca013e5f201a2dd371e6c438433ceac12af30
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * PGM - Page Manager and Monitor, Physical Memory Addressing.
a7f76a6a5289c5c56005df14dce59bfbceb3b132vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * available from http://www.virtualbox.org. This file is free software;
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * 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.
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * additional information or have any questions.
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync/*******************************************************************************
86b51be433c7032578ae50e94ebe590cc428448bvboxsync* Defined Constants And Macros *
86b51be433c7032578ae50e94ebe590cc428448bvboxsync*******************************************************************************/
86b51be433c7032578ae50e94ebe590cc428448bvboxsync/** @def PGM_IGNORE_RAM_FLAGS_RESERVED
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * Don't respect the MM_RAM_FLAGS_RESERVED flag when converting to HC addresses.
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * Since this flag is currently incorrectly kept set for ROM regions we will
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * have to ignore it for now so we don't break stuff.
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * @todo this has been fixed now I believe, remove this hack.
86b51be433c7032578ae50e94ebe590cc428448bvboxsync/*******************************************************************************
86b51be433c7032578ae50e94ebe590cc428448bvboxsync* Header Files *
86b51be433c7032578ae50e94ebe590cc428448bvboxsync*******************************************************************************/
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * \#PF Handler callback for Guest ROM range write access.
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * We simply ignore the writes or fall back to the recompiler if we don't support the instruction.
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * @returns VBox status code (appropritate for trap handling and GC return).
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * @param pVM VM Handle.
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * @param uErrorCode CPU Error code.
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * @param pRegFrame Trap register frame.
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * @param pvFault The fault address (cr2).
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * @param GCPhysFault The GC physical address corresponding to pvFault.
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * @param pvUser User argument. Pointer to the ROM range structure.
86b51be433c7032578ae50e94ebe590cc428448bvboxsyncVMMDECL(int) pgmPhysRomWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser)
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * If it's a simple instruction which doesn't change the cpu state
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * we will simply skip it. Otherwise we'll have to defer it to REM.
86b51be433c7032578ae50e94ebe590cc428448bvboxsync rc = EMInterpretDisasOne(pVM, pRegFrame, &Cpu, &cbOp);
86b51be433c7032578ae50e94ebe590cc428448bvboxsync && Cpu.mode == CPUMODE_32BIT /** @todo why does this matter? */
86b51be433c7032578ae50e94ebe590cc428448bvboxsync && !(Cpu.prefix & (PREFIX_REPNE | PREFIX_REP | PREFIX_SEG)))
78edef1df590edefed7cef91b6bcbf4d84f79947vboxsync /** @todo Find other instructions we can safely skip, possibly
86b51be433c7032578ae50e94ebe590cc428448bvboxsync * adding this kind of detection to DIS or EM. */
5e0d5717f4742e9fc86690c4406e0af249336bbfvboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatRZGuestROMWriteHandled);
86b51be433c7032578ae50e94ebe590cc428448bvboxsync rc = PGMHandlerPhysicalPageTempOff(pVM, pRom->GCPhys, GCPhysFault & X86_PTE_PG_MASK);
86b51be433c7032578ae50e94ebe590cc428448bvboxsync /* Handle it in ring-3 because it's *way* easier there. */
5e0d5717f4742e9fc86690c4406e0af249336bbfvboxsync AssertMsgFailedReturn(("enmProt=%d iPage=%d GCPhysFault=%RGp\n",
a0ed9c35186427ae0abbd14b1cfdf43bf2dc8659vboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatRZGuestROMWriteUnhandled);
a0ed9c35186427ae0abbd14b1cfdf43bf2dc8659vboxsync#endif /* IN_RING3 */
a0ed9c35186427ae0abbd14b1cfdf43bf2dc8659vboxsync * Checks if Address Gate 20 is enabled or not.
a0ed9c35186427ae0abbd14b1cfdf43bf2dc8659vboxsync * @returns true if enabled.
return pPage
&& !(pPage->HCPhys & (MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_ROM | MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_MMIO2));
return rc;
#ifndef PGM_IGNORE_RAM_FLAGS_RESERVED
return VERR_PGM_PHYS_PAGE_RESERVED;
return VINF_SUCCESS;
#ifdef IN_RING3
Log(("PGM: cHandyPages=%u out of %u -> allocate more\n", pVM->pgm.s.cHandyPages - 1 <= RT_ELEMENTS(pVM->pgm.s.aHandyPages)));
#ifdef IN_RING3
/** @todo call PGMR0PhysAllocateHandyPages directly - need to make sure we can call kernel code first and deal with the seeding fallback. */
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;
return rc;
AssertMsg(PGM_PAGE_IS_ZERO(pPage) || PGM_PAGE_IS_SHARED(pPage), ("%d %RGp\n", PGM_PAGE_GET_STATE(pPage), GCPhys));
Log2(("PGM: Replaced zero page %RGp with %#x / %RHp\n", GCPhys, pVM->pgm.s.aHandyPages[iHandyPage].idPage, HCPhys));
return VINF_SUCCESS;
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 VINF_SUCCESS;
if (!pMap)
#ifdef IN_RING0
return rc;
return VINF_SUCCESS;
return VINF_SUCCESS;
if (!pRam)
void *pv;
return rc;
return VINF_SUCCESS;
#ifdef VBOX_WITH_NEW_PHYS_CODE
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
#ifdef VBOX_WITH_NEW_PHYS_CODE
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;
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;
VMMDECL(int) PGMPhysGCPtr2R3PtrByGstCR3(PVM pVM, RTGCPTR GCPtr, uint64_t cr3, unsigned fFlags, PRTR3PTR pR3Ptr)
#ifdef VBOX_WITH_NEW_PHYS_CODE
int rc;
rc = PGMPhysGCPhys2R3Ptr(pVM, pgmGstGet4MBPhysPage(&pVM->pgm.s, Pde) | ((RTGCUINTPTR)GCPtr & X86_PAGE_4M_OFFSET_MASK),
return PGMPhysGCPhys2R3Ptr(pVM, (Pte.u & X86_PTE_PG_MASK) | ((RTGCUINTPTR)GCPtr & PAGE_OFFSET_MASK),
rc = PGMPhysGCPhys2R3Ptr(pVM, (Pde.u & X86_PDE2M_PAE_PG_MASK) | ((RTGCUINTPTR)GCPtr & X86_PAGE_2M_OFFSET_MASK),
return PGMPhysGCPhys2R3Ptr(pVM, (Pte.u & X86_PTE_PAE_PG_MASK) | ((RTGCUINTPTR)GCPtr & PAGE_OFFSET_MASK),
return rc;
#ifdef IN_RING3
#ifdef IN_RING3
bool fGrabbedLock = false;
if (cbRead == 0)
#ifdef IN_RING3
fGrabbedLock = true;
goto 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 end;
goto 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 end;
goto 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 end;
case MM_RAM_FLAGS_RESERVED:
goto end;
goto 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 end;
end:
#ifdef IN_RING3
if (fGrabbedLock)
#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 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 end;
goto 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 end;
goto 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 end;
goto 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 end;
case MM_RAM_FLAGS_RESERVED:
goto end;
goto 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 end;
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;