PGMAll.cpp revision 11c599b71a8c202a506b8623af57432c3d415dda
b9e697e180c323785bf1cb8a29f5ec6288da8ec4Jaco Jooste * PGM - Page Manager and Monitor - All context code.
b9e697e180c323785bf1cb8a29f5ec6288da8ec4Jaco Jooste * Copyright (C) 2006-2007 Sun Microsystems, Inc.
b9e697e180c323785bf1cb8a29f5ec6288da8ec4Jaco Jooste * This file is part of VirtualBox Open Source Edition (OSE), as
b9e697e180c323785bf1cb8a29f5ec6288da8ec4Jaco Jooste * available from http://www.virtualbox.org. This file is free software;
b9e697e180c323785bf1cb8a29f5ec6288da8ec4Jaco Jooste * you can redistribute it and/or modify it under the terms of the GNU
b9e697e180c323785bf1cb8a29f5ec6288da8ec4Jaco Jooste * General Public License (GPL) as published by the Free Software
b9e697e180c323785bf1cb8a29f5ec6288da8ec4Jaco Jooste * Foundation, in version 2 as it comes in the "COPYING" file of the
ccf9d4a5c6453fa9f8b839baeee25147865fbb7dJames Phillpotts * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b9e697e180c323785bf1cb8a29f5ec6288da8ec4Jaco Jooste * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b9e697e180c323785bf1cb8a29f5ec6288da8ec4Jaco Jooste * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Clara, CA 95054 USA or visit http://www.sun.com if you need
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * additional information or have any questions.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts/*******************************************************************************
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts* Header Files *
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts*******************************************************************************/
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts/*******************************************************************************
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts* Structures and Typedefs *
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts*******************************************************************************/
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Stated structure for PGM_GST_NAME(HandlerVirtualUpdate) that's
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * passed to PGM_GST_NAME(VirtHandlerUpdateOne) during enumeration.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts /** The VM handle. */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts /** The todo flags. */
b9e697e180c323785bf1cb8a29f5ec6288da8ec4Jaco Jooste /** The CR4 register value. */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts/*******************************************************************************
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts* Internal Functions *
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts*******************************************************************************/
ca7a323358dc50374d5f281355842fb7edb3983eJames PhillpottsDECLINLINE(int) pgmShwGetLongModePDPtr(PVM pVM, RTGCPTR64 GCPtr, PX86PML4E *ppPml4e, PX86PDPT *ppPdpt, PX86PDPAE *ppPD);
ca7a323358dc50374d5f281355842fb7edb3983eJames PhillpottsDECLINLINE(int) pgmShwGetPAEPDPtr(PVM pVM, RTGCPTR GCPtr, PX86PDPT *ppPdpt, PX86PDPAE *ppPD);
ca7a323358dc50374d5f281355842fb7edb3983eJames PhillpottsDECLINLINE(int) pgmShwGetPaePoolPagePD(PPGM pPGM, RTGCPTR GCPtr, PPGMPOOLPAGE *ppShwPde);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Shadow - 32-bit mode
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define PGM_SHW_NAME(name) PGM_SHW_NAME_32BIT(name)
b9e697e180c323785bf1cb8a29f5ec6288da8ec4Jaco Jooste/* Guest - real mode */
7197110fbdb6deb7868581c455516161cbcf7e0fJaco Jooste#define PGM_GST_NAME(name) PGM_GST_NAME_REAL(name)
7197110fbdb6deb7868581c455516161cbcf7e0fJaco Jooste#define PGM_BTH_NAME(name) PGM_BTH_NAME_32BIT_REAL(name)
b9e697e180c323785bf1cb8a29f5ec6288da8ec4Jaco Jooste#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_32BIT_PT_FOR_PHYS
b9e697e180c323785bf1cb8a29f5ec6288da8ec4Jaco Jooste#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_32BIT_PD_PHYS
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts/* Guest - protected mode */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define PGM_GST_NAME(name) PGM_GST_NAME_PROT(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define PGM_BTH_NAME(name) PGM_BTH_NAME_32BIT_PROT(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_32BIT_PT_FOR_PHYS
b9e697e180c323785bf1cb8a29f5ec6288da8ec4Jaco Jooste#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_32BIT_PD_PHYS
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts/* Guest - 32-bit mode */
7197110fbdb6deb7868581c455516161cbcf7e0fJaco Jooste#define PGM_GST_NAME(name) PGM_GST_NAME_32BIT(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define PGM_BTH_NAME(name) PGM_BTH_NAME_32BIT_32BIT(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_32BIT_PT_FOR_32BIT_PT
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_32BIT_PT_FOR_32BIT_4MB
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_32BIT_PD
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Shadow - PAE mode
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define PGM_SHW_NAME(name) PGM_SHW_NAME_PAE(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_REAL(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts/* Guest - real mode */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define PGM_GST_NAME(name) PGM_GST_NAME_REAL(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_REAL(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PHYS
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_PAE_PDPT_PHYS
b9e697e180c323785bf1cb8a29f5ec6288da8ec4Jaco Jooste/* Guest - protected mode */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define PGM_GST_NAME(name) PGM_GST_NAME_PROT(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_PROT(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PHYS
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_PAE_PDPT_PHYS
b9e697e180c323785bf1cb8a29f5ec6288da8ec4Jaco Jooste/* Guest - 32-bit mode */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define PGM_GST_NAME(name) PGM_GST_NAME_32BIT(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_32BIT(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_32BIT_PT
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_32BIT_4MB
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_PAE_PDPT_FOR_32BIT
7197110fbdb6deb7868581c455516161cbcf7e0fJaco Jooste/* Guest - PAE mode */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define PGM_GST_NAME(name) PGM_GST_NAME_PAE(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_PAE(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PAE_PT
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_PAE_PDPT
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#ifndef IN_RC /* AMD64 implies VT-x/AMD-V */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Shadow - AMD64 mode
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define PGM_SHW_NAME(name) PGM_SHW_NAME_AMD64(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts/* Guest - protected mode (only used for AMD-V nested paging in 64 bits mode) */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define PGM_GST_NAME(name) PGM_GST_NAME_PROT(name)
7197110fbdb6deb7868581c455516161cbcf7e0fJaco Jooste# define PGM_BTH_NAME(name) PGM_BTH_NAME_AMD64_PROT(name)
7197110fbdb6deb7868581c455516161cbcf7e0fJaco Jooste# define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PHYS
74b502cf428d057e78572e9fd66fb2f1861887b0Jaco Jooste# define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_PAE_PD_PHYS
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts/* Guest - AMD64 mode */
74b502cf428d057e78572e9fd66fb2f1861887b0Jaco Jooste# define PGM_GST_NAME(name) PGM_GST_NAME_AMD64(name)
7197110fbdb6deb7868581c455516161cbcf7e0fJaco Jooste# define PGM_BTH_NAME(name) PGM_BTH_NAME_AMD64_AMD64(name)
7197110fbdb6deb7868581c455516161cbcf7e0fJaco Jooste# define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PAE_PT
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_64BIT_PML4
63ee0c9f26b85deae17137a3965738153e0b2d20Gabor Melkvi# endif /* VBOX_WITH_64_BITS_GUESTS */
7197110fbdb6deb7868581c455516161cbcf7e0fJaco Jooste * Shadow - Nested paging mode
7197110fbdb6deb7868581c455516161cbcf7e0fJaco Jooste# define PGM_SHW_NAME(name) PGM_SHW_NAME_NESTED(name)
7197110fbdb6deb7868581c455516161cbcf7e0fJaco Jooste/* Guest - real mode */
7197110fbdb6deb7868581c455516161cbcf7e0fJaco Jooste# define PGM_GST_NAME(name) PGM_GST_NAME_REAL(name)
7197110fbdb6deb7868581c455516161cbcf7e0fJaco Jooste# define PGM_BTH_NAME(name) PGM_BTH_NAME_NESTED_REAL(name)
ccf9d4a5c6453fa9f8b839baeee25147865fbb7dJames Phillpotts/* Guest - protected mode */
7197110fbdb6deb7868581c455516161cbcf7e0fJaco Jooste# define PGM_GST_NAME(name) PGM_GST_NAME_PROT(name)
7197110fbdb6deb7868581c455516161cbcf7e0fJaco Jooste# define PGM_BTH_NAME(name) PGM_BTH_NAME_NESTED_PROT(name)
7197110fbdb6deb7868581c455516161cbcf7e0fJaco Jooste/* Guest - 32-bit mode */
7197110fbdb6deb7868581c455516161cbcf7e0fJaco Jooste# define PGM_GST_NAME(name) PGM_GST_NAME_32BIT(name)
7197110fbdb6deb7868581c455516161cbcf7e0fJaco Jooste# define PGM_BTH_NAME(name) PGM_BTH_NAME_NESTED_32BIT(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts/* Guest - PAE mode */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define PGM_GST_NAME(name) PGM_GST_NAME_PAE(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define PGM_BTH_NAME(name) PGM_BTH_NAME_NESTED_PAE(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts/* Guest - AMD64 mode */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define PGM_GST_NAME(name) PGM_GST_NAME_AMD64(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define PGM_BTH_NAME(name) PGM_BTH_NAME_NESTED_AMD64(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# endif /* VBOX_WITH_64_BITS_GUESTS */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Shadow - EPT
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define PGM_SHW_NAME(name) PGM_SHW_NAME_EPT(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts/* Guest - real mode */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define PGM_GST_NAME(name) PGM_GST_NAME_REAL(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define PGM_BTH_NAME(name) PGM_BTH_NAME_EPT_REAL(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_EPT_PT_FOR_PHYS
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts/* Guest - protected mode */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define PGM_GST_NAME(name) PGM_GST_NAME_PROT(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define PGM_BTH_NAME(name) PGM_BTH_NAME_EPT_PROT(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_EPT_PT_FOR_PHYS
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts/* Guest - 32-bit mode */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define PGM_GST_NAME(name) PGM_GST_NAME_32BIT(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define PGM_BTH_NAME(name) PGM_BTH_NAME_EPT_32BIT(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_EPT_PT_FOR_PHYS
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts/* Guest - PAE mode */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define PGM_GST_NAME(name) PGM_GST_NAME_PAE(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define PGM_BTH_NAME(name) PGM_BTH_NAME_EPT_PAE(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_EPT_PT_FOR_PHYS
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts/* Guest - AMD64 mode */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define PGM_GST_NAME(name) PGM_GST_NAME_AMD64(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define PGM_BTH_NAME(name) PGM_BTH_NAME_EPT_AMD64(name)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_EPT_PT_FOR_PHYS
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts# endif /* VBOX_WITH_64_BITS_GUESTS */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#endif /* !IN_RC */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * #PF Handler.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @returns VBox status code (appropriate for trap handling and GC return).
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @param pVM VM Handle.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @param uErr The trap error code.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @param pRegFrame Trap register frame.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @param pvFault The fault address.
ca7a323358dc50374d5f281355842fb7edb3983eJames PhillpottsVMMDECL(int) PGMTrap0eHandler(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts LogFlow(("PGMTrap0eHandler: uErr=%RGu pvFault=%RGv eip=%RGv\n", uErr, pvFault, (RTGCPTR)pRegFrame->rip));
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts STAM_PROFILE_START(&pVM->pgm.s.StatRZTrap0e, a);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts STAM_STATS({ pVM->pgm.s.CTX_SUFF(pStatTrap0eAttribution) = NULL; } );
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Error code stats.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eUSNotPresentWrite);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eUSNotPresentRead);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eUSWrite);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eUSReserved);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eUSNXE);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eUSRead);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts { /* Supervisor */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eSVNotPresentWrite);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eSVNotPresentRead);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eSVWrite);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eSNXE);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eSVReserved);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#endif /* VBOX_WITH_STATISTICS */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Call the worker.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts int rc = PGM_BTH_PFN(Trap0eHandler, pVM)(pVM, uErr, pRegFrame, pvFault);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts STAM_STATS({ if (rc == VINF_EM_RAW_GUEST_TRAP) STAM_COUNTER_INC(&pVM->pgm.s.StatRZTrap0eGuestPF); });
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts STAM_STATS({ if (!pVM->pgm.s.CTX_SUFF(pStatTrap0eAttribution))
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts pVM->pgm.s.CTX_SUFF(pStatTrap0eAttribution) = &pVM->pgm.s.StatRZTrap0eTime2Misc; });
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts STAM_PROFILE_STOP_EX(&pVM->pgm.s.StatRZTrap0e, pVM->pgm.s.CTX_SUFF(pStatTrap0eAttribution), a);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#endif /* !IN_RING3 */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Prefetch a page
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Typically used to sync commonly used pages before entering raw mode
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * after a CR3 reload.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @returns VBox status code suitable for scheduling.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @retval VINF_SUCCESS on success.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @retval VINF_PGM_SYNC_CR3 if we're out of shadow pages or something like that.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @param pVM VM handle.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @param GCPtrPage Page to invalidate.
ca7a323358dc50374d5f281355842fb7edb3983eJames PhillpottsVMMDECL(int) PGMPrefetchPage(PVM pVM, RTGCPTR GCPtrPage)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts STAM_PROFILE_START(&pVM->pgm.s.CTX_MID_Z(Stat,Prefetch), a);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts int rc = PGM_BTH_PFN(PrefetchPage, pVM)(pVM, GCPtrPage);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts STAM_PROFILE_STOP(&pVM->pgm.s.CTX_MID_Z(Stat,Prefetch), a);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts AssertMsg(rc == VINF_SUCCESS || rc == VINF_PGM_SYNC_CR3 || RT_FAILURE(rc), ("rc=%Rrc\n", rc));
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Gets the mapping corresponding to the specified address (if any).
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @returns Pointer to the mapping.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @returns NULL if not
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @param pVM The virtual machine.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @param GCPtr The guest context pointer.
ca7a323358dc50374d5f281355842fb7edb3983eJames PhillpottsPPGMMAPPING pgmGetMapping(PVM pVM, RTGCPTR GCPtr)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts PPGMMAPPING pMapping = pVM->pgm.s.CTX_SUFF(pMappings);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts if ((uintptr_t)GCPtr < (uintptr_t)pMapping->GCPtr)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts if ((uintptr_t)GCPtr - (uintptr_t)pMapping->GCPtr < pMapping->cb)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Verifies a range of pages for read or write access
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Only checks the guest's page tables
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @returns VBox status code.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @param pVM VM handle.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @param Addr Guest virtual address to check
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @param cbSize Access size
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @param fAccess Access type (r/w, user/supervisor (X86_PTE_*))
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @remarks Current not in use.
ca7a323358dc50374d5f281355842fb7edb3983eJames PhillpottsVMMDECL(int) PGMIsValidAccess(PVM pVM, RTGCPTR Addr, uint32_t cbSize, uint32_t fAccess)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Validate input.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts AssertMsgFailed(("PGMIsValidAccess: invalid access type %08x\n", fAccess));
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts int rc = PGMGstGetPage(pVM, (RTGCPTR)Addr, &fPage, NULL);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts Log(("PGMIsValidAccess: access violation for %RGv rc=%d\n", Addr, rc));
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Check if the access would cause a page fault
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Note that hypervisor page directories are not present in the guest's tables, so this check
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * is sufficient.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts Log(("PGMIsValidAccess: access violation for %RGv attr %#llx vs %d:%d\n", Addr, fPage, fWrite, fUser));
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts && PAGE_ADDRESS(Addr) != PAGE_ADDRESS(Addr + cbSize))
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts return PGMIsValidAccess(pVM, Addr + PAGE_SIZE, (cbSize > PAGE_SIZE) ? cbSize - PAGE_SIZE : 1, fAccess);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Verifies a range of pages for read or write access
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Supports handling of pages marked for dirty bit tracking and CSAM
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @returns VBox status code.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @param pVM VM handle.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @param Addr Guest virtual address to check
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @param cbSize Access size
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * @param fAccess Access type (r/w, user/supervisor (X86_PTE_*))
ca7a323358dc50374d5f281355842fb7edb3983eJames PhillpottsVMMDECL(int) PGMVerifyAccess(PVM pVM, RTGCPTR Addr, uint32_t cbSize, uint32_t fAccess)
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts AssertMsg(!(fAccess & ~(X86_PTE_US | X86_PTE_RW)), ("PGMVerifyAccess: invalid access type %08x\n", fAccess));
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts int rc = PGMGstGetPage(pVM, (RTGCPTR)Addr, &fPageGst, NULL);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts Log(("PGMVerifyAccess: access violation for %RGv rc=%d\n", Addr, rc));
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Check if the access would cause a page fault
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Note that hypervisor page directories are not present in the guest's tables, so this check
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * is sufficient.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts const bool fWrite = !!(fAccess & X86_PTE_RW);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts const bool fUser = !!(fAccess & X86_PTE_US);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts Log(("PGMVerifyAccess: access violation for %RGv attr %#llx vs %d:%d\n", Addr, fPageGst, fWrite, fUser));
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Next step is to verify if we protected this page for dirty bit tracking or for CSAM scanning
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts rc = PGMShwGetPage(pVM, (RTGCPTR)Addr, NULL, NULL);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Page is not present in our page tables.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * Try to sync it!
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts Assert(X86_TRAP_PF_RW == X86_PTE_RW && X86_TRAP_PF_US == X86_PTE_US);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts uint32_t uErr = fAccess & (X86_TRAP_PF_RW | X86_TRAP_PF_US);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts rc = PGM_BTH_PFN(VerifyAccessSyncPage, pVM)(pVM, Addr, fPageGst, uErr);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts AssertMsg(rc == VINF_SUCCESS, ("PGMShwGetPage %RGv failed with %Rrc\n", Addr, rc));
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts#if 0 /* def VBOX_STRICT; triggers too often now */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts * This check is a bit paranoid, but useful.
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts /** @note this will assert when writing to monitored pages (a bit annoying actually) */
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts rc = PGMShwGetPage(pVM, (RTGCPTR)Addr, &fPageShw, NULL);
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts if ( (rc == VERR_PAGE_NOT_PRESENT || RT_FAILURE(rc))
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts AssertMsgFailed(("Unexpected access violation for %RGv! rc=%Rrc write=%d user=%d\n",
ca7a323358dc50374d5f281355842fb7edb3983eJames Phillpotts Addr, rc, fWrite && !(fPageShw & X86_PTE_RW), fUser && !(fPageShw & X86_PTE_US)));
return VINF_EM_RAW_GUEST_TRAP;
return rc;
int rc;
#ifndef IN_RING3
return rc;
#ifdef IN_RC
return VINF_PGM_SYNC_CR3;
return VINF_EM_RAW_EMULATE_INSTR;
#ifdef IN_RING3
#ifndef VBOX_WITH_PGMPOOL_PAGING_ONLY
return rc;
return rc;
return VINF_SUCCESS;
int rc;
return VINF_PGM_SYNC_CR3;
/* In 32 bits PAE mode we *must* invalidate the TLB when changing a PDPT entry; the CPU fetches them only during cr3 load, so any
ASMReloadCR3();
return VINF_SUCCESS;
return VINF_SUCCESS;
#ifndef IN_RC
int pgmShwSyncLongModePDPtr(PVM pVM, RTGCPTR64 GCPtr, PX86PML4E pGstPml4e, PX86PDPE pGstPdpe, PX86PDPAE *ppPD)
int rc;
if (!fNestedPaging)
return VINF_PGM_SYNC_CR3;
if (!fNestedPaging)
rc = pgmPoolAlloc(pVM, pGstPdpe->u & X86_PDPE_PG_MASK, PGMPOOLKIND_64BIT_PD_FOR_64BIT_PD, pShwPage->idx, iPdPt, &pShwPage);
rc = pgmPoolAlloc(pVM, GCPdPt + RT_BIT_64(62) /* hack: make the address unique */, PGMPOOLKIND_64BIT_PD_FOR_PHYS, pShwPage->idx, iPdPt, &pShwPage);
return VINF_PGM_SYNC_CR3;
return VINF_SUCCESS;
DECLINLINE(int) pgmShwGetLongModePDPtr(PVM pVM, RTGCPTR64 GCPtr, PX86PML4E *ppPml4e, PX86PDPT *ppPdpt, PX86PDPAE *ppPD)
if (ppPml4e)
return VERR_PAGE_MAP_LEVEL4_NOT_PRESENT;
return VINF_SUCCESS;
int rc;
rc = pgmPoolAlloc(pVM, GCPml4, PGMPOOLKIND_EPT_PDPT_FOR_PHYS, PGMPOOL_IDX_NESTED_ROOT, iPml4, &pShwPage);
rc = pgmPoolAlloc(pVM, GCPml4 + RT_BIT_64(63) /* hack: make the address unique */, PGMPOOLKIND_EPT_PDPT_FOR_PHYS, PGMPOOL_IDX_NESTED_ROOT, iPml4, &pShwPage);
return VINF_PGM_SYNC_CR3;
if (ppPdpt)
rc = pgmPoolAlloc(pVM, GCPdPt + RT_BIT_64(62) /* hack: make the address unique */, PGMPOOLKIND_64BIT_PD_FOR_PHYS, pShwPage->idx, iPdPt, &pShwPage);
return VINF_PGM_SYNC_CR3;
return VINF_SUCCESS;
return rc;
switch (enmShadowMode)
case PGMMODE_32_BIT:
case PGMMODE_PAE:
case PGMMODE_PAE_NX:
case PGMMODE_AMD64:
case PGMMODE_AMD64_NX:
case PGMMODE_EPT:
case PGMMODE_NESTED:
switch (enmShadowMode)
case PGMMODE_32_BIT:
case PGMMODE_PAE:
case PGMMODE_PAE_NX:
case PGMMODE_AMD64:
case PGMMODE_AMD64_NX:
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)
case PGMMODE_PAE:
case PGMMODE_PAE_NX:
case PGMMODE_AMD64:
case PGMMODE_AMD64_NX:
#ifndef VBOX_WITH_PGMPOOL_PAGING_ONLY
if (fGlobal)
#ifndef VBOX_WITH_PGMPOOL_PAGING_ONLY
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 VINF_SUCCESS;
fGlobal = true;
#ifdef PGMPOOL_WITH_MONITORING
return rc;
case PGMMODE_PAE:
case PGMMODE_PAE_NX:
case PGMMODE_AMD64:
case PGMMODE_AMD64_NX:
#ifdef IN_RING3
return rc;
#ifndef VBOX_WITH_PGMPOOL_PAGING_ONLY
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)
#ifdef IN_RC
return rc;
if (!pRam)
return VINF_SUCCESS;
if (!pRam)
return VINF_SUCCESS;
# ifdef IN_RC
register unsigned iCache;
static const uint8_t au8Trans[MM_HYPER_DYNAMIC_SIZE >> PAGE_SHIFT][RT_ELEMENTS(pVM->pgm.s.aHCPhysDynPageMapCache)] =
/* The cache can get out of sync with locked entries. (10 locked, 2 overwrites its cache position, last = 11, lookup 2 -> page 10 instead of 2) */
return VINF_SUCCESS;
# ifdef VBOX_WITH_PGMPOOL_PAGING_ONLY
iPage++;
pVM->pgm.s.aHCPhysDynPageMapCache[iPage & (RT_ELEMENTS(pVM->pgm.s.aHCPhysDynPageMapCache) - 1)] = HCPhys;
return VINF_SUCCESS;
unsigned iPage;
Assert(GCPage >= pVM->pgm.s.pbDynPageMapBaseGC && GCPage < (pVM->pgm.s.pbDynPageMapBaseGC + MM_HYPER_DYNAMIC_SIZE));
unsigned iPage;
AssertCompile(RT_ELEMENTS(pVM->pgm.s.aHCPhysDynPageMapCache) == RT_ELEMENTS(pVM->pgm.s.aLockedDynPageMapCache));
Assert(GCPage >= pVM->pgm.s.pbDynPageMapBaseGC && GCPage < (pVM->pgm.s.pbDynPageMapBaseGC + MM_HYPER_DYNAMIC_SIZE));
# ifdef VBOX_STRICT
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;