PGMAll.cpp revision 1999ae03c34840fa4d712fd2e020120b2cb7182a
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * PGM - Page Manager and Monitor - All context code.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Copyright (C) 2006-2007 Oracle Corporation
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * This file is part of VirtualBox Open Source Edition (OSE), as
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * available from http://www.virtualbox.org. This file is free software;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * you can redistribute it and/or modify it under the terms of the GNU
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * General Public License (GPL) as published by the Free Software
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Foundation, in version 2 as it comes in the "COPYING" file of the
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis/*******************************************************************************
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis* Header Files *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis*******************************************************************************/
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis/*******************************************************************************
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis* Structures and Typedefs *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis*******************************************************************************/
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Stated structure for PGM_GST_NAME(HandlerVirtualUpdate) that's
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * passed to PGM_GST_NAME(VirtHandlerUpdateOne) during enumeration.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis /** The VM handle. */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis /** The VMCPU handle. */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis /** The todo flags. */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis /** The CR4 register value. */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis/*******************************************************************************
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis* Internal Functions *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis*******************************************************************************/
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr JasiukajtisDECLINLINE(int) pgmShwGetLongModePDPtr(PVMCPU pVCpu, RTGCPTR64 GCPtr, PX86PML4E *ppPml4e, PX86PDPT *ppPdpt, PX86PDPAE *ppPD);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr JasiukajtisDECLINLINE(int) pgmShwGetPaePoolPagePD(PVMCPU pVCpu, RTGCPTR GCPtr, PPGMPOOLPAGE *ppShwPde);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisstatic int pgmShwSyncLongModePDPtr(PVMCPU pVCpu, RTGCPTR64 GCPtr, X86PGPAEUINT uGstPml4e, X86PGPAEUINT uGstPdpe, PX86PDPAE *ppPD);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisstatic int pgmShwGetEPTPDPtr(PVMCPU pVCpu, RTGCPTR64 GCPtr, PEPTPDPT *ppPdpt, PEPTPD *ppPD);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Shadow - 32-bit mode
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define PGM_SHW_NAME(name) PGM_SHW_NAME_32BIT(name)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis/* Guest - real mode */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define PGM_GST_NAME(name) PGM_GST_NAME_REAL(name)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define PGM_BTH_NAME(name) PGM_BTH_NAME_32BIT_REAL(name)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_32BIT_PT_FOR_PHYS
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_32BIT_PD_PHYS
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis/* Guest - protected mode */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define PGM_GST_NAME(name) PGM_GST_NAME_PROT(name)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define PGM_BTH_NAME(name) PGM_BTH_NAME_32BIT_PROT(name)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_32BIT_PT_FOR_PHYS
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_32BIT_PD_PHYS
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis/* Guest - 32-bit mode */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define PGM_GST_NAME(name) PGM_GST_NAME_32BIT(name)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define PGM_BTH_NAME(name) PGM_BTH_NAME_32BIT_32BIT(name)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_32BIT_PT_FOR_32BIT_PT
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_32BIT_PT_FOR_32BIT_4MB
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_32BIT_PD
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Shadow - PAE mode
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define PGM_SHW_NAME(name) PGM_SHW_NAME_PAE(name)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_REAL(name)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis/* Guest - real mode */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define PGM_GST_NAME(name) PGM_GST_NAME_REAL(name)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_REAL(name)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PHYS
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_PAE_PDPT_PHYS
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis/* Guest - protected mode */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define PGM_GST_NAME(name) PGM_GST_NAME_PROT(name)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_PROT(name)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PHYS
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_PAE_PDPT_PHYS
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis/* Guest - 32-bit mode */
#include "PGMGstDefs.h"
#include "PGMAllBth.h"
#include "PGMGstDefs.h"
#include "PGMAllGst.h"
#include "PGMAllBth.h"
# include "PGMAllShw.h"
# include "PGMGstDefs.h"
# include "PGMAllBth.h"
# ifdef VBOX_WITH_64_BITS_GUESTS
# include "PGMGstDefs.h"
# include "PGMAllGst.h"
# include "PGMAllBth.h"
# include "PGMAllShw.h"
# include "PGMGstDefs.h"
# include "PGMAllBth.h"
# include "PGMGstDefs.h"
# include "PGMAllBth.h"
# include "PGMGstDefs.h"
# include "PGMAllBth.h"
# include "PGMGstDefs.h"
# include "PGMAllBth.h"
# ifdef VBOX_WITH_64_BITS_GUESTS
# include "PGMGstDefs.h"
# include "PGMAllBth.h"
# include "PGMAllShw.h"
# include "PGMGstDefs.h"
# include "PGMAllBth.h"
# include "PGMGstDefs.h"
# include "PGMAllBth.h"
# include "PGMGstDefs.h"
# include "PGMAllBth.h"
# include "PGMGstDefs.h"
# include "PGMAllBth.h"
# ifdef VBOX_WITH_64_BITS_GUESTS
# include "PGMGstDefs.h"
# include "PGMAllBth.h"
#ifndef IN_RING3
Log(("PGMTrap0eHandler: uErr=%RGx pvFault=%RGv eip=%04x:%RGv cr3=%RGp\n", uErr, pvFault, pRegFrame->cs, (RTGCPTR)pRegFrame->rip, (RTGCPHYS)CPUMGetGuestCR3(pVCpu)));
#ifdef VBOX_WITH_STATISTICS
bool fLockTaken = false;
if (fLockTaken)
# ifdef IN_RING0
Log(("WARNING: Unexpected VERR_PAGE_TABLE_NOT_PRESENT (%d) for page fault at %RGv error code %x (rip=%RGv)\n", rc, pvFault, uErr, pRegFrame->rip));
/* Some kind of inconsistency in the SMP case; it's safe to just execute the instruction again; not sure about single VCPU VMs though. */
STAM_STATS({ if (rc == VINF_EM_RAW_GUEST_TRAP) STAM_COUNTER_INC(&pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0eGuestPF); });
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;
return rc;
while (pMapping)
return pMapping;
return NULL;
* @param fAccess Access type (r/w, user/supervisor (X86_PTE_*))
return VERR_INVALID_PARAMETER;
return VINF_EM_RAW_GUEST_TRAP;
Log(("PGMIsValidAccess: access violation for %RGv attr %#llx vs %d:%d\n", Addr, fPage, fWrite, fUser));
return VINF_EM_RAW_GUEST_TRAP;
return PGMIsValidAccess(pVCpu, Addr + PAGE_SIZE, (cbSize > PAGE_SIZE) ? cbSize - PAGE_SIZE : 1, fAccess);
return rc;
* @param fAccess Access type (r/w, user/supervisor (X86_PTE_*))
AssertMsg(!(fAccess & ~(X86_PTE_US | X86_PTE_RW)), ("PGMVerifyAccess: invalid access type %08x\n", fAccess));
return VINF_EM_RAW_GUEST_TRAP;
Log(("PGMVerifyAccess: access violation for %RGv attr %#llx vs %d:%d\n", Addr, fPageGst, fWrite, fUser));
return VINF_EM_RAW_GUEST_TRAP;
return rc;
return VINF_EM_RAW_GUEST_TRAP;
return rc;
int rc;
#ifndef IN_RING3
#ifdef IN_RC
return VINF_PGM_SYNC_CR3;
return VINF_EM_RAW_EMULATE_INSTR;
#ifdef IN_RING3
return rc;
VMMDECL(VBOXSTRICTRC) PGMInterpretInstruction(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault)
return rc;
return rc;
DECLINLINE(int) pdmShwModifyPage(PVMCPU pVCpu, RTGCPTR GCPtr, uint64_t fFlags, uint64_t fMask, uint32_t fOpFlags)
return rc;
int rc;
# if defined(IN_RC)
ASMReloadCR3();
return VINF_SUCCESS;
PPGMPOOLPAGE pShwPde = pgmPoolGetPage(pVM->pgm.s.CTX_SUFF(pPool), pPdpt->a[iPdPt].u & X86_PDPE_PG_MASK);
return VINF_SUCCESS;
#ifndef IN_RC
static int pgmShwSyncLongModePDPtr(PVMCPU pVCpu, RTGCPTR64 GCPtr, X86PGPAEUINT uGstPml4e, X86PGPAEUINT uGstPdpe, PX86PDPAE *ppPD)
int rc;
return VINF_SUCCESS;
DECLINLINE(int) pgmShwGetLongModePDPtr(PVMCPU pVCpu, RTGCPTR64 GCPtr, PX86PML4E *ppPml4e, PX86PDPT *ppPdpt, PX86PDPAE *ppPD)
if (ppPml4e)
return VERR_PAGE_MAP_LEVEL4_NOT_PRESENT;
Log4(("pgmShwGetLongModePDPtr %RGv -> *ppPD=%p PDE=%p/%RX64\n", GCPtr, *ppPD, &(*ppPD)->a[(GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK], (*ppPD)->a[(GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK].u));
return VINF_SUCCESS;
int rc;
rc = pgmPoolAlloc(pVM, GCPml4, PGMPOOLKIND_EPT_PDPT_FOR_PHYS, PGMPOOL_IDX_NESTED_ROOT, iPml4, &pShwPage);
if (ppPdpt)
return VINF_SUCCESS;
#ifdef IN_RING0
int pgmShwSyncNestedPageLocked(PVMCPU pVCpu, RTGCPHYS GCPhysFault, uint32_t cPages, PGMMODE enmShwPagingMode)
int rc;
switch (enmShwPagingMode)
case PGMMODE_32_BIT:
case PGMMODE_PAE:
case PGMMODE_PAE_NX:
case PGMMODE_AMD64:
case PGMMODE_AMD64_NX:
case PGMMODE_EPT:
return rc;
VMMDECL(int) PGMGstModifyPage(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask)
return rc;
# ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
return VINF_SUCCESS;
return rc;
# ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
return VINF_SUCCESS;
return rc;
# ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
if (fChanged)
return VINF_SUCCESS;
# ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
return rc;
# ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
return VINF_SUCCESS;
return rc;
return rc;
case SUPPAGINGMODE_32_BIT:
case SUPPAGINGMODE_PAE:
case SUPPAGINGMODE_PAE_GLOBAL:
case SUPPAGINGMODE_PAE_NX:
case SUPPAGINGMODE_AMD64:
case SUPPAGINGMODE_AMD64_NX:
case PGMMODE_32_BIT:
case PGMMODE_PAE:
case PGMMODE_PAE_NX:
case PGMMODE_AMD64:
case PGMMODE_AMD64_NX:
case PGMMODE_EPT:
case PGMMODE_NESTED:
if (fGlobal)
LogFlow(("PGMFlushTLB: cr3=%RX64 OldCr3=%RX64 fGlobal=%d\n", cr3, pVCpu->pgm.s.GCPhysCR3, fGlobal));
case PGMMODE_PAE:
case PGMMODE_PAE_NX:
case PGMMODE_AMD64:
case PGMMODE_AMD64_NX:
if (fGlobal)
# ifdef PGMPOOL_WITH_OPTIMIZED_DIRTY_PT
if (fGlobal)
return rc;
case PGMMODE_PAE:
case PGMMODE_PAE_NX:
case PGMMODE_AMD64:
case PGMMODE_AMD64_NX:
AssertRCSuccess(rc); /* Assumes VINF_PGM_SYNC_CR3 doesn't apply to nested paging. */ /** @todo this isn't true for the mac, but we need hw to test/fix this. */
return rc;
int rc;
return rc;
return VINF_SUCCESS;
fGlobal = true;
VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3), VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL)));
case PGMMODE_PAE:
case PGMMODE_PAE_NX:
case PGMMODE_AMD64:
case PGMMODE_AMD64_NX:
#ifdef IN_RING3
return VINF_PGM_SYNC_CR3;
return VINF_PGM_SYNC_CR3;
return rc;
return VINF_SUCCESS;
#ifdef IN_RING3
return VINF_PGM_CHANGE_MODE;
case SUPPAGINGMODE_32_BIT:
return PGMMODE_32_BIT;
case SUPPAGINGMODE_PAE:
case SUPPAGINGMODE_PAE_GLOBAL:
return PGMMODE_PAE;
case SUPPAGINGMODE_PAE_NX:
return PGMMODE_PAE_NX;
case SUPPAGINGMODE_AMD64:
return PGMMODE_AMD64;
case SUPPAGINGMODE_AMD64_NX:
return PGMMODE_AMD64_NX;
return PGMMODE_INVALID;
switch (enmMode)
if (fNxe)
/*pVCpu->pgm.s.fGst32BitMbzBigPdeMask - N/A */
/*pVCpu->pgm.s.fGstPaeMbzPdpeMask - N/A */
/*pVCpu->pgm.s.fGst32BitMbzBigPdeMask - N/A */
/*pVCpu->pgm.s.fGstPaeMbzPdpeMask -N/A */
return rc;
int pgmRZDynMapGCPageCommon(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void **ppv RTLOG_COMMA_SRC_POS_DECL)
int rc;
void *pv;
return rc;
void *pvUser)
cch = 0;
#define IS_PART_INCLUDED(lvl) ( !(fFlags & RTSTR_F_PRECISION) || cchPrecision == (lvl) || cchPrecision >= (lvl)+10 )
static const char s_achPageTypes[8][4] = { "INV", "RAM", "MI2", "M2A", "SHA", "ROM", "MIO", "BAD" };
cch += RTStrFormatNumber(&szTmp[cch], PGM_PAGE_GET_HCPHYS(pPage), 16, 12, 0, RTSTR_F_ZEROPAD | RTSTR_F_64BIT);
cch += RTStrFormatNumber(&szTmp[cch], PGM_PAGE_GET_PAGEID(pPage), 16, 7, 0, RTSTR_F_ZEROPAD | RTSTR_F_32BIT);
cch += RTStrFormatNumber(&szTmp[cch], PGM_PAGE_GET_TD_IDX(pPage), 16, 4, 0, RTSTR_F_ZEROPAD | RTSTR_F_16BIT);
return cch;
static DECLCALLBACK(size_t) pgmFormatTypeHandlerRamRange(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
void *pvUser)
return cch;
/** Format type andlers to be registered/deregistered. */
} g_aPgmFormatTypes[] =
# ifdef IN_RING0
return rc;
return VINF_SUCCESS;
#ifdef VBOX_STRICT
unsigned cErrors = 0;
cErrors++;
return cErrors;
return cErrors;