PGMAllShw.h revision 5476bd9ec30ebad9ed9e39aa8a4ff2c49bede2d7
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * VBox - Page Manager, Shadow Paging Template - All context code.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2007 innotek GmbH
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * available from http://www.virtualbox.org. This file is free software;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync/*******************************************************************************
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync* Defined Constants And Macros *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync*******************************************************************************/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#else /* 32 bits PAE mode */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# define SHW_TOTAL_PD_ENTRIES (X86_PG_PAE_ENTRIES*X86_PG_PAE_PDPTE_ENTRIES)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*******************************************************************************
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync* Internal Functions *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync*******************************************************************************/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGM_SHW_DECL(int, GetPage)(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGM_SHW_DECL(int, ModifyPage)(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGM_SHW_DECL(int, GetPDEByIndex)(PVM pVM, uint32_t iPD, PX86PDEPAE pPde);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGM_SHW_DECL(int, SetPDEByIndex)(PVM pVM, uint32_t iPD, X86PDEPAE Pde);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGM_SHW_DECL(int, ModifyPDEByIndex)(PVM pVM, uint32_t iPD, uint64_t fFlags, uint64_t fMask);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Gets effective page information (from the VMM page directory).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM VM Handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param GCPtr Guest Context virtual address of the page.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pfFlags Where to store the flags. These are X86_PTE_*.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pHCPhys Where to store the HC physical address of the page.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This is page aligned.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @remark You should use PGMMapGetPage() for pages in a mapping.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGM_SHW_DECL(int, GetPage)(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Get the PDE.
fdea543f71872a3ec3909536a4fce37ab7aa3a8bvboxsync * For the first 4G we have preallocated page directories.
fdea543f71872a3ec3909536a4fce37ab7aa3a8bvboxsync * Since the two upper levels contains only fixed flags, we skip those when possible.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const unsigned iPdptr = (GCPtr >> X86_PDPTR_SHIFT) & X86_PDPTR_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const unsigned iPd = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Pde = CTXMID(pVM->pgm.s.ap,PaePDs)[iPdptr]->a[iPd];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const unsigned iPml4 = (GCPtr >> X86_PML4_SHIFT) & X86_PML4_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync X86PML4E Pml4e = CTXMID(pVM->pgm.s.p,PaePML4)->a[iPml4];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* PDPTR */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = PGM_HCPHYS_2_PTR(pVM, Pml4e.u & X86_PML4E_PG_MASK, &pPdPtr);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const unsigned iPdptr = (GCPtr >> X86_PDPTR_SHIFT) & X86_PDPTR_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_HCPHYS_2_PTR(pVM, Pdpe.u & X86_PDPE_PG_MASK, &pPd);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const unsigned iPd = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* GC_ARCH_BITS == 64 */
a11c569636fa6838bd423f4631a9660a5a84204bvboxsync const unsigned iPdptr = (GCPtr >> X86_PDPTR_SHIFT) & X86_PDPTR_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const unsigned iPd = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync X86PDEPAE Pde = CTXMID(pVM->pgm.s.ap,PaePDs)[iPdptr]->a[iPd];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#else /* PGM_TYPE_32BIT */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const unsigned iPd = (GCPtr >> X86_PD_SHIFT) & X86_PD_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Get PT entry.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = PGM_HCPHYS_2_PTR(pVM, Pde.u & SHW_PDE_PG_MASK, &pPT);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else /* mapping: */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PPGMMAPPING pMap = pgmGetMapping(pVM, (RTGCPTR)GCPtr);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgReturn(pMap, ("GCPtr=%VGv\n", GCPtr), VERR_INTERNAL_ERROR);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pPT = pMap->aPTs[(GCPtr - pMap->GCPtr) >> X86_PD_SHIFT].CTXALLSUFF(pPT);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#else /* PAE and AMD64: */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pPT = pMap->aPTs[(GCPtr - pMap->GCPtr) >> X86_PD_SHIFT].CTXALLSUFF(paPaePTs);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const unsigned iPt = (GCPtr >> SHW_PT_SHIFT) & SHW_PT_MASK;
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync * Store the results.
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync * RW and US flags depend on the entire page transation hierarchy - except for
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * legacy PAE which has a simplified PDPE.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync & ((Pde.u & (X86_PTE_RW | X86_PTE_US)) | ~(uint64_t)(X86_PTE_RW | X86_PTE_US));
78a205e3fc6719d59e8c561b3d287d3a4f879852vboxsync * Modify page flags for a range of pages in the shadow context.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The existing flags are ANDed with the fMask and ORed with the fFlags.
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync * @returns VBox status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param GCPtr Virtual address of the first page in the range. Page aligned!
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cb Size (in bytes) of the range to apply the modification to. Page aligned!
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fFlags The OR mask - page flags X86_PTE_*, excluding the page mask of course.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fMask The AND mask - page flags X86_PTE_*.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Be extremely CAREFUL with ~'ing values because they can be 32-bit!
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @remark You must use PGMMapModifyPage() for pages in a mapping.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGM_SHW_DECL(int, ModifyPage)(PVM pVM, RTGCUINTPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Walk page tables and pages till we're done.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Get the PDE.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * For the first 4G we have preallocated page directories.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Since the two upper levels contains only fixed flags, we skip those when possible.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const unsigned iPdptr = (GCPtr >> X86_PDPTR_SHIFT) & X86_PDPTR_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const unsigned iPd = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Pde = CTXMID(pVM->pgm.s.ap,PaePDs)[iPdptr]->a[iPd];
8a132edc1577cbe2a19cd778c1b2bea6ae5e8515vboxsync const unsigned iPml4 = (GCPtr >> X86_PML4_SHIFT) & X86_PML4_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync X86PML4E Pml4e = CTXMID(pVM->pgm.s.p,PaePML4)->a[iPml4];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* PDPTR */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = PGM_HCPHYS_2_PTR(pVM, Pml4e.u & X86_PML4E_PG_MASK, &pPdPtr);
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync const unsigned iPdptr = (GCPtr >> X86_PDPTR_SHIFT) & X86_PDPTR_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_HCPHYS_2_PTR(pVM, Pdpe.u & X86_PDPE_PG_MASK, &pPd);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const unsigned iPd = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* GC_ARCH_BITS == 64 */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const unsigned iPdptr = (GCPtr >> X86_PDPTR_SHIFT) & X86_PDPTR_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const unsigned iPd = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync X86PDEPAE Pde = CTXMID(pVM->pgm.s.ap,PaePDs)[iPdptr]->a[iPd];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#else /* PGM_TYPE_32BIT */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const unsigned iPd = (GCPtr >> X86_PD_SHIFT) & X86_PD_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Map the page table.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = PGM_HCPHYS_2_PTR(pVM, Pde.u & SHW_PDE_PG_MASK, &pPT);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync unsigned iPTE = (GCPtr >> SHW_PT_SHIFT) & SHW_PT_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pPT->a[iPTE].u = (pPT->a[iPTE].u & (fMask | SHW_PTE_PG_MASK)) | (fFlags & ~SHW_PTE_PG_MASK);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* next page */
0e77737b0ba913683e614db11463b31ca67aacbevboxsync * Retrieve shadow PDE
0e77737b0ba913683e614db11463b31ca67aacbevboxsync * @returns VBox status code.
0e77737b0ba913683e614db11463b31ca67aacbevboxsync * @param pVM The virtual machine.
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync * @param iPD Shadow PDE index.
0e77737b0ba913683e614db11463b31ca67aacbevboxsync * @param pPde Where to store the shadow PDE entry.
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsyncPGM_SHW_DECL(int, GetPDEByIndex)(PVM pVM, unsigned iPD, PX86PDEPAE pPde)
2d53f6e472561965d363674e17f48d3bdffc24d3vboxsync#if PGM_SHW_TYPE == PGM_TYPE_32BIT || PGM_SHW_TYPE == PGM_TYPE_PAE
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync * Get page directory addresses.
2d53f6e472561965d363674e17f48d3bdffc24d3vboxsync PX86PDE pPdeSrc = &CTXMID(pVM->pgm.s.p,32BitPD)->a[iPD];
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync PX86PDEPAE pPdeSrc = &CTXMID(pVM->pgm.s.ap,PaePDs)[0]->a[iPD]; /* We treat this as a PD with 2048 entries. */
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync * Set shadow PDE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The virtual machine.
d98e61ba075ed7d0b567a5d884bc85d643fe3de7vboxsync * @param iPD Shadow PDE index.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param Pde Shadow PDE.
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsyncPGM_SHW_DECL(int, SetPDEByIndex)(PVM pVM, unsigned iPD, X86PDEPAE Pde)
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync#if PGM_SHW_TYPE == PGM_TYPE_32BIT || PGM_SHW_TYPE == PGM_TYPE_PAE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Get page directory addresses and update the specified entry.
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync Assert(Pde.au32[1] == 0); /* First uint32_t is backwards compatible. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PX86PDE pPdeDst = &CTXMID(pVM->pgm.s.p,32BitPD)->a[iPD];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PX86PDEPAE pPdeDst = &CTXMID(pVM->pgm.s.ap,PaePDs)[0]->a[iPD]; /* We treat this as a PD with 2048 entries. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Modify shadow PDE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status code.
d98e61ba075ed7d0b567a5d884bc85d643fe3de7vboxsync * @param pVM The virtual machine.
d98e61ba075ed7d0b567a5d884bc85d643fe3de7vboxsync * @param iPD Shadow PDE index.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fFlags The OR mask - page flags X86_PDE_*, excluding the page mask of course.
d98e61ba075ed7d0b567a5d884bc85d643fe3de7vboxsync * @param fMask The AND mask - page flags X86_PDE_*.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Be extremely CAREFUL with ~'ing values because they can be 32-bit!
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsyncPGM_SHW_DECL(int, ModifyPDEByIndex)(PVM pVM, uint32_t iPD, uint64_t fFlags, uint64_t fMask)
d98e61ba075ed7d0b567a5d884bc85d643fe3de7vboxsync#if PGM_SHW_TYPE == PGM_TYPE_32BIT || PGM_SHW_TYPE == PGM_TYPE_PAE
d98e61ba075ed7d0b567a5d884bc85d643fe3de7vboxsync * Get page directory addresses and update the specified entry.
d98e61ba075ed7d0b567a5d884bc85d643fe3de7vboxsync PX86PDE pPdeDst = &CTXMID(pVM->pgm.s.p,32BitPD)->a[iPD];
d98e61ba075ed7d0b567a5d884bc85d643fe3de7vboxsync pPdeDst->u = ((pPdeDst->u & ((X86PGUINT)fMask | SHW_PDE_PG_MASK)) | ((X86PGUINT)fFlags & ~SHW_PDE_PG_MASK));
d98e61ba075ed7d0b567a5d884bc85d643fe3de7vboxsync PX86PDEPAE pPdeDst = &CTXMID(pVM->pgm.s.ap,PaePDs)[0]->a[iPD]; /* We treat this as a PD with 2048 entries. */
d98e61ba075ed7d0b567a5d884bc85d643fe3de7vboxsync pPdeDst->u = (pPdeDst->u & (fMask | SHW_PDE_PG_MASK)) | (fFlags & ~SHW_PDE_PG_MASK);