PGMR0.cpp revision b40179b44fea65b72b2f226f62af1ed7bd3c48fc
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * PGM - Page Manager and Monitor, Ring-0.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Copyright (C) 2007-2010 Oracle Corporation
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * available from http://www.virtualbox.org. This file is free software;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * General Public License (GPL) as published by the Free Software
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/*******************************************************************************
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync* Header Files *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync*******************************************************************************/
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Instantiate the ring-0 header/code templates.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_32BIT_PROT(name)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_PROT(name)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_AMD64_PROT(name)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_EPT_PROT(name)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Worker function for PGMR3PhysAllocateHandyPages and pgmPhysEnsureHandyPage.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @returns The following VBox status codes.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @retval VINF_SUCCESS on success. FF cleared.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @retval VINF_EM_NO_MEMORY if we're out of memory. The FF is set in this case.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pVM The VM handle.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param pVCpu The VMCPU handle.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @remarks Must be called from within the PGM critical section. The caller
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * must clear the new pages.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncVMMR0DECL(int) PGMR0PhysAllocateHandyPages(PVM pVM, PVMCPU pVCpu)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Assert(PDMCritSectIsOwnerEx(&pVM->pgm.s.CritSect, pVCpu->idCpu));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Check for error injection.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Try allocate a full set of handy pages.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync AssertReturn(iFirst <= RT_ELEMENTS(pVM->pgm.s.aHandyPages), VERR_INTERNAL_ERROR);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t cPages = RT_ELEMENTS(pVM->pgm.s.aHandyPages) - iFirst;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = GMMR0AllocateHandyPages(pVM, pVCpu->idCpu, cPages, cPages, &pVM->pgm.s.aHandyPages[iFirst]);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (uint32_t i = 0; i < RT_ELEMENTS(pVM->pgm.s.aHandyPages); i++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Assert(pVM->pgm.s.aHandyPages[i].idPage != NIL_GMM_PAGEID);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Assert(pVM->pgm.s.aHandyPages[i].idPage <= GMM_PAGEID_LAST);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Assert(pVM->pgm.s.aHandyPages[i].idSharedPage == NIL_GMM_PAGEID);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Assert(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys != NIL_RTHCPHYS);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Assert(!(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys & ~X86_PTE_PAE_PG_MASK));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pVM->pgm.s.cHandyPages = RT_ELEMENTS(pVM->pgm.s.aHandyPages);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* We're ASSUMING that GMM has updated all the entires before failing us. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (i = iFirst; i < RT_ELEMENTS(pVM->pgm.s.aHandyPages); i++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Assert(pVM->pgm.s.aHandyPages[i].idPage == NIL_GMM_PAGEID);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Assert(pVM->pgm.s.aHandyPages[i].idSharedPage == NIL_GMM_PAGEID);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Assert(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys == NIL_RTHCPHYS);
#ifdef VBOX_STRICT
return rc;
int rc = GMMR0AllocateLargePage(pVM, pVCpu->idCpu, _2M, &pVM->pgm.s.aLargeHandyPage[0].idPage, &pVM->pgm.s.aLargeHandyPage[0].HCPhysGCPhys);
return rc;
VMMR0DECL(int) PGMR0Trap0eHandlerNestedPaging(PVM pVM, PVMCPU pVCpu, PGMMODE enmShwPagingMode, RTGCUINT uErr,
int rc;
LogFlow(("PGMTrap0eHandler: uErr=%RGx GCPhysFault=%RGp eip=%RGv\n", uErr, GCPhysFault, (RTGCPTR)pRegFrame->rip));
AssertMsg( enmShwPagingMode == PGMMODE_32_BIT || enmShwPagingMode == PGMMODE_PAE || enmShwPagingMode == PGMMODE_PAE_NX
|| enmShwPagingMode == PGMMODE_AMD64 || enmShwPagingMode == PGMMODE_AMD64_NX || enmShwPagingMode == PGMMODE_EPT,
#ifdef VBOX_WITH_STATISTICS
bool fLockTaken = false;
switch(enmShwPagingMode)
case PGMMODE_32_BIT:
case PGMMODE_PAE:
case PGMMODE_PAE_NX:
case PGMMODE_AMD64:
case PGMMODE_AMD64_NX:
case PGMMODE_EPT:
AssertFailed();
if (fLockTaken)
Log(("WARNING: Unexpected VERR_PAGE_TABLE_NOT_PRESENT (%d) for page fault at %RGp error code %x (rip=%RGv)\n", rc, GCPhysFault, uErr, pRegFrame->rip));
/* Some kind of inconsistency in the SMP case; it's safe to just execute the instruction again; not sure about
pVCpu->pgm.s.CTX_SUFF(pStatTrap0eAttribution) = &pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0eTime2Misc; });
STAM_PROFILE_STOP_EX(&pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0e, pVCpu->pgm.s.CTX_SUFF(pStatTrap0eAttribution), a);
return rc;
VMMR0DECL(VBOXSTRICTRC) PGMR0Trap0eHandlerNPMisconfig(PVM pVM, PVMCPU pVCpu, PGMMODE enmShwPagingMode,
#ifdef PGM_WITH_MMIO_OPTIMIZATIONS
Log6(("PGMR0Trap0eHandlerNPMisconfig: calling %p(,%#x,,%RGp,%p)\n", pfnHandler, uErr, GCPhysFault, pvUser));
rc = pfnHandler(pVM, uErr == UINT32_MAX ? RTGCPTR_MAX : uErr, pRegFrame, GCPhysFault, GCPhysFault, pvUser);
#ifdef VBOX_WITH_STATISTICS
if (pHandler)
return rc;
return VERR_INTERNAL_ERROR_4;