PGMAllPhys.cpp revision 8739e2db2c064b0b6dc80722ea107d81701f4704
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * PGM - Page Manager and Monitor, Physical Memory Addressing.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * available from http://www.virtualbox.org. This file is free software;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * you can redistribute it and/or modify it under the terms of the GNU
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * General Public License (GPL) as published by the Free Software
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * additional information or have any questions.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/*******************************************************************************
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync* Defined Constants And Macros *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync*******************************************************************************/
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/** @def PGM_IGNORE_RAM_FLAGS_RESERVED
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Don't respect the MM_RAM_FLAGS_RESERVED flag when converting to HC addresses.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Since this flag is currently incorrectly kept set for ROM regions we will
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * have to ignore it for now so we don't break stuff.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @todo this has been fixed now I believe, remove this hack.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/*******************************************************************************
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync* Header Files *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync*******************************************************************************/
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * \#PF Handler callback for Guest ROM range write access.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * We simply ignore the writes or fall back to the recompiler if we don't support the instruction.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns VBox status code (appropritate for trap handling and GC return).
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pVM VM Handle.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param uErrorCode CPU Error code.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pRegFrame Trap register frame.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pvFault The fault address (cr2).
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param GCPhysFault The GC physical address corresponding to pvFault.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pvUser User argument. Pointer to the ROM range structure.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncVMMDECL(int) pgmPhysRomWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync uint32_t iPage = (GCPhysFault - pRom->GCPhys) >> PAGE_SHIFT;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * If it's a simple instruction which doesn't change the cpu state
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * we will simply skip it. Otherwise we'll have to defer it to REM.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rc = EMInterpretDisasOne(pVM, pRegFrame, &Cpu, &cbOp);
0f81043c307886fc3e8d0479c4e4120b35c6d0b9vboxsync && Cpu.mode == CPUMODE_32BIT /** @todo why does this matter? */
0f81043c307886fc3e8d0479c4e4120b35c6d0b9vboxsync && !(Cpu.prefix & (PREFIX_REPNE | PREFIX_REP | PREFIX_SEG)))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /** @todo Find other instructions we can safely skip, possibly
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * adding this kind of detection to DIS or EM. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatRZGuestROMWriteHandled);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rc = PGMHandlerPhysicalPageTempOff(pVM, pRom->GCPhys, GCPhysFault & X86_PTE_PG_MASK);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync break; /** @todo Must restart the instruction, not use the interpreter! */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* Handle it in ring-3 because it's *way* easier there. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync AssertMsgFailedReturn(("enmProt=%d iPage=%d GCPhysFault=%RGp\n",
98427c0ab08697e468c26dc33ee9571308577867vboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatRZGuestROMWriteUnhandled);
98427c0ab08697e468c26dc33ee9571308577867vboxsync#endif /* IN_RING3 */
98427c0ab08697e468c26dc33ee9571308577867vboxsync * Checks if Address Gate 20 is enabled or not.
98427c0ab08697e468c26dc33ee9571308577867vboxsync * @returns true if enabled.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns false if disabled.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pVM VM handle.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync LogFlow(("PGMPhysIsA20Enabled %d\n", pVM->pgm.s.fA20Enabled));
0f81043c307886fc3e8d0479c4e4120b35c6d0b9vboxsync return !!pVM->pgm.s.fA20Enabled ; /* stupid MS compiler doesn't trust me. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Validates a GC physical address.
0f81043c307886fc3e8d0479c4e4120b35c6d0b9vboxsync * @returns true if valid.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns false if invalid.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pVM The VM handle.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param GCPhys The physical address to validate.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncVMMDECL(bool) PGMPhysIsGCPhysValid(PVM pVM, RTGCPHYS GCPhys)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Checks if a GC physical address is a normal page,
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * i.e. not ROM, MMIO or reserved.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns true if normal.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns false if invalid, ROM, MMIO or reserved page.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pVM The VM handle.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param GCPhys The physical address to check.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncVMMDECL(bool) PGMPhysIsGCPhysNormal(PVM pVM, RTGCPHYS GCPhys)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync && !(pPage->HCPhys & (MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_ROM | MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_MMIO2));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Converts a GC physical address to a HC physical address.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns VINF_SUCCESS on success.
0f81043c307886fc3e8d0479c4e4120b35c6d0b9vboxsync * @returns VERR_PGM_PHYS_PAGE_RESERVED it it's a valid GC physical
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * page but has no physical backing.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if it's not a valid
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * GC physical address.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pVM The VM handle.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param GCPhys The GC physical address to convert.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pHCPhys Where to store the HC physical address on success.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncVMMDECL(int) PGMPhysGCPhys2HCPhys(PVM pVM, RTGCPHYS GCPhys, PRTHCPHYS pHCPhys)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync int rc = pgmPhysGetPageEx(&pVM->pgm.s, GCPhys, &pPage);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (RT_UNLIKELY(pPage->HCPhys & MM_RAM_FLAGS_RESERVED)) /** @todo PAGE FLAGS */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *pHCPhys = PGM_PAGE_GET_HCPHYS(pPage) | (GCPhys & PAGE_OFFSET_MASK);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Invalidates the GC page mapping TLB.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pVM The VM handle.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncVMMDECL(void) PGMPhysInvalidatePageGCMapTLB(PVM pVM)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* later */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Invalidates the ring-0 page mapping TLB.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pVM The VM handle.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncVMMDECL(void) PGMPhysInvalidatePageR0MapTLB(PVM pVM)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Invalidates the ring-3 page mapping TLB.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pVM The VM handle.
50f998bb47f333d10515d4c12ad01a4e92a0747bvboxsyncVMMDECL(void) PGMPhysInvalidatePageR3MapTLB(PVM pVM)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.PhysTlbHC.aEntries); i++)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pVM->pgm.s.PhysTlbHC.aEntries[i].GCPhys = NIL_RTGCPHYS;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Makes sure that there is at least one handy page ready for use.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * This will also take the appropriate actions when reaching water-marks.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns The following VBox status codes.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @retval VINF_SUCCESS on success.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @retval VERR_EM_NO_MEMORY if we're really out of memory.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pVM The VM handle.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @remarks Must be called from within the PGM critical section. It may
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * nip back to ring-3/0 in some cases.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /** @remarks
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * low-water mark logic for R0 & GC:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * - 75%: Set FF.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * - 50%: Force return to ring-3 ASAP.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * For ring-3 there is a little problem wrt to the recompiler, so:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * - 75%: Set FF.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * - 50%: Try allocate pages; on failure we'll force REM to quite ASAP.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * The basic idea is that we should be able to get out of any situation with
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * only 50% of handy pages remaining.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * At the moment we'll not adjust the number of handy pages relative to the
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * actual VM RAM committment, that's too much work for now.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync AssertMsg(pVM->pgm.s.cHandyPages <= RT_ELEMENTS(pVM->pgm.s.aHandyPages), ("%d\n", pVM->pgm.s.cHandyPages));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync || pVM->pgm.s.cHandyPages - 1 <= RT_ELEMENTS(pVM->pgm.s.aHandyPages) / 2 /* 50% */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync Log(("PGM: cHandyPages=%u out of %u -> allocate more\n", pVM->pgm.s.cHandyPages, RT_ELEMENTS(pVM->pgm.s.aHandyPages)));
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync int rc = VMMR0CallHost(pVM, VMMCALLHOST_PGM_ALLOCATE_HANDY_PAGES, 0);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync int rc = VMMGCCallHost(pVM, VMMCALLHOST_PGM_ALLOCATE_HANDY_PAGES, 0);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync Assert(VM_FF_ISSET(pVM, VM_FF_PGM_NEED_HANDY_PAGES));
e2bd93b4f9c38c9b01eb960ba7bc1fc9c4d38ce8vboxsync && pVM->pgm.s.cHandyPages <= RT_ELEMENTS(pVM->pgm.s.aHandyPages),
e2bd93b4f9c38c9b01eb960ba7bc1fc9c4d38ce8vboxsync else if (pVM->pgm.s.cHandyPages - 1 <= (RT_ELEMENTS(pVM->pgm.s.aHandyPages) / 4) * 3) /* 75% */
beb683ae4828ae01a388a124997a2517fbe78190vboxsync if (pVM->pgm.s.cHandyPages - 1 <= RT_ELEMENTS(pVM->pgm.s.aHandyPages) / 2)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync Log(("PGM: VM_FF_TO_R3 - cHandyPages=%u out of %u\n", pVM->pgm.s.cHandyPages - 1, RT_ELEMENTS(pVM->pgm.s.aHandyPages)));
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync * Replace a zero or shared page with new page that we can write to.
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync * @returns The following VBox status codes.
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync * @retval VINF_SUCCESS on success, pPage is modified.
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync * @retval VINF_PGM_SYNC_CR3 on success and a page pool flush is pending.
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync * @retval VERR_EM_NO_MEMORY if we're totally out of memory.
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync * @todo Propagate VERR_EM_NO_MEMORY up the call tree.
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync * @param pVM The VM address.
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync * @param pPage The physical page tracking structure. This will
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync * be modified on success.
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync * @param GCPhys The address of the page.
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync * @remarks Must be called from within the PGM critical section. It may
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync * nip back to ring-3/0 in some cases.
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync * @remarks This function shouldn't really fail, however if it does
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync * it probably means we've screwed up the size of the amount
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync * and/or the low-water mark of handy pages. Or, that some
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync * device I/O is causing a lot of pages to be allocated while
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync * while the host is in a low-memory condition.
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsyncint pgmPhysAllocPage(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys)
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync LogFlow(("pgmPhysAllocPage: %R[pgmpage] %RGp\n", pPage, GCPhys));
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync AssertMsg(PGM_PAGE_IS_ZERO(pPage) || PGM_PAGE_IS_SHARED(pPage), ("%R[pgmpage] %RGp\n", pPage, GCPhys));
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync * Flush any shadow page table mappings of the page.
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync * When VBOX_WITH_NEW_LAZY_PAGE_ALLOC isn't defined, there shouldn't be any.
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync bool fFlushTLBs = false;
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync int rc = pgmPoolTrackFlushGCPhys(pVM, pPage, &fFlushTLBs);
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync /* nothing */;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync AssertMsgFailedReturn(("%Rrc\n", rc), VERR_INTERNAL_ERROR);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Ensure that we've got a page handy, take it and use it.
84161d024cfbfa8f0fd7e79b8c925e1f2ba77009vboxsync /* re-assert preconditions since pgmPhysEnsureHandyPage may do a context switch. */
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync AssertMsg(PGM_PAGE_IS_ZERO(pPage) || PGM_PAGE_IS_SHARED(pPage), ("%R[pgmpage] %RGp\n", pPage, GCPhys));
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync AssertMsg(iHandyPage < RT_ELEMENTS(pVM->pgm.s.aHandyPages), ("%d\n", iHandyPage));
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync Assert(pVM->pgm.s.aHandyPages[iHandyPage].HCPhysGCPhys != NIL_RTHCPHYS);
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync Assert(!(pVM->pgm.s.aHandyPages[iHandyPage].HCPhysGCPhys & ~X86_PTE_PAE_PG_MASK));
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync Assert(pVM->pgm.s.aHandyPages[iHandyPage].idPage != NIL_GMM_PAGEID);
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync Assert(pVM->pgm.s.aHandyPages[iHandyPage].idSharedPage == NIL_GMM_PAGEID);
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * There are one or two action to be taken the next time we allocate handy pages:
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * - Tell the GMM (global memory manager) what the page is being used for.
d1d4bf58f99da14d0aaa7bcc728a359c8a7eb7bdvboxsync * (Speeds up replacement operations - sharing and defragmenting.)
d1d4bf58f99da14d0aaa7bcc728a359c8a7eb7bdvboxsync * - If the current backing is shared, it must be freed.
d1d4bf58f99da14d0aaa7bcc728a359c8a7eb7bdvboxsync const RTHCPHYS HCPhys = pVM->pgm.s.aHandyPages[iHandyPage].HCPhysGCPhys;
d1d4bf58f99da14d0aaa7bcc728a359c8a7eb7bdvboxsync pVM->pgm.s.aHandyPages[iHandyPage].HCPhysGCPhys = GCPhys & ~(RTGCPHYS)PAGE_OFFSET_MASK;
d1d4bf58f99da14d0aaa7bcc728a359c8a7eb7bdvboxsync pVM->pgm.s.aHandyPages[iHandyPage].idSharedPage = PGM_PAGE_GET_PAGEID(pPage);
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync Assert(PGM_PAGE_GET_PAGEID(pPage) != NIL_GMM_PAGEID);
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync Log2(("PGM: Replaced shared page %#x at %RGp with %#x / %RHp\n", PGM_PAGE_GET_PAGEID(pPage),
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync GCPhys, pVM->pgm.s.aHandyPages[iHandyPage].idPage, HCPhys));
98427c0ab08697e468c26dc33ee9571308577867vboxsync STAM_COUNTER_INC(&pVM->pgm.s.CTX_MID_Z(Stat,PageReplaceShared));
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync AssertMsgFailed(("TODO: copy shared page content")); /** @todo err.. what about copying the page content? */
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync Log2(("PGM: Replaced zero page %RGp with %#x / %RHp\n", GCPhys, pVM->pgm.s.aHandyPages[iHandyPage].idPage, HCPhys));
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatRZPageReplaceZero);
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync Assert(pVM->pgm.s.aHandyPages[iHandyPage].idSharedPage == NIL_GMM_PAGEID);
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * Do the PGMPAGE modifications.
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync PGM_PAGE_SET_PAGEID(pPage, pVM->pgm.s.aHandyPages[iHandyPage].idPage);
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync PGM_PAGE_SET_STATE(pPage, PGM_PAGE_STATE_ALLOCATED);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Deal with pages that are not writable, i.e. not in the ALLOCATED state.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns VBox status code.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @retval VINF_SUCCESS on success.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @retval VINF_PGM_SYNC_CR3 on success and a page pool flush is pending.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @retval VERR_PGM_PHYS_PAGE_RESERVED it it's a valid page but has no physical backing.
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * @param pVM The VM address.
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * @param pPage The physical page tracking structure.
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync * @param GCPhys The address of the page.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @remarks Called from within the PGM critical section.
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsyncint pgmPhysPageMakeWritable(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys)
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync PGM_PAGE_SET_STATE(pPage, PGM_PAGE_STATE_ALLOCATED);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* fall thru */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync default: /* to shut up GCC */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Zero pages can be dummy pages for MMIO or reserved memory,
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * so we need to check the flags before joining cause with
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * shared page replacement.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* fall thru */
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
#ifdef IN_RING3
PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys);
const void *pvSrc;
int rc = pCur->CTX_SUFF(pfnHandler)(pVM, GCPhys, (void *)pvSrc, pvBuf, cb, PGMACCESSTYPE_READ, pCur->CTX_SUFF(pvUser));
AssertLogRelMsgFailed(("pgmPhysGCPhys2CCPtrInternalReadOnly failed on %RGp / %R[pgmpage] -> %Rrc\n",
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;