PGMInline.h revision e3e2f9c4418bfc06191b71bce1533c9e1bc2df9c
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * PGM - Inlined functions.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Copyright (C) 2006-2012 Oracle Corporation
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * available from http://www.virtualbox.org. This file is free software;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * you can redistribute it and/or modify it under the terms of the GNU
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * General Public License (GPL) as published by the Free Software
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync/** @addtogroup grp_pgm_int Internals
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * @internal
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Gets the PGMRAMRANGE structure for a guest page.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * @returns Pointer to the RAM range on success.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * @returns NULL on a VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS condition.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * @param pVM Pointer to the VM.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * @param GCPhys The GC physical address.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncDECLINLINE(PPGMRAMRANGE) pgmPhysGetRange(PVM pVM, RTGCPHYS GCPhys)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync PPGMRAMRANGE pRam = pVM->pgm.s.CTX_SUFF(apRamRangesTlb)[PGM_RAMRANGE_TLB_IDX(GCPhys)];
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync STAM_COUNTER_INC(&pVM->pgm.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,RamRangeTlbHits));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Gets the PGMRAMRANGE structure for a guest page, if unassigned get the ram
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * range above it.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * @returns Pointer to the RAM range on success.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * @returns NULL if the address is located after the last range.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * @param pVM Pointer to the VM.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * @param GCPhys The GC physical address.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncDECLINLINE(PPGMRAMRANGE) pgmPhysGetRangeAtOrAbove(PVM pVM, RTGCPHYS GCPhys)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync PPGMRAMRANGE pRam = pVM->pgm.s.CTX_SUFF(apRamRangesTlb)[PGM_RAMRANGE_TLB_IDX(GCPhys)];
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync STAM_COUNTER_INC(&pVM->pgm.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,RamRangeTlbHits));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Gets the PGMPAGE structure for a guest page.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * @returns Pointer to the page on success.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * @returns NULL on a VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS condition.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * @param pVM Pointer to the VM.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * @param GCPhys The GC physical address.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncDECLINLINE(PPGMPAGE) pgmPhysGetPage(PVM pVM, RTGCPHYS GCPhys)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync PPGMRAMRANGE pRam = pVM->pgm.s.CTX_SUFF(apRamRangesTlb)[PGM_RAMRANGE_TLB_IDX(GCPhys)];
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync STAM_COUNTER_INC(&pVM->pgm.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,RamRangeTlbHits));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Gets the PGMPAGE structure for a guest page.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Old Phys code: Will make sure the page is present.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * @returns VBox status code.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * @retval VINF_SUCCESS and a valid *ppPage on success.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if the address isn't valid.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * @param pVM Pointer to the VM.
if ( !pRam
return VINF_SUCCESS;
DECLINLINE(int) pgmPhysGetPageWithHintEx(PVM pVM, RTGCPHYS GCPhys, PPPGMPAGE ppPage, PPGMRAMRANGE *ppRamHint)
if ( !pRam
if ( !pRam
return VINF_SUCCESS;
DECLINLINE(int) pgmPhysGetPageAndRangeEx(PVM pVM, RTGCPHYS GCPhys, PPPGMPAGE ppPage, PPGMRAMRANGE *ppRam)
if ( !pRam
return VINF_SUCCESS;
return rc;
return VINF_SUCCESS;
DECLINLINE(int) pgmRZDynMapHCPageInlined(PVMCPU pVCpu, RTHCPHYS HCPhys, void **ppv RTLOG_COMMA_SRC_POS_DECL)
return VINF_SUCCESS;
DECLINLINE(int) pgmRZDynMapGCPageV2Inlined(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void **ppv RTLOG_COMMA_SRC_POS_DECL)
if ( !pRam
return VINF_SUCCESS;
DECLINLINE(int) pgmRZDynMapGCPageInlined(PVMCPU pVCpu, RTGCPHYS GCPhys, void **ppv RTLOG_COMMA_SRC_POS_DECL)
return pgmRZDynMapGCPageV2Inlined(pVCpu->CTX_SUFF(pVM), pVCpu, GCPhys, ppv RTLOG_COMMA_SRC_POS_ARGS);
DECLINLINE(int) pgmRZDynMapGCPageOffInlined(PVMCPU pVCpu, RTGCPHYS GCPhys, void **ppv RTLOG_COMMA_SRC_POS_DECL)
if ( !pRam
return VINF_SUCCESS;
void *pv;
return pv;
DECLINLINE(void *) pgmPoolMapPageV2Inlined(PVM pVM, PVMCPU pVCpu, PPGMPOOLPAGE pPage RTLOG_COMMA_SRC_POS_DECL)
void *pv;
return pv;
#ifndef IN_RC
int rc;
return rc;
DECLINLINE(int) pgmPhysPageQueryTlbeWithPage(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys, PPPGMPAGEMAPTLBE ppTlbe)
int rc;
# ifndef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
return rc;
int rc = pgmRZDynMapGCPageInlined(pVCpu, pVCpu->pgm.s.GCPhysCR3, (void **)ppPd RTLOG_COMMA_SRC_POS);
return rc;
return VINF_SUCCESS;
int rc = pgmRZDynMapGCPageInlined(pVCpu, pVCpu->pgm.s.GCPhysCR3, (void **)&pGuestPD RTLOG_COMMA_SRC_POS);
return NULL;
return NULL;
return pGuestPD;
int rc = pgmRZDynMapGCPageOffInlined(pVCpu, pVCpu->pgm.s.GCPhysCR3, (void **)ppPdpt RTLOG_COMMA_SRC_POS);
return rc;
return VINF_SUCCESS;
return pGuestPdpt;
int rc = pgmRZDynMapGCPageOffInlined(pVCpu, pVCpu->pgm.s.GCPhysCR3, (void **)&pGuestPDPT RTLOG_COMMA_SRC_POS);
return NULL;
(void **)&pGuestPD
if ( !pGuestPD
if (pGuestPD)
return ZeroPde;
DECLINLINE(PX86PDPAE) pgmGstGetPaePDPtr(PVMCPU pVCpu, RTGCPTR GCPtr, unsigned *piPD, PX86PDPE pPdpe)
return NULL;
if (pPdpe)
return NULL;
return NULL;
(void **)&pGuestPD
return NULL;
if ( !pGuestPD
return pGuestPD;
#ifndef IN_RC
int rc = pgmRZDynMapGCPageInlined(pVCpu, pVCpu->pgm.s.GCPhysCR3, (void **)ppPml4 RTLOG_COMMA_SRC_POS);
return rc;
return VINF_SUCCESS;
return pGuestPml4;
int rc = pgmRZDynMapGCPageInlined(pVCpu, pVCpu->pgm.s.GCPhysCR3, (void **)&pGuestPml4 RTLOG_COMMA_SRC_POS);
return ZeroPde;
DECLINLINE(PX86PDPAE) pgmGstGetLongModePDPtr(PVMCPU pVCpu, RTGCPTR64 GCPtr, PX86PML4E *ppPml4e, PX86PDPE pPdpe, unsigned *piPD)
return NULL;
return NULL;
return NULL;
return NULL;
return NULL;
return NULL;
return NULL;
return pPD;
return (PX86PD)PGMPOOL_PAGE_2_PTR_V2(pVCpu->CTX_SUFF(pVM), pVCpu, pVCpu->pgm.s.CTX_SUFF(pShwPageCR3));
if (!pShwPde)
return ZeroPde;
return (PX86PDPT)PGMPOOL_PAGE_2_PTR_V2(pVCpu->CTX_SUFF(pVM), pVCpu, pVCpu->pgm.s.CTX_SUFF(pShwPageCR3));
return NULL;
PPGMPOOLPAGE pShwPde = pgmPoolGetPage(pVM->pgm.s.CTX_SUFF(pPool), pPdpt->a[iPdpt].u & X86_PDPE_PG_MASK);
return NULL;
PPGMPOOLPAGE pShwPde = pgmPoolGetPage(pVM->pgm.s.CTX_SUFF(pPool), pPdpt->a[iPdpt].u & X86_PDPE_PG_MASK);
if (!pShwPde)
return ZeroPde;
#ifndef IN_RC
return (PX86PML4)PGMPOOL_PAGE_2_PTR_V2(pVCpu->CTX_SUFF(pVM), pVCpu, pVCpu->pgm.s.CTX_SUFF(pShwPageCR3));
if (!pShwPml4)
return ZeroPml4e;
if (!pShwPml4)
return NULL;
if ( pHandler
return pHandler;
pHandler = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys);
if (pHandler)
return pHandler;
return PGM_PAGE_HNDL_PHYS_STATE_WRITE;
case PGMPHYSHANDLERTYPE_MMIO:
return PGM_PAGE_HNDL_PHYS_STATE_ALL;
case PGMVIRTHANDLERTYPE_WRITE:
return PGM_PAGE_HNDL_VIRT_STATE_WRITE;
case PGMVIRTHANDLERTYPE_ALL:
return PGM_PAGE_HNDL_VIRT_STATE_ALL;
("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias));
PPGMPHYS2VIRTHANDLER pRemove = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysRemove(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key); NOREF(pRemove);
("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias));
("wanted: pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n"
" got: pRemove=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias,
pRemove, pRemove->Core.Key, pRemove->Core.KeyLast, pRemove->offVirtHandler, pRemove->offNextAlias));
PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
PPGMPHYS2VIRTHANDLER pPrev = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key);
("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} pPrev=%p\n",
pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias, pPrev));
PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPrev + (pPrev->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
LogFlow(("pgmHandlerVirtualClearPage: removed %p:{.offNextAlias=%#RX32} from alias chain. prev %p:{.offNextAlias=%#RX32} [%RGp-%RGp]\n",
pPhys2Virt, pPhys2Virt->offNextAlias, pPrev, pPrev->offNextAlias, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast));
PPGMPHYS2VIRTHANDLER pNewNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} pPrev=%p\n",
pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias, pPrev));
pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offNextAlias, R3STRING(pCur->pszDesc)));
DECLINLINE(void) pgmTrackDerefGCPhys(PPGMPOOL pPool, PPGMPOOLPAGE pPoolPage, PPGMPAGE pPhysPage, uint16_t iPte)
# ifdef VBOX_STRICT
# ifdef LOG_ENABLED
Log2(("pgmTrackDerefGCPhys: %x -> %x pPhysPage=%R[pgmpage]\n", uOrg, PGM_PAGE_GET_TRACKING(pPhysPage), pPhysPage ));
pPage->cModifications = 1; /* reset counter (can't use 0, or else it will be reinserted in the modified list) */
#ifdef PGM_WITHOUT_MAPPINGS
#ifdef PGM_WITHOUT_MAPPINGS