PGMAllMap.cpp revision 089df8ada78128cb620e6a9af2bcb5bcae7d318f
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * PGM - Page Manager and Monitor - All context code.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Copyright (C) 2006-2007 Oracle Corporation
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * available from http://www.virtualbox.org. This file is free software;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * you can redistribute it and/or modify it under the terms of the GNU
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * General Public License (GPL) as published by the Free Software
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/*******************************************************************************
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync* Header Files *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync*******************************************************************************/
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync * Maps a range of physical pages at a given virtual address
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * in the guest context.
b1cc3e87518139898395f96974ecff9e6bf228fbvboxsync * The GC virtual address range must be within an existing mapping.
7862f4bd000f1eb6c86289f5ac2849e9cf943ca9vboxsync * @returns VBox status code.
388b6b190a5407548753b7fde12fa58134ec3563vboxsync * @param pVM The virtual machine.
7862f4bd000f1eb6c86289f5ac2849e9cf943ca9vboxsync * @param GCPtr Where to map the page(s). Must be page aligned.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * @param HCPhys Start of the range of physical pages. Must be page aligned.
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync * @param cbPages Number of bytes to map. Must be page aligned.
f9ce005e61f0fbb51a2cabc53d58c3485151faa9vboxsync * @param fFlags Page flags (X86_PTE_*).
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsyncVMMDECL(int) PGMMap(PVM pVM, RTGCUINTPTR GCPtr, RTHCPHYS HCPhys, uint32_t cbPages, unsigned fFlags)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Validate input.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync AssertMsg(RT_ALIGN_T(GCPtr, PAGE_SIZE, RTGCUINTPTR) == GCPtr, ("Invalid alignment GCPtr=%#x\n", GCPtr));
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync AssertMsg(cbPages > 0 && RT_ALIGN_32(cbPages, PAGE_SIZE) == cbPages, ("Invalid cbPages=%#x\n", cbPages));
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync AssertMsg(!(fFlags & X86_PDE_PG_MASK), ("Invalid flags %#x\n", fFlags));
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync /* hypervisor defaults */
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * Find the mapping.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * Setup PTE.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * Update the page tables.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync const unsigned iPageNo = (off >> PAGE_SHIFT) & X86_PT_MASK;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync /* 32-bit */
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync pCur->aPTs[iPT].CTX_SUFF(pPT)->a[iPageNo].u = (uint32_t)Pte.u; /* ASSUMES HCPhys < 4GB and/or that we're never gonna do 32-bit on a PAE host! */
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync PGMSHWPTEPAE_SET(pCur->aPTs[iPT].CTX_SUFF(paPaePTs)[iPageNo / 512].a[iPageNo % 512], Pte.u);
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync AssertMsgFailed(("GCPtr=%#x was not found in any mapping ranges!\n", GCPtr));
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * Sets (replaces) the page flags for a range of pages in a mapping.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @returns VBox status.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param pVM VM handle.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param GCPtr Virtual address of the first page in the range.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param cb Size (in bytes) of the range to apply the modification to.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param fFlags Page flags X86_PTE_*, excluding the page mask of course.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsyncVMMDECL(int) PGMMapSetPage(PVM pVM, RTGCPTR GCPtr, uint64_t cb, uint64_t fFlags)
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync return PGMMapModifyPage(pVM, GCPtr, cb, fFlags, 0);
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * Modify page flags for a range of pages in a mapping.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * The existing flags are ANDed with the fMask and ORed with the fFlags.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @returns VBox status code.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param pVM VM handle.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param GCPtr Virtual address of the first page in the range.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param cb Size (in bytes) of the range to apply the modification to.
581f0625e43a928987623d7cf59e1b1ab61ca6c8vboxsync * @param fFlags The OR mask - page flags X86_PTE_*, excluding the page mask of course.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param fMask The AND mask - page flags X86_PTE_*, excluding the page mask of course.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncVMMDECL(int) PGMMapModifyPage(PVM pVM, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Validate input.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertMsg(!(fFlags & (X86_PTE_PAE_PG_MASK_FULL | X86_PTE_PAE_MBZ_MASK_NX)), ("fFlags=%#x\n", fFlags));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Align the input.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync GCPtr = (RTGCPTR)((RTGCUINTPTR)GCPtr & PAGE_BASE_GC_MASK);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Find the mapping.
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync RTGCUINTPTR off = (RTGCUINTPTR)GCPtr - (RTGCUINTPTR)pCur->GCPtr;
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync ("Invalid page range %#x LB%#x. mapping '%s' %#x to %#x\n",
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync GCPtr, cb, pCur->pszDesc, pCur->GCPtr, pCur->GCPtrLast),
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Perform the requested operation.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync while (cb > 0)
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync while (cb > 0 && iPTE < RT_ELEMENTS(pCur->aPTs[iPT].CTX_SUFF(pPT)->a))
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync /* 32-Bit */
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync pCur->aPTs[iPT].CTX_SUFF(pPT)->a[iPTE].u &= fMask | X86_PTE_PG_MASK;
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync pCur->aPTs[iPT].CTX_SUFF(pPT)->a[iPTE].u |= fFlags & ~X86_PTE_PG_MASK;
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync PPGMSHWPTEPAE pPtePae = &pCur->aPTs[iPT].CTX_SUFF(paPaePTs)[iPTE / 512].a[iPTE % 512];
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync | (fFlags & ~(X86_PTE_PAE_PG_MASK | X86_PTE_PAE_MBZ_MASK_NX)));
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync /* invalidate tls */
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync PGM_INVL_PG(VMMGetCpu(pVM), (RTGCUINTPTR)pCur->GCPtr + off);
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync AssertMsgFailed(("Page range %#x LB%#x not found\n", GCPtr, cb));
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync * Get information about a page in a mapping.
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync * This differs from PGMShwGetPage and PGMGstGetPage in that it only consults
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync * the page table to calculate the flags.
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync * @returns VINF_SUCCESS, VERR_PAGE_NOT_PRESENT or VERR_NOT_FOUND.
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync * @param pVM The VM handle.
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync * @param GCPtr The page addresss.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param pfFlags Where to return the flags. Optional.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param pHCPhys Where to return the address. Optional.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsyncVMMDECL(int) PGMMapGetPage(PVM pVM, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys)
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * Find the mapping.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync RTGCUINTPTR off = (RTGCUINTPTR)GCPtr - (RTGCUINTPTR)pCur->GCPtr;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * Dig out the information.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync PCPGMSHWPTEPAE pPtePae = &pCur->aPTs[iPT].CTX_SUFF(paPaePTs)[iPTE / 512].a[iPTE % 512];
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync *pfFlags = PGMSHWPTEPAE_GET_U(*pPtePae) & ~X86_PTE_PAE_PG_MASK_FULL;
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync * Sets all PDEs involved with the mapping in the shadow page table.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * @param pVM The VM handle.
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync * @param pMap Pointer to the mapping in question.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * @param iNewPDE The index of the 32-bit PDE corresponding to the base of the mapping.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncvoid pgmMapSetShadowPDEs(PVM pVM, PPGMMAPPING pMap, unsigned iNewPDE)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync Log4(("pgmMapSetShadowPDEs new pde %x (mappings enabled %d)\n", iNewPDE, pgmMapAreMappingsEnabled(&pVM->pgm.s)));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* This only applies to raw mode where we only support 1 VCPU. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync return; /* too early */
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync * Insert the page tables into the shadow page directories.
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync while (i-- > 0)
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync /* Free any previous user, unless it's us. */
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync Assert( (pShw32BitPd->a[iNewPDE].u & (X86_PDE_P | PGM_PDFLAGS_MAPPING)) != (X86_PDE_P | PGM_PDFLAGS_MAPPING)
ed9d3db07648c7e3a979105c15ad752ee9ea18devboxsync || (pShw32BitPd->a[iNewPDE].u & X86_PDE_PG_MASK) == pMap->aPTs[i].HCPhysPT);
ed9d3db07648c7e3a979105c15ad752ee9ea18devboxsync && !(pShw32BitPd->a[iNewPDE].u & PGM_PDFLAGS_MAPPING))
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync pgmPoolFree(pVM, pShw32BitPd->a[iNewPDE].u & X86_PDE_PG_MASK, pVCpu->pgm.s.CTX_SUFF(pShwPageCR3)->idx, iNewPDE);
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync /* Default mapping page directory flags are read/write and supervisor; individual page attributes determine the final flags. */
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync pShw32BitPd->a[iNewPDE].u = PGM_PDFLAGS_MAPPING | X86_PDE_P | X86_PDE_A | X86_PDE_RW | X86_PDE_US
06ea6bcf23874b662d499b3f130024c98b2dd7a6vboxsync * Get the shadow PD.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * If no PD, sync it (PAE guest) or fake (not present or 32-bit guest).
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Note! The RW, US and A bits are reserved for PAE PDPTEs. Setting the
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * accessed bit causes invalid VT-x guest state errors.
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync PX86PDPAE pShwPaePd = pgmShwGetPaePDPtr(pVCpu, iPdPt << X86_PDPT_SHIFT);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PX86PDPE pGstPdpe = pgmGstGetPaePDPEPtr(pVCpu, iPdPt << X86_PDPT_SHIFT);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync int rc = pgmShwSyncPaePDPtr(pVCpu, iPdPt << X86_PDPT_SHIFT, GstPdpe.u, &pShwPaePd);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Mark the page as locked; disallow flushing.
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync PPGMPOOLPAGE pPoolPagePd = pgmPoolGetPage(pPool, pShwPdpt->a[iPdPt].u & X86_PDPE_PG_MASK);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (!pgmPoolIsPageLocked(&pVM->pgm.s, pPoolPagePd))
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync else if (pShwPaePd->a[iPaePde].u & PGM_PDFLAGS_MAPPING)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync Assert(PGMGetGuestMode(pVCpu) >= PGMMODE_PAE); /** @todo We may hit this during reset, will fix later. */
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync AssertFatalMsg( (pShwPaePd->a[iPaePde].u & X86_PDE_PAE_PG_MASK_FULL) == pMap->aPTs[i].HCPhysPaePT0
510567648d46488f4166e5f69ffffe3eeeeec4d9vboxsync ("%RX64 vs %RX64\n", pShwPaePd->a[iPaePde+1].u & X86_PDE_PAE_PG_MASK_FULL, pMap->aPTs[i].HCPhysPaePT0));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync Assert(pShwPaePd->a[iPaePde+1].u & PGM_PDFLAGS_MAPPING);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertFatalMsg( (pShwPaePd->a[iPaePde+1].u & X86_PDE_PAE_PG_MASK_FULL) == pMap->aPTs[i].HCPhysPaePT1
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync ("%RX64 vs %RX64\n", pShwPaePd->a[iPaePde+1].u & X86_PDE_PAE_PG_MASK_FULL, pMap->aPTs[i].HCPhysPaePT1));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Insert our first PT, freeing anything we might be replacing unless it's a mapping (i.e. us).
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync Assert( (pShwPaePd->a[iPaePde].u & (X86_PDE_P | PGM_PDFLAGS_MAPPING)) != (X86_PDE_P | PGM_PDFLAGS_MAPPING)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync || (pShwPaePd->a[iPaePde].u & X86_PDE_PAE_PG_MASK_FULL) == pMap->aPTs[i].HCPhysPaePT0);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync && !(pShwPaePd->a[iPaePde].u & PGM_PDFLAGS_MAPPING))
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync Assert(!(pShwPaePd->a[iPaePde].u & PGM_PDFLAGS_MAPPING));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pgmPoolFree(pVM, pShwPaePd->a[iPaePde].u & X86_PDE_PAE_PG_MASK_FULL, pPoolPagePd->idx, iPaePde);
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync pShwPaePd->a[iPaePde].u = PGM_PDFLAGS_MAPPING | X86_PDE_P | X86_PDE_A | X86_PDE_RW | X86_PDE_US
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* 2nd 2 MB PDE of the 4 MB region, same as above. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync Assert( (pShwPaePd->a[iPaePde].u & (X86_PDE_P | PGM_PDFLAGS_MAPPING)) != (X86_PDE_P | PGM_PDFLAGS_MAPPING)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync || (pShwPaePd->a[iPaePde].u & X86_PDE_PAE_PG_MASK_FULL) == pMap->aPTs[i].HCPhysPaePT1);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync && !(pShwPaePd->a[iPaePde].u & PGM_PDFLAGS_MAPPING))
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pgmPoolFree(pVM, pShwPaePd->a[iPaePde].u & X86_PDE_PG_MASK, pPoolPagePd->idx, iPaePde);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pShwPaePd->a[iPaePde].u = PGM_PDFLAGS_MAPPING | X86_PDE_P | X86_PDE_A | X86_PDE_RW | X86_PDE_US
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Set the PGM_PDFLAGS_MAPPING flag in the page directory pointer entry. (legacy PAE guest mode)
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * Clears all PDEs involved with the mapping in the shadow page table.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * @param pVM The VM handle.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * @param pShwPageCR3 CR3 root page
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * @param pMap Pointer to the mapping in question.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * @param iOldPDE The index of the 32-bit PDE corresponding to the base of the mapping.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * @param fDeactivateCR3 Set if it's pgmMapDeactivateCR3 calling.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsyncvoid pgmMapClearShadowPDEs(PVM pVM, PPGMPOOLPAGE pShwPageCR3, PPGMMAPPING pMap, unsigned iOldPDE, bool fDeactivateCR3)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync Log(("pgmMapClearShadowPDEs: old pde %x (cPTs=%x) (mappings enabled %d) fDeactivateCR3=%RTbool\n", iOldPDE, pMap->cPTs, pgmMapAreMappingsEnabled(&pVM->pgm.s), fDeactivateCR3));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Skip this if disabled or if it doesn't apply.
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync /* This only applies to raw mode where we only support 1 VCPU. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync Assert(pShwPageCR3 != pVCpu->pgm.s.CTX_SUFF(pShwPageCR3));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync && pShwPageCR3 != pVCpu->pgm.s.CTX_SUFF(pShwPageCR3))
7e8ef90d3160234df0f254131b87af4243d79476vboxsync while (i-- > 0)
7e8ef90d3160234df0f254131b87af4243d79476vboxsync PX86PD pShw32BitPd = (PX86PD)PGMPOOL_PAGE_2_PTR_V2(pVM, pVCpu, pShwPageCR3);
7e8ef90d3160234df0f254131b87af4243d79476vboxsync Assert(!pShw32BitPd->a[iOldPDE].n.u1Present || (pShw32BitPd->a[iOldPDE].u & PGM_PDFLAGS_MAPPING));
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync const unsigned iPdpt = iOldPDE / 256; /* iOldPDE * 2 / 512; iOldPDE is in 4 MB pages */
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync PX86PDPT pShwPdpt = (PX86PDPT)PGMPOOL_PAGE_2_PTR_V2(pVM, pVCpu, pShwPageCR3);
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync PX86PDPAE pShwPaePd = pgmShwGetPaePDPtr(pVCpu, pShwPdpt, (iPdpt << X86_PDPT_SHIFT));
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync * Clear the PGM_PDFLAGS_MAPPING flag for the page directory pointer entry. (legacy PAE guest mode)
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync else if (pShwPdpt->a[iPdpt].u & PGM_PLXFLAGS_MAPPING)
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync /* See if there are any other mappings here. This is suboptimal code. */
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync for (PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings); pCur; pCur = pCur->CTX_SUFF(pNext))
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync * If the page directory of the old CR3 is reused in the new one, then don't
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync * clear the hypervisor mappings.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync && (pCurrentShwPdpt->a[iPdpt].u & X86_PDPE_PG_MASK) == (pShwPdpt->a[iPdpt].u & X86_PDPE_PG_MASK) )
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync LogFlow(("pgmMapClearShadowPDEs: Pdpe %d reused -> don't clear hypervisor mappings!\n", iPdpt));
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * Clear the mappings in the PD.
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync Assert(!pShwPaePd->a[iPaePde].n.u1Present || (pShwPaePd->a[iPaePde].u & PGM_PDFLAGS_MAPPING));
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync Assert(!pShwPaePd->a[iPaePde].n.u1Present || (pShwPaePd->a[iPaePde].u & PGM_PDFLAGS_MAPPING));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Unlock the shadow pool PD page if the PDPTE no longer holds any mappings.
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync PPGMPOOLPAGE pPoolPagePd = pgmPoolGetPage(pPool, pShwPdpt->a[iPdpt].u & X86_PDPE_PG_MASK);
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync#endif /* !IN_RING0 */
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync * Clears all PDEs involved with the mapping in the shadow page table.
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync * @param pVM The VM handle.
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync * @param pVCpu The VMCPU handle.
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync * @param pShwPageCR3 CR3 root page
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync * @param pMap Pointer to the mapping in question.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * @param iPDE The index of the 32-bit PDE corresponding to the base of the mapping.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncstatic void pgmMapCheckShadowPDEs(PVM pVM, PVMCPU pVCpu, PPGMPOOLPAGE pShwPageCR3, PPGMMAPPING pMap, unsigned iPDE)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync while (i-- > 0)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PCX86PD pShw32BitPd = (PCX86PD)PGMPOOL_PAGE_2_PTR_V2(pVM, pVCpu, pShwPageCR3);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertMsg(pShw32BitPd->a[iPDE].u == (PGM_PDFLAGS_MAPPING | X86_PDE_P | X86_PDE_A | X86_PDE_RW | X86_PDE_US | (uint32_t)pMap->aPTs[i].HCPhysPT),
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync ("Expected %x vs %x; iPDE=%#x %RGv %s\n",
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pShw32BitPd->a[iPDE].u, (PGM_PDFLAGS_MAPPING | X86_PDE_P | X86_PDE_A | X86_PDE_RW | X86_PDE_US | (uint32_t)pMap->aPTs[i].HCPhysPT),
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync const unsigned iPdpt = iPDE / 256; /* iPDE * 2 / 512; iPDE is in 4 MB pages */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PX86PDPT pShwPdpt = (PX86PDPT)PGMPOOL_PAGE_2_PTR_V2(pVM, pVCpu, pShwPageCR3);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PCX86PDPAE pShwPaePd = pgmShwGetPaePDPtr(pVCpu, pShwPdpt, iPdpt << X86_PDPT_SHIFT);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertMsg(pShwPaePd->a[iPaePDE].u == (PGM_PDFLAGS_MAPPING | X86_PDE_P | X86_PDE_A | X86_PDE_RW | X86_PDE_US | pMap->aPTs[i].HCPhysPaePT0),
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync ("Expected %RX64 vs %RX64; iPDE=%#x iPdpt=%#x iPaePDE=%#x %RGv %s\n",
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pShwPaePd->a[iPaePDE].u, (PGM_PDFLAGS_MAPPING | X86_PDE_P | X86_PDE_A | X86_PDE_RW | X86_PDE_US | pMap->aPTs[i].HCPhysPaePT0),
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync iPDE, iPdpt, iPaePDE, pMap->GCPtr, R3STRING(pMap->pszDesc) ));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertMsg(pShwPaePd->a[iPaePDE].u == (PGM_PDFLAGS_MAPPING | X86_PDE_P | X86_PDE_A | X86_PDE_RW | X86_PDE_US | pMap->aPTs[i].HCPhysPaePT1),
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync ("Expected %RX64 vs %RX64; iPDE=%#x iPdpt=%#x iPaePDE=%#x %RGv %s\n",
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pShwPaePd->a[iPaePDE].u, (PGM_PDFLAGS_MAPPING | X86_PDE_P | X86_PDE_A | X86_PDE_RW | X86_PDE_US | pMap->aPTs[i].HCPhysPaePT1),
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync iPDE, iPdpt, iPaePDE, pMap->GCPtr, R3STRING(pMap->pszDesc) ));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertMsg(pShwPdpt->a[iPdpt].u & PGM_PLXFLAGS_MAPPING,
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync ("%RX64; iPdpt=%#x iPDE=%#x iPaePDE=%#x %RGv %s\n",
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync iPDE, iPdpt, iPaePDE, pMap->GCPtr, R3STRING(pMap->pszDesc) ));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PCPGMPOOLPAGE pPoolPagePd = pgmPoolGetPage(pPool, pShwPdpt->a[iPdpt].u & X86_PDPE_PG_MASK);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertMsg(pPoolPagePd->cLocked, (".idx=%d .type=%d\n", pPoolPagePd->idx, pPoolPagePd->enmKind));
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync * Check the hypervisor mappings in the active CR3.
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync * @param pVM The virtual machine.
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync * Can skip this if mappings are disabled.
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync /* This only applies to raw mode where we only support 1 VCPU. */
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync * Iterate mappings.
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync for (PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings); pCur; pCur = pCur->CTX_SUFF(pNext))
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync pgmMapCheckShadowPDEs(pVM, pVCpu, pVCpu->pgm.s.CTX_SUFF(pShwPageCR3), pCur, iPDE);
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync#endif /* defined(VBOX_STRICT) && !defined(IN_RING0) */
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * Apply the hypervisor mappings to the active CR3.
c193ae401647c574d0ef52af57c32cf5d7c44966vboxsync * @returns VBox status.
c193ae401647c574d0ef52af57c32cf5d7c44966vboxsync * @param pVM The virtual machine.
c193ae401647c574d0ef52af57c32cf5d7c44966vboxsync * @param pShwPageCR3 CR3 root page
c193ae401647c574d0ef52af57c32cf5d7c44966vboxsyncint pgmMapActivateCR3(PVM pVM, PPGMPOOLPAGE pShwPageCR3)
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * Skip this if disabled or if it doesn't apply.
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync /* Note! This might not be logged successfully in RC because we usually
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync cannot flush the log at this point. */
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync Log4(("pgmMapActivateCR3: fixed mappings=%RTbool idxShwPageCR3=%#x\n", pVM->pgm.s.fMappingsFixed, pShwPageCR3 ? pShwPageCR3->idx : NIL_PGMPOOL_IDX));
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync Assert(pShwPageCR3 && pShwPageCR3 == pVCpu->pgm.s.CTX_SUFF(pShwPageCR3));
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * Iterate mappings.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync for (PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings); pCur; pCur = pCur->CTX_SUFF(pNext))
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * Remove the hypervisor mappings from the specified CR3
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @returns VBox status.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param pVM The virtual machine.
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync * @param pShwPageCR3 CR3 root page
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsyncint pgmMapDeactivateCR3(PVM pVM, PPGMPOOLPAGE pShwPageCR3)
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync * Skip this if disabled or if it doesn't apply.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Log4(("pgmMapDeactivateCR3: fixed mappings=%d idxShwPageCR3=%#x\n", pVM->pgm.s.fMappingsFixed, pShwPageCR3 ? pShwPageCR3->idx : NIL_PGMPOOL_IDX));
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * Iterate mappings.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync for (PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings); pCur; pCur = pCur->CTX_SUFF(pNext))
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync pgmMapClearShadowPDEs(pVM, pShwPageCR3, pCur, iPDE, true /*fDeactivateCR3*/);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * Checks guest PD for conflicts with VMM GC mappings.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * @returns true if conflict detected.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * @returns false if not.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * @param pVM The virtual machine.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * Can skip this if mappings are safely fixed.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync return false;
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync /* This only applies to raw mode where we only support 1 VCPU. */
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync PGMMODE const enmGuestMode = PGMGetGuestMode(pVCpu);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * Iterate mappings.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * Resolve the page directory.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync for (PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings); pCur; pCur = pCur->CTX_SUFF(pNext))
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync while (iPT-- > 0)
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync if ( pPD->a[iPDE + iPT].n.u1Present /** @todo PGMGstGetPDE. */
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync && (pVM->fRawR0Enabled || pPD->a[iPDE + iPT].n.u1User))
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync STAM_COUNTER_INC(&pVM->pgm.s.CTX_SUFF(pStats)->StatR3DetectedConflicts);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Log(("PGMHasMappingConflicts: Conflict was detected at %08RX32 for mapping %s (32 bits)\n"
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync " iPDE=%#x iPT=%#x PDE=%RGp.\n",
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Log(("PGMHasMappingConflicts: Conflict was detected at %08RX32 for mapping (32 bits)\n"
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync " iPDE=%#x iPT=%#x PDE=%RGp.\n",
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync return true;
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync for (PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings); pCur; pCur = pCur->CTX_SUFF(pNext))
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync while (iPT-- > 0)
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync STAM_COUNTER_INC(&pVM->pgm.s.CTX_SUFF(pStats)->StatR3DetectedConflicts);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Log(("PGMHasMappingConflicts: Conflict was detected at %RGv for mapping %s (PAE)\n"
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync " PDE=%016RX64.\n",
b8bb9c9f6b8ebfd0a7d6df0c0289f9fe80241750vboxsync Log(("PGMHasMappingConflicts: Conflict was detected at %RGv for mapping (PAE)\n"
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync " PDE=%016RX64.\n",
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync return true;
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync return false;
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * Checks and resolves (ring 3 only) guest conflicts with the guest mappings.
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * @returns VBox status.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * @param pVM The virtual machine.
b8bb9c9f6b8ebfd0a7d6df0c0289f9fe80241750vboxsync /* The caller is expected to check these two conditions. */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* This only applies to raw mode where we only support 1 VCPU. */
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync PGMMODE const enmGuestMode = PGMGetGuestMode(pVCpu);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync * Resolve the page directory.
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync * Iterate mappings.
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync for (PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings); pCur; )
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync while (iPT-- > 0)
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync if ( pPD->a[iPDE + iPT].n.u1Present /** @todo PGMGstGetPDE. */
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync STAM_COUNTER_INC(&pVM->pgm.s.CTX_SUFF(pStats)->StatR3DetectedConflicts);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Log(("PGMHasMappingConflicts: Conflict was detected at %08RX32 for mapping %s (32 bits)\n"
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync " iPDE=%#x iPT=%#x PDE=%RGp.\n",
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync int rc = pgmR3SyncPTResolveConflict(pVM, pCur, pPD, iPDE << X86_PD_SHIFT);
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync Log(("PGMHasMappingConflicts: Conflict was detected at %08RX32 for mapping (32 bits)\n"
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync " iPDE=%#x iPT=%#x PDE=%RGp.\n",
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * Iterate mappings.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync for (PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings); pCur;)
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync while (iPT-- > 0)
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync STAM_COUNTER_INC(&pVM->pgm.s.CTX_SUFF(pStats)->StatR3DetectedConflicts);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Log(("PGMHasMappingConflicts: Conflict was detected at %RGv for mapping %s (PAE)\n"
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync " PDE=%016RX64.\n",
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync int rc = pgmR3SyncPTResolveConflictPAE(pVM, pCur, pCur->GCPtr);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Log(("PGMHasMappingConflicts: Conflict was detected at %RGv for mapping (PAE)\n"
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync " PDE=%016RX64.\n",
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync#endif /* IN_RING0 */