PGMAllMap.cpp revision 089df8ada78128cb620e6a9af2bcb5bcae7d318f
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/* $Id$ */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/** @file
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * PGM - Page Manager and Monitor - All context code.
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Copyright (C) 2006-2007 Oracle Corporation
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync *
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
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/*******************************************************************************
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync* Header Files *
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync*******************************************************************************/
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#define LOG_GROUP LOG_GROUP_PGM
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include <VBox/pgm.h>
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync#include "../PGMInternal.h"
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include <VBox/vm.h>
7b9f0c34e9ea328981c99e97054bdf8684d9d620vboxsync#include "../PGMInline.h"
9e7e0b61d29309a0ed7af9472c8d6d865f9e8a2dvboxsync#include <VBox/err.h>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include <iprt/asm-amd64-x86.h>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#include <iprt/assert.h>
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
0fd108a555ae02f2fb557d5f2c40281999b60d15vboxsync
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync/**
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync * Maps a range of physical pages at a given virtual address
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * in the guest context.
b1cc3e87518139898395f96974ecff9e6bf228fbvboxsync *
b1cc3e87518139898395f96974ecff9e6bf228fbvboxsync * The GC virtual address range must be within an existing mapping.
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync *
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_*).
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsyncVMMDECL(int) PGMMap(PVM pVM, RTGCUINTPTR GCPtr, RTHCPHYS HCPhys, uint32_t cbPages, unsigned fFlags)
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync{
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync AssertMsg(pVM->pgm.s.offVM, ("Bad init order\n"));
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync /*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Validate input.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync */
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
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync /* hypervisor defaults */
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync if (!fFlags)
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync fFlags = X86_PTE_P | X86_PTE_A | X86_PTE_D;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync /*
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * Find the mapping.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync */
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings);
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync while (pCur)
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync {
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync if (GCPtr - pCur->GCPtr < pCur->cb)
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync {
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync if (GCPtr + cbPages - 1 > pCur->GCPtrLast)
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync {
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync AssertMsgFailed(("Invalid range!!\n"));
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync return VERR_INVALID_PARAMETER;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync }
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync /*
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * Setup PTE.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync */
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync X86PTEPAE Pte;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync Pte.u = fFlags | (HCPhys & X86_PTE_PAE_PG_MASK);
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync /*
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * Update the page tables.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync */
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync for (;;)
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync {
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync RTGCUINTPTR off = GCPtr - pCur->GCPtr;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync const unsigned iPT = off >> X86_PD_SHIFT;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync const unsigned iPageNo = (off >> PAGE_SHIFT) & X86_PT_MASK;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync
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
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync /* pae */
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync PGMSHWPTEPAE_SET(pCur->aPTs[iPT].CTX_SUFF(paPaePTs)[iPageNo / 512].a[iPageNo % 512], Pte.u);
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync /* next */
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync cbPages -= PAGE_SIZE;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync if (!cbPages)
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync break;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync GCPtr += PAGE_SIZE;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync Pte.u += PAGE_SIZE;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync }
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync return VINF_SUCCESS;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync }
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync /* next */
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync pCur = pCur->CTX_SUFF(pNext);
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync }
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync AssertMsgFailed(("GCPtr=%#x was not found in any mapping ranges!\n", GCPtr));
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync return VERR_INVALID_PARAMETER;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync}
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync/**
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * Sets (replaces) the page flags for a range of pages in a mapping.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync *
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.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync */
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsyncVMMDECL(int) PGMMapSetPage(PVM pVM, RTGCPTR GCPtr, uint64_t cb, uint64_t fFlags)
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync{
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync return PGMMapModifyPage(pVM, GCPtr, cb, fFlags, 0);
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync}
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync/**
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * Modify page flags for a range of pages in a mapping.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync *
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * The existing flags are ANDed with the fMask and ORed with the fFlags.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync *
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.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncVMMDECL(int) PGMMapModifyPage(PVM pVM, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Validate input.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertMsg(!(fFlags & (X86_PTE_PAE_PG_MASK_FULL | X86_PTE_PAE_MBZ_MASK_NX)), ("fFlags=%#x\n", fFlags));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync Assert(cb);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Align the input.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync cb += (RTGCUINTPTR)GCPtr & PAGE_OFFSET_MASK;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync cb = RT_ALIGN_Z(cb, PAGE_SIZE);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync GCPtr = (RTGCPTR)((RTGCUINTPTR)GCPtr & PAGE_BASE_GC_MASK);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Find the mapping.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync while (pCur)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync RTGCUINTPTR off = (RTGCUINTPTR)GCPtr - (RTGCUINTPTR)pCur->GCPtr;
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync if (off < pCur->cb)
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync {
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync AssertMsgReturn(off + cb <= pCur->cb,
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync ("Invalid page range %#x LB%#x. mapping '%s' %#x to %#x\n",
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync GCPtr, cb, pCur->pszDesc, pCur->GCPtr, pCur->GCPtrLast),
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync VERR_INVALID_PARAMETER);
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync /*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Perform the requested operation.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync */
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync while (cb > 0)
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync {
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync unsigned iPT = off >> X86_PD_SHIFT;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync unsigned iPTE = (off >> PAGE_SHIFT) & X86_PT_MASK;
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync while (cb > 0 && iPTE < RT_ELEMENTS(pCur->aPTs[iPT].CTX_SUFF(pPT)->a))
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
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
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync /* PAE */
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync PPGMSHWPTEPAE pPtePae = &pCur->aPTs[iPT].CTX_SUFF(paPaePTs)[iPTE / 512].a[iPTE % 512];
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync PGMSHWPTEPAE_SET(*pPtePae,
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync ( PGMSHWPTEPAE_GET_U(*pPtePae)
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync & (fMask | X86_PTE_PAE_PG_MASK))
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync | (fFlags & ~(X86_PTE_PAE_PG_MASK | X86_PTE_PAE_MBZ_MASK_NX)));
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync /* invalidate tls */
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync PGM_INVL_PG(VMMGetCpu(pVM), (RTGCUINTPTR)pCur->GCPtr + off);
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync /* next */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync iPTE++;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync cb -= PAGE_SIZE;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync off += PAGE_SIZE;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync }
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync }
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync return VINF_SUCCESS;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync }
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync /* next */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pCur = pCur->CTX_SUFF(pNext);
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync }
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync AssertMsgFailed(("Page range %#x LB%#x not found\n", GCPtr, cb));
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync return VERR_INVALID_PARAMETER;
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync}
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync/**
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync * Get information about a page in a mapping.
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync *
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync * This differs from PGMShwGetPage and PGMGstGetPage in that it only consults
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync * the page table to calculate the flags.
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync *
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.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync */
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsyncVMMDECL(int) PGMMapGetPage(PVM pVM, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys)
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync{
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync /*
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * Find the mapping.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync */
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync GCPtr &= PAGE_BASE_GC_MASK;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings);
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync while (pCur)
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync {
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync RTGCUINTPTR off = (RTGCUINTPTR)GCPtr - (RTGCUINTPTR)pCur->GCPtr;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync if (off < pCur->cb)
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync {
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync /*
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * Dig out the information.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync */
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync int rc = VINF_SUCCESS;
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync unsigned iPT = off >> X86_PD_SHIFT;
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync unsigned iPTE = (off >> PAGE_SHIFT) & X86_PT_MASK;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync PCPGMSHWPTEPAE pPtePae = &pCur->aPTs[iPT].CTX_SUFF(paPaePTs)[iPTE / 512].a[iPTE % 512];
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync if (PGMSHWPTEPAE_IS_P(*pPtePae))
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync {
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync if (pfFlags)
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync *pfFlags = PGMSHWPTEPAE_GET_U(*pPtePae) & ~X86_PTE_PAE_PG_MASK_FULL;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync if (pHCPhys)
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync *pHCPhys = PGMSHWPTEPAE_GET_HCPHYS(*pPtePae);
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync }
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync else
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync rc = VERR_PAGE_NOT_PRESENT;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync return rc;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync }
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync /* next */
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync pCur = pCur->CTX_SUFF(pNext);
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync }
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync return VERR_NOT_FOUND;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync}
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync#ifndef IN_RING0
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync/**
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync * Sets all PDEs involved with the mapping in the shadow page table.
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync *
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.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncvoid pgmMapSetShadowPDEs(PVM pVM, PPGMMAPPING pMap, unsigned iNewPDE)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync Log4(("pgmMapSetShadowPDEs new pde %x (mappings enabled %d)\n", iNewPDE, pgmMapAreMappingsEnabled(&pVM->pgm.s)));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if ( !pgmMapAreMappingsEnabled(&pVM->pgm.s)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync || pVM->cCpus > 1)
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync return;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* This only applies to raw mode where we only support 1 VCPU. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PVMCPU pVCpu = VMMGetCpu0(pVM);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (!pVCpu->pgm.s.CTX_SUFF(pShwPageCR3))
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync return; /* too early */
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync PGMMODE enmShadowMode = PGMGetShadowMode(pVCpu);
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync Assert(enmShadowMode <= PGMMODE_PAE_NX);
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync PPGMPOOL pPool = pVM->pgm.s.CTX_SUFF(pPool);
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync /*
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync * Insert the page tables into the shadow page directories.
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync */
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync unsigned i = pMap->cPTs;
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync iNewPDE += i;
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync while (i-- > 0)
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync {
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync iNewPDE--;
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync switch (enmShadowMode)
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync {
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync case PGMMODE_32_BIT:
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync {
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync PX86PD pShw32BitPd = pgmShwGet32BitPDPtr(pVCpu);
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync AssertFatal(pShw32BitPd);
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync
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 if ( pShw32BitPd->a[iNewPDE].n.u1Present
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);
9523921c89c66f4bececdbd5ac95aed0039eda1bvboxsync
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
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync | (uint32_t)pMap->aPTs[i].HCPhysPT;
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync PGM_DYNMAP_UNUSED_HINT_VM(pVM, pShw32BitPd);
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync break;
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync }
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync case PGMMODE_PAE:
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync case PGMMODE_PAE_NX:
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync {
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync const uint32_t iPdPt = iNewPDE / 256;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync unsigned iPaePde = iNewPDE * 2 % 512;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PX86PDPT pShwPdpt = pgmShwGetPaePDPTPtr(pVCpu);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync Assert(pShwPdpt);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /*
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.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync PX86PDPAE pShwPaePd = pgmShwGetPaePDPtr(pVCpu, iPdPt << X86_PDPT_SHIFT);
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync if (!pShwPaePd)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync X86PDPE GstPdpe;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (PGMGetGuestMode(pVCpu) < PGMMODE_PAE)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync GstPdpe.u = X86_PDPE_P;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync else
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PX86PDPE pGstPdpe = pgmGstGetPaePDPEPtr(pVCpu, iPdPt << X86_PDPT_SHIFT);
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync if (pGstPdpe)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync GstPdpe = *pGstPdpe;
510567648d46488f4166e5f69ffffe3eeeeec4d9vboxsync else
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync GstPdpe.u = X86_PDPE_P;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync int rc = pgmShwSyncPaePDPtr(pVCpu, iPdPt << X86_PDPT_SHIFT, GstPdpe.u, &pShwPaePd);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertFatalRC(rc);
06ea6bcf23874b662d499b3f130024c98b2dd7a6vboxsync }
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync Assert(pShwPaePd);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Mark the page as locked; disallow flushing.
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync */
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync PPGMPOOLPAGE pPoolPagePd = pgmPoolGetPage(pPool, pShwPdpt->a[iPdPt].u & X86_PDPE_PG_MASK);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertFatal(pPoolPagePd);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if (!pgmPoolIsPageLocked(&pVM->pgm.s, pPoolPagePd))
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pgmPoolLockPage(pPool, pPoolPagePd);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#ifdef VBOX_STRICT
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync else if (pShwPaePd->a[iPaePde].u & PGM_PDFLAGS_MAPPING)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
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
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync || !PGMMODE_WITH_PAGING(PGMGetGuestMode(pVCpu)),
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 || !PGMMODE_WITH_PAGING(PGMGetGuestMode(pVCpu)),
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync ("%RX64 vs %RX64\n", pShwPaePd->a[iPaePde+1].u & X86_PDE_PAE_PG_MASK_FULL, pMap->aPTs[i].HCPhysPaePT1));
06ea6bcf23874b662d499b3f130024c98b2dd7a6vboxsync }
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync#endif
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Insert our first PT, freeing anything we might be replacing unless it's a mapping (i.e. us).
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync */
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 if ( pShwPaePd->a[iPaePde].n.u1Present
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync && !(pShwPaePd->a[iPaePde].u & PGM_PDFLAGS_MAPPING))
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
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);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync pShwPaePd->a[iPaePde].u = PGM_PDFLAGS_MAPPING | X86_PDE_P | X86_PDE_A | X86_PDE_RW | X86_PDE_US
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync | pMap->aPTs[i].HCPhysPaePT0;
510567648d46488f4166e5f69ffffe3eeeeec4d9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /* 2nd 2 MB PDE of the 4 MB region, same as above. */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync iPaePde++;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertFatal(iPaePde < 512);
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 if ( pShwPaePd->a[iPaePde].n.u1Present
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
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync | pMap->aPTs[i].HCPhysPaePT1;
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Set the PGM_PDFLAGS_MAPPING flag in the page directory pointer entry. (legacy PAE guest mode)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pShwPdpt->a[iPdPt].u |= PGM_PLXFLAGS_MAPPING;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PGM_DYNMAP_UNUSED_HINT_VM(pVM, pShwPaePd);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PGM_DYNMAP_UNUSED_HINT_VM(pVM, pShwPdpt);
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync break;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync }
510567648d46488f4166e5f69ffffe3eeeeec4d9vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync default:
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync AssertFailed();
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync break;
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync }
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync }
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync}
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync/**
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * Clears all PDEs involved with the mapping in the shadow page table.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync *
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.
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync */
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsyncvoid pgmMapClearShadowPDEs(PVM pVM, PPGMPOOLPAGE pShwPageCR3, PPGMMAPPING pMap, unsigned iOldPDE, bool fDeactivateCR3)
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync Log(("pgmMapClearShadowPDEs: old pde %x (cPTs=%x) (mappings enabled %d) fDeactivateCR3=%RTbool\n", iOldPDE, pMap->cPTs, pgmMapAreMappingsEnabled(&pVM->pgm.s), fDeactivateCR3));
510567648d46488f4166e5f69ffffe3eeeeec4d9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Skip this if disabled or if it doesn't apply.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if ( !pgmMapAreMappingsEnabled(&pVM->pgm.s)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync || pVM->cCpus > 1)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync return;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync Assert(pShwPageCR3);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync /* This only applies to raw mode where we only support 1 VCPU. */
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync PVMCPU pVCpu = VMMGetCpu0(pVM);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync# ifdef IN_RC
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync Assert(pShwPageCR3 != pVCpu->pgm.s.CTX_SUFF(pShwPageCR3));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync# endif
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PPGMPOOL pPool = pVM->pgm.s.CTX_SUFF(pPool);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PX86PDPT pCurrentShwPdpt = NULL;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if ( PGMGetGuestMode(pVCpu) >= PGMMODE_PAE
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync && pShwPageCR3 != pVCpu->pgm.s.CTX_SUFF(pShwPageCR3))
510567648d46488f4166e5f69ffffe3eeeeec4d9vboxsync pCurrentShwPdpt = pgmShwGetPaePDPTPtr(pVCpu);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync unsigned i = pMap->cPTs;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PGMMODE enmShadowMode = PGMGetShadowMode(pVCpu);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
7e8ef90d3160234df0f254131b87af4243d79476vboxsync iOldPDE += i;
7e8ef90d3160234df0f254131b87af4243d79476vboxsync while (i-- > 0)
7e8ef90d3160234df0f254131b87af4243d79476vboxsync {
7e8ef90d3160234df0f254131b87af4243d79476vboxsync iOldPDE--;
7e8ef90d3160234df0f254131b87af4243d79476vboxsync
7e8ef90d3160234df0f254131b87af4243d79476vboxsync switch(enmShadowMode)
7e8ef90d3160234df0f254131b87af4243d79476vboxsync {
7e8ef90d3160234df0f254131b87af4243d79476vboxsync case PGMMODE_32_BIT:
7e8ef90d3160234df0f254131b87af4243d79476vboxsync {
7e8ef90d3160234df0f254131b87af4243d79476vboxsync PX86PD pShw32BitPd = (PX86PD)PGMPOOL_PAGE_2_PTR_V2(pVM, pVCpu, pShwPageCR3);
7e8ef90d3160234df0f254131b87af4243d79476vboxsync AssertFatal(pShw32BitPd);
7e8ef90d3160234df0f254131b87af4243d79476vboxsync
7e8ef90d3160234df0f254131b87af4243d79476vboxsync Assert(!pShw32BitPd->a[iOldPDE].n.u1Present || (pShw32BitPd->a[iOldPDE].u & PGM_PDFLAGS_MAPPING));
7e8ef90d3160234df0f254131b87af4243d79476vboxsync pShw32BitPd->a[iOldPDE].u = 0;
510567648d46488f4166e5f69ffffe3eeeeec4d9vboxsync break;
7e8ef90d3160234df0f254131b87af4243d79476vboxsync }
7e8ef90d3160234df0f254131b87af4243d79476vboxsync
7e8ef90d3160234df0f254131b87af4243d79476vboxsync case PGMMODE_PAE:
7e8ef90d3160234df0f254131b87af4243d79476vboxsync case PGMMODE_PAE_NX:
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync {
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync const unsigned iPdpt = iOldPDE / 256; /* iOldPDE * 2 / 512; iOldPDE is in 4 MB pages */
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync unsigned iPaePde = iOldPDE * 2 % 512;
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync PX86PDPT pShwPdpt = (PX86PDPT)PGMPOOL_PAGE_2_PTR_V2(pVM, pVCpu, pShwPageCR3);
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync PX86PDPAE pShwPaePd = pgmShwGetPaePDPtr(pVCpu, pShwPdpt, (iPdpt << X86_PDPT_SHIFT));
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync /*
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync * Clear the PGM_PDFLAGS_MAPPING flag for the page directory pointer entry. (legacy PAE guest mode)
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync */
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync if (fDeactivateCR3)
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync pShwPdpt->a[iPdpt].u &= ~PGM_PLXFLAGS_MAPPING;
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync else if (pShwPdpt->a[iPdpt].u & PGM_PLXFLAGS_MAPPING)
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync {
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync /* See if there are any other mappings here. This is suboptimal code. */
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync pShwPdpt->a[iPdpt].u &= ~PGM_PLXFLAGS_MAPPING;
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync for (PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings); pCur; pCur = pCur->CTX_SUFF(pNext))
510567648d46488f4166e5f69ffffe3eeeeec4d9vboxsync if ( pCur != pMap
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync && ( (pCur->GCPtr >> X86_PDPT_SHIFT) == iPdpt
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync || (pCur->GCPtrLast >> X86_PDPT_SHIFT) == iPdpt))
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync {
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync pShwPdpt->a[iPdpt].u |= PGM_PLXFLAGS_MAPPING;
06ea6bcf23874b662d499b3f130024c98b2dd7a6vboxsync break;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /*
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync * If the page directory of the old CR3 is reused in the new one, then don't
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync * clear the hypervisor mappings.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if ( pCurrentShwPdpt
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync && (pCurrentShwPdpt->a[iPdpt].u & X86_PDPE_PG_MASK) == (pShwPdpt->a[iPdpt].u & X86_PDPE_PG_MASK) )
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync LogFlow(("pgmMapClearShadowPDEs: Pdpe %d reused -> don't clear hypervisor mappings!\n", iPdpt));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync break;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync /*
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * Clear the mappings in the PD.
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertFatal(pShwPaePd);
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync Assert(!pShwPaePd->a[iPaePde].n.u1Present || (pShwPaePd->a[iPaePde].u & PGM_PDFLAGS_MAPPING));
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync pShwPaePd->a[iPaePde].u = 0;
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync iPaePde++;
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync AssertFatal(iPaePde < 512);
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync Assert(!pShwPaePd->a[iPaePde].n.u1Present || (pShwPaePd->a[iPaePde].u & PGM_PDFLAGS_MAPPING));
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync pShwPaePd->a[iPaePde].u = 0;
510567648d46488f4166e5f69ffffe3eeeeec4d9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync /*
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync * Unlock the shadow pool PD page if the PDPTE no longer holds any mappings.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync if ( fDeactivateCR3
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync || !(pShwPdpt->a[iPdpt].u & PGM_PLXFLAGS_MAPPING))
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync {
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync PPGMPOOLPAGE pPoolPagePd = pgmPoolGetPage(pPool, pShwPdpt->a[iPdpt].u & X86_PDPE_PG_MASK);
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync AssertFatal(pPoolPagePd);
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync if (pgmPoolIsPageLocked(&pVM->pgm.s, pPoolPagePd))
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync pgmPoolUnlockPage(pPool, pPoolPagePd);
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync }
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync break;
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync }
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync default:
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync AssertFailed();
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync break;
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync }
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync }
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync PGM_DYNMAP_UNUSED_HINT_VM(pVM, pCurrentShwPdpt);
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync}
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync#endif /* !IN_RING0 */
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync#if defined(VBOX_STRICT) && !defined(IN_RING0)
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync/**
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync * Clears all PDEs involved with the mapping in the shadow page table.
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync *
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.
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsyncstatic void pgmMapCheckShadowPDEs(PVM pVM, PVMCPU pVCpu, PPGMPOOLPAGE pShwPageCR3, PPGMMAPPING pMap, unsigned iPDE)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync{
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync Assert(pShwPageCR3);
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync uint32_t i = pMap->cPTs;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PGMMODE enmShadowMode = PGMGetShadowMode(pVCpu);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PPGMPOOL pPool = pVM->pgm.s.CTX_SUFF(pPool);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync iPDE += i;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync while (i-- > 0)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync iPDE--;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync switch (enmShadowMode)
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync case PGMMODE_32_BIT:
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PCX86PD pShw32BitPd = (PCX86PD)PGMPOOL_PAGE_2_PTR_V2(pVM, pVCpu, pShwPageCR3);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertFatal(pShw32BitPd);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
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 iPDE, pMap->GCPtr, R3STRING(pMap->pszDesc) ));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync break;
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync }
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync case PGMMODE_PAE:
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync case PGMMODE_PAE_NX:
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync {
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync const unsigned iPdpt = iPDE / 256; /* iPDE * 2 / 512; iPDE is in 4 MB pages */
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync unsigned iPaePDE = iPDE * 2 % 512;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PX86PDPT pShwPdpt = (PX86PDPT)PGMPOOL_PAGE_2_PTR_V2(pVM, pVCpu, pShwPageCR3);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PCX86PDPAE pShwPaePd = pgmShwGetPaePDPtr(pVCpu, pShwPdpt, iPdpt << X86_PDPT_SHIFT);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertFatal(pShwPaePd);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
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
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync iPaePDE++;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertFatal(iPaePDE < 512);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
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) ));
702a8ee2dc1de96f2f77e97135015d3e243186fdvboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertMsg(pShwPdpt->a[iPdpt].u & PGM_PLXFLAGS_MAPPING,
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync ("%RX64; iPdpt=%#x iPDE=%#x iPaePDE=%#x %RGv %s\n",
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync pShwPdpt->a[iPdpt].u,
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync iPDE, iPdpt, iPaePDE, pMap->GCPtr, R3STRING(pMap->pszDesc) ));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync PCPGMPOOLPAGE pPoolPagePd = pgmPoolGetPage(pPool, pShwPdpt->a[iPdpt].u & X86_PDPE_PG_MASK);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertFatal(pPoolPagePd);
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertMsg(pPoolPagePd->cLocked, (".idx=%d .type=%d\n", pPoolPagePd->idx, pPoolPagePd->enmKind));
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync break;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync default:
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync AssertFailed();
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync break;
2f3883b126a405f92b19e829472f614c7352b4f9vboxsync }
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync }
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync}
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync/**
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync * Check the hypervisor mappings in the active CR3.
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync *
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync * @param pVM The virtual machine.
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync */
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsyncVMMDECL(void) PGMMapCheck(PVM pVM)
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync{
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync /*
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync * Can skip this if mappings are disabled.
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync */
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync if (!pgmMapAreMappingsEnabled(&pVM->pgm.s))
510567648d46488f4166e5f69ffffe3eeeeec4d9vboxsync return;
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync
fb41ad77bcfbdb3aaa1fc9503a37ee6a70dc6461vboxsync /* This only applies to raw mode where we only support 1 VCPU. */
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync Assert(pVM->cCpus == 1);
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync PVMCPU pVCpu = VMMGetCpu0(pVM);
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync Assert(pVCpu->pgm.s.CTX_SUFF(pShwPageCR3));
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync /*
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync * Iterate mappings.
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync */
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync pgmLock(pVM); /* to avoid assertions */
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync for (PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings); pCur; pCur = pCur->CTX_SUFF(pNext))
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync {
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync unsigned iPDE = pCur->GCPtr >> X86_PD_SHIFT;
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync pgmMapCheckShadowPDEs(pVM, pVCpu, pVCpu->pgm.s.CTX_SUFF(pShwPageCR3), pCur, iPDE);
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync }
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync pgmUnlock(pVM);
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync}
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync#endif /* defined(VBOX_STRICT) && !defined(IN_RING0) */
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync#ifndef IN_RING0
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync/**
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync * Apply the hypervisor mappings to the active CR3.
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync *
c193ae401647c574d0ef52af57c32cf5d7c44966vboxsync * @returns VBox status.
c193ae401647c574d0ef52af57c32cf5d7c44966vboxsync * @param pVM The virtual machine.
c193ae401647c574d0ef52af57c32cf5d7c44966vboxsync * @param pShwPageCR3 CR3 root page
c55bf74b54ecdfb5ebc4e5d90b620d0fee31737evboxsync */
c193ae401647c574d0ef52af57c32cf5d7c44966vboxsyncint pgmMapActivateCR3(PVM pVM, PPGMPOOLPAGE pShwPageCR3)
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync{
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync /*
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * Skip this if disabled or if it doesn't apply.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync */
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync if ( !pgmMapAreMappingsEnabled(&pVM->pgm.s)
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync || pVM->cCpus > 1)
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync return VINF_SUCCESS;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync
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
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync#ifdef VBOX_STRICT
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync PVMCPU pVCpu = VMMGetCpu0(pVM);
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync Assert(pShwPageCR3 && pShwPageCR3 == pVCpu->pgm.s.CTX_SUFF(pShwPageCR3));
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync#endif
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync /*
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * Iterate mappings.
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync */
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync for (PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings); pCur; pCur = pCur->CTX_SUFF(pNext))
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync {
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync unsigned iPDE = pCur->GCPtr >> X86_PD_SHIFT;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync pgmMapSetShadowPDEs(pVM, pCur, iPDE);
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync }
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync return VINF_SUCCESS;
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync}
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync
510567648d46488f4166e5f69ffffe3eeeeec4d9vboxsync
510567648d46488f4166e5f69ffffe3eeeeec4d9vboxsync/**
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * Remove the hypervisor mappings from the specified CR3
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync *
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @returns VBox status.
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsync * @param pVM The virtual machine.
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync * @param pShwPageCR3 CR3 root page
cd5df721f068659172f3bf95de8fedeb465f057dvboxsync */
ecf100db90e8e3af96312908282d3c20e754fbe8vboxsyncint pgmMapDeactivateCR3(PVM pVM, PPGMPOOLPAGE pShwPageCR3)
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync{
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync /*
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync * Skip this if disabled or if it doesn't apply.
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync */
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync if ( !pgmMapAreMappingsEnabled(&pVM->pgm.s)
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync || pVM->cCpus > 1)
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync return VINF_SUCCESS;
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Assert(pShwPageCR3);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Log4(("pgmMapDeactivateCR3: fixed mappings=%d idxShwPageCR3=%#x\n", pVM->pgm.s.fMappingsFixed, pShwPageCR3 ? pShwPageCR3->idx : NIL_PGMPOOL_IDX));
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync /*
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * Iterate mappings.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync */
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync for (PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings); pCur; pCur = pCur->CTX_SUFF(pNext))
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync {
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync unsigned iPDE = pCur->GCPtr >> X86_PD_SHIFT;
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync pgmMapClearShadowPDEs(pVM, pShwPageCR3, pCur, iPDE, true /*fDeactivateCR3*/);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync }
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync return VINF_SUCCESS;
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync}
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync/**
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * Checks guest PD for conflicts with VMM GC mappings.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync *
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * @returns true if conflict detected.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * @returns false if not.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * @param pVM The virtual machine.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync */
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsyncVMMDECL(bool) PGMMapHasConflicts(PVM pVM)
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync{
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync /*
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * Can skip this if mappings are safely fixed.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync */
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync if (!pgmMapAreMappingsFloating(&pVM->pgm.s))
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync return false;
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Assert(pVM->cCpus == 1);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync /* This only applies to raw mode where we only support 1 VCPU. */
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync PVMCPU pVCpu = &pVM->aCpus[0];
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync PGMMODE const enmGuestMode = PGMGetGuestMode(pVCpu);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Assert(enmGuestMode <= PGMMODE_PAE_NX);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync /*
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * Iterate mappings.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync */
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync if (enmGuestMode == PGMMODE_32_BIT)
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync {
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync /*
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * Resolve the page directory.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync */
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync PX86PD pPD = pgmGstGet32bitPDPtr(pVCpu);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Assert(pPD);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync for (PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings); pCur; pCur = pCur->CTX_SUFF(pNext))
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync {
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync unsigned iPDE = pCur->GCPtr >> X86_PD_SHIFT;
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync unsigned iPT = pCur->cPTs;
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync while (iPT-- > 0)
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync if ( pPD->a[iPDE + iPT].n.u1Present /** @todo PGMGstGetPDE. */
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync && (pVM->fRawR0Enabled || pPD->a[iPDE + iPT].n.u1User))
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync {
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync STAM_COUNTER_INC(&pVM->pgm.s.CTX_SUFF(pStats)->StatR3DetectedConflicts);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync#ifdef IN_RING3
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Log(("PGMHasMappingConflicts: Conflict was detected at %08RX32 for mapping %s (32 bits)\n"
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync " iPDE=%#x iPT=%#x PDE=%RGp.\n",
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync (iPT + iPDE) << X86_PD_SHIFT, pCur->pszDesc,
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync iPDE, iPT, pPD->a[iPDE + iPT].au32[0]));
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync#else
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Log(("PGMHasMappingConflicts: Conflict was detected at %08RX32 for mapping (32 bits)\n"
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync " iPDE=%#x iPT=%#x PDE=%RGp.\n",
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync (iPT + iPDE) << X86_PD_SHIFT,
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync iPDE, iPT, pPD->a[iPDE + iPT].au32[0]));
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync#endif
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync return true;
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync }
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync }
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync }
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync else if ( enmGuestMode == PGMMODE_PAE
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync || enmGuestMode == PGMMODE_PAE_NX)
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync {
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync for (PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings); pCur; pCur = pCur->CTX_SUFF(pNext))
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync {
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync RTGCPTR GCPtr = pCur->GCPtr;
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync
3fb3de312d1ff675e0f7cc62a7d46cbb1d5d9353vboxsync unsigned iPT = pCur->cb >> X86_PD_PAE_SHIFT;
c10a6f0c7041e4d1ee50ad38425aab9d43c55522vboxsync while (iPT-- > 0)
5f2b03bf7695dabd71222dba123532a3f76828c1vboxsync {
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync X86PDEPAE Pde = pgmGstGetPaePDE(pVCpu, GCPtr);
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync if ( Pde.n.u1Present
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync && (pVM->fRawR0Enabled || Pde.n.u1User))
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync {
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync STAM_COUNTER_INC(&pVM->pgm.s.CTX_SUFF(pStats)->StatR3DetectedConflicts);
d4a9d525e6f2111d462d2d96462dced6b9ec00efvboxsync#ifdef IN_RING3
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Log(("PGMHasMappingConflicts: Conflict was detected at %RGv for mapping %s (PAE)\n"
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync " PDE=%016RX64.\n",
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync GCPtr, pCur->pszDesc, Pde.u));
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync#else
b8bb9c9f6b8ebfd0a7d6df0c0289f9fe80241750vboxsync Log(("PGMHasMappingConflicts: Conflict was detected at %RGv for mapping (PAE)\n"
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync " PDE=%016RX64.\n",
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync GCPtr, Pde.u));
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync#endif
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync return true;
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync }
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync GCPtr += (1 << X86_PD_PAE_SHIFT);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync }
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync }
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync }
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync else
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync AssertFailed();
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync return false;
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync}
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync/**
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * Checks and resolves (ring 3 only) guest conflicts with the guest mappings.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync *
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync * @returns VBox status.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * @param pVM The virtual machine.
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync */
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsyncint pgmMapResolveConflicts(PVM pVM)
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync{
b8bb9c9f6b8ebfd0a7d6df0c0289f9fe80241750vboxsync /* The caller is expected to check these two conditions. */
b8bb9c9f6b8ebfd0a7d6df0c0289f9fe80241750vboxsync Assert(!pVM->pgm.s.fMappingsFixed);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Assert(!pVM->pgm.s.fMappingsDisabled);
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync /* This only applies to raw mode where we only support 1 VCPU. */
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Assert(pVM->cCpus == 1);
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync PVMCPU pVCpu = &pVM->aCpus[0];
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync PGMMODE const enmGuestMode = PGMGetGuestMode(pVCpu);
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync Assert(enmGuestMode <= PGMMODE_PAE_NX);
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync
35e6d303696e46d969aaf9a59cc381333a483b0bvboxsync if (enmGuestMode == PGMMODE_32_BIT)
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync {
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync /*
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync * Resolve the page directory.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync */
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync PX86PD pPD = pgmGstGet32bitPDPtr(pVCpu);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Assert(pPD);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync /*
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync * Iterate mappings.
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync */
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync for (PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings); pCur; )
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync {
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync PPGMMAPPING pNext = pCur->CTX_SUFF(pNext);
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync unsigned iPDE = pCur->GCPtr >> X86_PD_SHIFT;
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync unsigned iPT = pCur->cPTs;
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync while (iPT-- > 0)
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync {
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync if ( pPD->a[iPDE + iPT].n.u1Present /** @todo PGMGstGetPDE. */
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync && ( pVM->fRawR0Enabled
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync || pPD->a[iPDE + iPT].n.u1User))
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync {
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync STAM_COUNTER_INC(&pVM->pgm.s.CTX_SUFF(pStats)->StatR3DetectedConflicts);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync#ifdef IN_RING3
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Log(("PGMHasMappingConflicts: Conflict was detected at %08RX32 for mapping %s (32 bits)\n"
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync " iPDE=%#x iPT=%#x PDE=%RGp.\n",
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync (iPT + iPDE) << X86_PD_SHIFT, pCur->pszDesc,
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync iPDE, iPT, pPD->a[iPDE + iPT].au32[0]));
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync int rc = pgmR3SyncPTResolveConflict(pVM, pCur, pPD, iPDE << X86_PD_SHIFT);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync AssertRCReturn(rc, rc);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync break;
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync#else
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync Log(("PGMHasMappingConflicts: Conflict was detected at %08RX32 for mapping (32 bits)\n"
462e60a19d02a99b2b1a5c08dff74bb0808d707cvboxsync " iPDE=%#x iPT=%#x PDE=%RGp.\n",
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync (iPT + iPDE) << X86_PD_SHIFT,
ca3db470494a8b6eaec69ea37468a5cda65e2da8vboxsync iPDE, iPT, pPD->a[iPDE + iPT].au32[0]));
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync return VINF_PGM_SYNC_CR3;
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync#endif
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync }
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync }
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync pCur = pNext;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync }
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync }
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync else if ( enmGuestMode == PGMMODE_PAE
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync || enmGuestMode == PGMMODE_PAE_NX)
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync {
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync /*
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync * Iterate mappings.
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync */
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync for (PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings); pCur;)
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync {
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync PPGMMAPPING pNext = pCur->CTX_SUFF(pNext);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync RTGCPTR GCPtr = pCur->GCPtr;
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync unsigned iPT = pCur->cb >> X86_PD_PAE_SHIFT;
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync while (iPT-- > 0)
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync {
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync X86PDEPAE Pde = pgmGstGetPaePDE(pVCpu, GCPtr);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync if ( Pde.n.u1Present
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync && (pVM->fRawR0Enabled || Pde.n.u1User))
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync {
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync STAM_COUNTER_INC(&pVM->pgm.s.CTX_SUFF(pStats)->StatR3DetectedConflicts);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync#ifdef IN_RING3
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Log(("PGMHasMappingConflicts: Conflict was detected at %RGv for mapping %s (PAE)\n"
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync " PDE=%016RX64.\n",
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync GCPtr, pCur->pszDesc, Pde.u));
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync int rc = pgmR3SyncPTResolveConflictPAE(pVM, pCur, pCur->GCPtr);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync AssertRCReturn(rc, rc);
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync break;
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync#else
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync Log(("PGMHasMappingConflicts: Conflict was detected at %RGv for mapping (PAE)\n"
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync " PDE=%016RX64.\n",
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync GCPtr, Pde.u));
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync return VINF_PGM_SYNC_CR3;
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync#endif
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync }
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync GCPtr += (1 << X86_PD_PAE_SHIFT);
88cc9bf61296bc5526344415167bb2625ae1dd99vboxsync }
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync pCur = pNext;
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync }
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync }
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync else
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync AssertFailed();
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync Assert(!PGMMapHasConflicts(pVM));
5050fc8de0b121eab1b738d7c1007cde4903284dvboxsync return VINF_SUCCESS;
8bc8d66f188d5357155b8340e2d489573be2b607vboxsync}
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync#endif /* IN_RING0 */
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync
4171ffb38eb8720b2ae9a8d13e95103ab26cfd12vboxsync