PGMAll.cpp revision 134a71c1528b56afe4db843ab63ec5a5b849535b
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* $Id$ */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** @file
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * PGM - Page Manager and Monitor - All context code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * available from http://www.virtualbox.org. This file is free software;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync *
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * additional information or have any questions.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*******************************************************************************
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync* Header Files *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync*******************************************************************************/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define LOG_GROUP LOG_GROUP_PGM
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <VBox/pgm.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <VBox/cpum.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <VBox/selm.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <VBox/iom.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <VBox/sup.h>
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync#include <VBox/mm.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <VBox/stam.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <VBox/csam.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <VBox/patm.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <VBox/trpm.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <VBox/rem.h>
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync#include <VBox/em.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <VBox/hwaccm.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "PGMInternal.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <VBox/vm.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/assert.h>
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync#include <iprt/asm.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/string.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <VBox/log.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <VBox/param.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <VBox/err.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*******************************************************************************
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync* Structures and Typedefs *
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync*******************************************************************************/
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Stated structure for PGM_GST_NAME(HandlerVirtualUpdate) that's
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * passed to PGM_GST_NAME(VirtHandlerUpdateOne) during enumeration.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
afed5ab737f4aacfae3fe73776f40e989190a7cavboxsynctypedef struct PGMHVUSTATE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** The VM handle. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PVM pVM;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** The todo flags. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTUINT fTodo;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** The CR4 register value. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t cr4;
0174432b2b1a760b89840ba696f7ba51def65dddvboxsync} PGMHVUSTATE, *PPGMHVUSTATE;
2daaccf68be3773aee600c5c3e48bcf5401418a6vboxsync
0174432b2b1a760b89840ba696f7ba51def65dddvboxsync
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync/*******************************************************************************
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync* Internal Functions *
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync*******************************************************************************/
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync/*
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync * Shadow - 32-bit mode
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync */
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync#define PGM_SHW_TYPE PGM_TYPE_32BIT
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync#define PGM_SHW_NAME(name) PGM_SHW_NAME_32BIT(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "PGMAllShw.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Guest - real mode */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_TYPE PGM_TYPE_REAL
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_NAME(name) PGM_GST_NAME_REAL(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_32BIT_REAL(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_32BIT_PT_FOR_PHYS
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "PGMAllGst.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "PGMAllBth.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef BTH_PGMPOOLKIND_PT_FOR_PT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef PGM_BTH_NAME
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef PGM_GST_TYPE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef PGM_GST_NAME
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Guest - protected mode */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_TYPE PGM_TYPE_PROT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_NAME(name) PGM_GST_NAME_PROT(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_32BIT_PROT(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_32BIT_PT_FOR_PHYS
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "PGMAllGst.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "PGMAllBth.h"
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#undef BTH_PGMPOOLKIND_PT_FOR_PT
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#undef PGM_BTH_NAME
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#undef PGM_GST_TYPE
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#undef PGM_GST_NAME
22e281e75ed636601178296c6daebda8f1d17c59vboxsync
22e281e75ed636601178296c6daebda8f1d17c59vboxsync/* Guest - 32-bit mode */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#define PGM_GST_TYPE PGM_TYPE_32BIT
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#define PGM_GST_NAME(name) PGM_GST_NAME_32BIT(name)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_32BIT_32BIT(name)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_32BIT_PT_FOR_32BIT_PT
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_32BIT_PT_FOR_32BIT_4MB
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#include "PGMAllGst.h"
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#include "PGMAllBth.h"
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#undef BTH_PGMPOOLKIND_PT_FOR_BIG
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#undef BTH_PGMPOOLKIND_PT_FOR_PT
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#undef PGM_BTH_NAME
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#undef PGM_GST_TYPE
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#undef PGM_GST_NAME
22e281e75ed636601178296c6daebda8f1d17c59vboxsync
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#undef PGM_SHW_TYPE
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#undef PGM_SHW_NAME
22e281e75ed636601178296c6daebda8f1d17c59vboxsync
22e281e75ed636601178296c6daebda8f1d17c59vboxsync
7b80828e5760a8814fe6cd494d2715a4544fbddcvboxsync/*
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * Shadow - PAE mode
22e281e75ed636601178296c6daebda8f1d17c59vboxsync */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#define PGM_SHW_TYPE PGM_TYPE_PAE
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#define PGM_SHW_NAME(name) PGM_SHW_NAME_PAE(name)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_REAL(name)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#include "PGMAllShw.h"
22e281e75ed636601178296c6daebda8f1d17c59vboxsync
22e281e75ed636601178296c6daebda8f1d17c59vboxsync/* Guest - real mode */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#define PGM_GST_TYPE PGM_TYPE_REAL
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#define PGM_GST_NAME(name) PGM_GST_NAME_REAL(name)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_REAL(name)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PHYS
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#include "PGMAllBth.h"
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#undef BTH_PGMPOOLKIND_PT_FOR_PT
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#undef PGM_BTH_NAME
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#undef PGM_GST_TYPE
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#undef PGM_GST_NAME
d1cbbd799d8912978f5146960b6780f387bb414bvboxsync
22e281e75ed636601178296c6daebda8f1d17c59vboxsync/* Guest - protected mode */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#define PGM_GST_TYPE PGM_TYPE_PROT
c17f5c90f2cb60b38ecabebce128724c6ff2d036vboxsync#define PGM_GST_NAME(name) PGM_GST_NAME_PROT(name)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_PROT(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PHYS
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "PGMAllBth.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef BTH_PGMPOOLKIND_PT_FOR_PT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef PGM_BTH_NAME
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef PGM_GST_TYPE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef PGM_GST_NAME
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Guest - 32-bit mode */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_TYPE PGM_TYPE_32BIT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_NAME(name) PGM_GST_NAME_32BIT(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_32BIT(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_32BIT_PT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_32BIT_4MB
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "PGMAllBth.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef BTH_PGMPOOLKIND_PT_FOR_BIG
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef BTH_PGMPOOLKIND_PT_FOR_PT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef PGM_BTH_NAME
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef PGM_GST_TYPE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef PGM_GST_NAME
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Guest - PAE mode */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_TYPE PGM_TYPE_PAE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_NAME(name) PGM_GST_NAME_PAE(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_PAE(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PAE_PT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "PGMAllGst.h"
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync#include "PGMAllBth.h"
a11c569636fa6838bd423f4631a9660a5a84204bvboxsync#undef BTH_PGMPOOLKIND_PT_FOR_BIG
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef BTH_PGMPOOLKIND_PT_FOR_PT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef PGM_BTH_NAME
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef PGM_GST_TYPE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef PGM_GST_NAME
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef PGM_SHW_TYPE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef PGM_SHW_NAME
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#ifndef IN_GC /* AMD64 implies VT-x/AMD-V */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Shadow - AMD64 mode
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_SHW_TYPE PGM_TYPE_AMD64
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_SHW_NAME(name) PGM_SHW_NAME_AMD64(name)
3ecf9412133496b2aeb090cfd33a286404ec59fbvboxsync#include "PGMAllShw.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Guest - protected mode */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_TYPE PGM_TYPE_PROT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_NAME(name) PGM_GST_NAME_PROT(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_AMD64_PROT(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PHYS
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "PGMAllBth.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef BTH_PGMPOOLKIND_PT_FOR_PT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef PGM_BTH_NAME
750d4d0506a38b2e80c997075d40aad474e675fbvboxsync#undef PGM_GST_TYPE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef PGM_GST_NAME
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Guest - AMD64 mode */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_TYPE PGM_TYPE_AMD64
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_NAME(name) PGM_GST_NAME_AMD64(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_AMD64_AMD64(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PAE_PT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "PGMAllGst.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "PGMAllBth.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#undef BTH_PGMPOOLKIND_PT_FOR_BIG
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync#undef BTH_PGMPOOLKIND_PT_FOR_PT
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync#undef PGM_BTH_NAME
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync#undef PGM_GST_TYPE
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync#undef PGM_GST_NAME
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync#undef PGM_SHW_TYPE
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync#undef PGM_SHW_NAME
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync#endif
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
576d4214137bce409cdcf01e8df4a0bca5e0b2d1vboxsync * #PF Handler.
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync *
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * @returns VBox status code (appropriate for trap handling and GC return).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM VM Handle.
72ef2b9fc5ffc01d0dabd5052d6e8baa3a952773vboxsync * @param uErr The trap error code.
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * @param pRegFrame Trap register frame.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pvFault The fault address.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGMDECL(int) PGMTrap0eHandler(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("PGMTrap0eHandler: uErr=%#x pvFault=%VGv eip=%VGv\n", uErr, pvFault, pRegFrame->eip));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_PROFILE_START(&pVM->pgm.s.StatGCTrap0e, a);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_STATS({ pVM->pgm.s.CTXSUFF(pStatTrap0eAttribution) = NULL; } );
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync#ifdef VBOX_WITH_STATISTICS
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Error code stats.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (uErr & X86_TRAP_PF_US)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync if (!(uErr & X86_TRAP_PF_P))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (uErr & X86_TRAP_PF_RW)
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatGCTrap0eUSNotPresentWrite);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
909f4391cc20b4a3a9a2d3f8718084b669663ab2vboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatGCTrap0eUSNotPresentRead);
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync }
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync else if (uErr & X86_TRAP_PF_RW)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatGCTrap0eUSWrite);
8a132edc1577cbe2a19cd778c1b2bea6ae5e8515vboxsync else if (uErr & X86_TRAP_PF_RSVD)
3ecd8008b81f02a04220705ae0033142af363280vboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatGCTrap0eUSReserved);
3ecd8008b81f02a04220705ae0033142af363280vboxsync else if (uErr & X86_TRAP_PF_ID)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatGCTrap0eUSNXE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
576d4214137bce409cdcf01e8df4a0bca5e0b2d1vboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatGCTrap0eUSRead);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { /* Supervisor */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!(uErr & X86_TRAP_PF_P))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (uErr & X86_TRAP_PF_RW)
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatGCTrap0eSVNotPresentWrite);
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatGCTrap0eSVNotPresentRead);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
3ecd8008b81f02a04220705ae0033142af363280vboxsync else if (uErr & X86_TRAP_PF_RW)
3ecd8008b81f02a04220705ae0033142af363280vboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatGCTrap0eSVWrite);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync else if (uErr & X86_TRAP_PF_ID)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatGCTrap0eSNXE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else if (uErr & X86_TRAP_PF_RSVD)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatGCTrap0eSVReserved);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#endif
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
247b55faa8d054157f2481e68caca36f4dc9542cvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Call the worker.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = PGM_BTH_PFN(Trap0eHandler, pVM)(pVM, uErr, pRegFrame, pvFault);
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync if (rc == VINF_PGM_SYNCPAGE_MODIFIED_PDE)
57399ab65e2825c324fb9dcb4642d4ae2c232509vboxsync rc = VINF_SUCCESS;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync STAM_STATS({ if (!pVM->pgm.s.CTXSUFF(pStatTrap0eAttribution))
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync pVM->pgm.s.CTXSUFF(pStatTrap0eAttribution) = &pVM->pgm.s.StatTrap0eMisc; });
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync STAM_PROFILE_STOP_EX(&pVM->pgm.s.StatGCTrap0e, pVM->pgm.s.CTXSUFF(pStatTrap0eAttribution), a);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync * Prefetch a page
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Typically used to sync commonly used pages before entering raw mode
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * after a CR3 reload.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status code suitable for scheduling.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @retval VINF_SUCCESS on success.
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * @retval VINF_PGM_SYNC_CR3 if we're out of shadow pages or something like that.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * @param pVM VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param GCPtrPage Page to invalidate.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGMDECL(int) PGMPrefetchPage(PVM pVM, RTGCPTR GCPtrPage)
247b55faa8d054157f2481e68caca36f4dc9542cvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_PROFILE_START(&pVM->pgm.s.StatHCPrefetch, a);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = PGM_BTH_PFN(PrefetchPage, pVM)(pVM, (RTGCUINTPTR)GCPtrPage);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_PROFILE_STOP(&pVM->pgm.s.StatHCPrefetch, a);
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync AssertMsg(rc == VINF_SUCCESS || rc == VINF_PGM_SYNC_CR3 || VBOX_FAILURE(rc), ("rc=%Vrc\n", rc));
22e281e75ed636601178296c6daebda8f1d17c59vboxsync return rc;
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync}
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Gets the mapping corresponding to the specified address (if any).
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns Pointer to the mapping.
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync * @returns NULL if not
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The virtual machine.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param GCPtr The guest context pointer.
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync */
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsyncPPGMMAPPING pgmGetMapping(PVM pVM, RTGCPTR GCPtr)
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync{
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync PPGMMAPPING pMapping = CTXALLSUFF(pVM->pgm.s.pMappings);
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync while (pMapping)
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync {
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync if ((uintptr_t)GCPtr < (uintptr_t)pMapping->GCPtr)
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync break;
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync if ((uintptr_t)GCPtr - (uintptr_t)pMapping->GCPtr < pMapping->cb)
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync {
22e281e75ed636601178296c6daebda8f1d17c59vboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatGCSyncPTConflict);
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync return pMapping;
e50404712a2b5234c42bdf9740bddab5729ba188vboxsync }
57399ab65e2825c324fb9dcb4642d4ae2c232509vboxsync pMapping = CTXALLSUFF(pMapping->pNext);
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync }
57399ab65e2825c324fb9dcb4642d4ae2c232509vboxsync return NULL;
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync}
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync
1843553dbdf4e46417158b4c6348c503adf10740vboxsync
1843553dbdf4e46417158b4c6348c503adf10740vboxsync/**
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * Verifies a range of pages for read or write access
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync *
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * Only checks the guest's page tables
806d0b554daa555364af5f87bc96eccbe760db7avboxsync *
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * @returns VBox status code.
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * @param pVM VM handle.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * @param Addr Guest virtual address to check
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * @param cbSize Access size
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * @param fAccess Access type (r/w, user/supervisor (X86_PTE_*))
1843553dbdf4e46417158b4c6348c503adf10740vboxsync */
22e281e75ed636601178296c6daebda8f1d17c59vboxsyncPGMDECL(int) PGMIsValidAccess(PVM pVM, RTGCUINTPTR Addr, uint32_t cbSize, uint32_t fAccess)
1843553dbdf4e46417158b4c6348c503adf10740vboxsync{
1843553dbdf4e46417158b4c6348c503adf10740vboxsync /*
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * Validate input.
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync */
1843553dbdf4e46417158b4c6348c503adf10740vboxsync if (fAccess & ~(X86_PTE_US | X86_PTE_RW))
ebbb1f6c7e8bae363a4efda4b35b58c8467d24bcvboxsync {
1843553dbdf4e46417158b4c6348c503adf10740vboxsync AssertMsgFailed(("PGMIsValidAccess: invalid access type %08x\n", fAccess));
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync return VERR_INVALID_PARAMETER;
1843553dbdf4e46417158b4c6348c503adf10740vboxsync }
1843553dbdf4e46417158b4c6348c503adf10740vboxsync
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync uint64_t fPage;
1843553dbdf4e46417158b4c6348c503adf10740vboxsync int rc = PGMGstGetPage(pVM, (RTGCPTR)Addr, &fPage, NULL);
1843553dbdf4e46417158b4c6348c503adf10740vboxsync if (VBOX_FAILURE(rc))
ebbb1f6c7e8bae363a4efda4b35b58c8467d24bcvboxsync {
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync Log(("PGMIsValidAccess: access violation for %VGv rc=%d\n", Addr, rc));
1843553dbdf4e46417158b4c6348c503adf10740vboxsync return VINF_EM_RAW_GUEST_TRAP;
1843553dbdf4e46417158b4c6348c503adf10740vboxsync }
22e281e75ed636601178296c6daebda8f1d17c59vboxsync
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync /*
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * Check if the access would cause a page fault
806d0b554daa555364af5f87bc96eccbe760db7avboxsync *
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * Note that hypervisor page directories are not present in the guest's tables, so this check
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * is sufficient.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync */
1843553dbdf4e46417158b4c6348c503adf10740vboxsync bool fWrite = !!(fAccess & X86_PTE_RW);
1843553dbdf4e46417158b4c6348c503adf10740vboxsync bool fUser = !!(fAccess & X86_PTE_US);
1843553dbdf4e46417158b4c6348c503adf10740vboxsync if ( !(fPage & X86_PTE_P)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync || (fWrite && !(fPage & X86_PTE_RW))
1843553dbdf4e46417158b4c6348c503adf10740vboxsync || (fUser && !(fPage & X86_PTE_US)) )
1843553dbdf4e46417158b4c6348c503adf10740vboxsync {
1843553dbdf4e46417158b4c6348c503adf10740vboxsync Log(("PGMIsValidAccess: access violation for %VGv attr %#llx vs %d:%d\n", Addr, fPage, fWrite, fUser));
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync return VINF_EM_RAW_GUEST_TRAP;
1843553dbdf4e46417158b4c6348c503adf10740vboxsync }
ebbb1f6c7e8bae363a4efda4b35b58c8467d24bcvboxsync if ( VBOX_SUCCESS(rc)
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync && PAGE_ADDRESS(Addr) != PAGE_ADDRESS(Addr + cbSize))
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync return PGMIsValidAccess(pVM, Addr + PAGE_SIZE, (cbSize > PAGE_SIZE) ? cbSize - PAGE_SIZE : 1, fAccess);
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync return rc;
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync}
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Verifies a range of pages for read or write access
22e281e75ed636601178296c6daebda8f1d17c59vboxsync *
e52f819639386db020b2a635b47a415248c7fbf9vboxsync * Supports handling of pages marked for dirty bit tracking and CSAM
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM VM handle.
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * @param Addr Guest virtual address to check
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * @param cbSize Access size
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * @param fAccess Access type (r/w, user/supervisor (X86_PTE_*))
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync */
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsyncPGMDECL(int) PGMVerifyAccess(PVM pVM, RTGCUINTPTR Addr, uint32_t cbSize, uint32_t fAccess)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * Validate input.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync if (fAccess & ~(X86_PTE_US | X86_PTE_RW))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
0e77737b0ba913683e614db11463b31ca67aacbevboxsync AssertMsgFailed(("PGMVerifyAccess: invalid access type %08x\n", fAccess));
0e77737b0ba913683e614db11463b31ca67aacbevboxsync return VERR_INVALID_PARAMETER;
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync }
0e77737b0ba913683e614db11463b31ca67aacbevboxsync
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync uint64_t fPageGst;
0e77737b0ba913683e614db11463b31ca67aacbevboxsync int rc = PGMGstGetPage(pVM, (RTGCPTR)Addr, &fPageGst, NULL);
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync if (VBOX_FAILURE(rc))
22e281e75ed636601178296c6daebda8f1d17c59vboxsync {
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync Log(("PGMVerifyAccess: access violation for %VGv rc=%d\n", Addr, rc));
2d53f6e472561965d363674e17f48d3bdffc24d3vboxsync return VINF_EM_RAW_GUEST_TRAP;
2d53f6e472561965d363674e17f48d3bdffc24d3vboxsync }
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync /*
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * Check if the access would cause a page fault
22e281e75ed636601178296c6daebda8f1d17c59vboxsync *
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * Note that hypervisor page directories are not present in the guest's tables, so this check
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * is sufficient.
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync */
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync const bool fWrite = !!(fAccess & X86_PTE_RW);
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync const bool fUser = !!(fAccess & X86_PTE_US);
2d53f6e472561965d363674e17f48d3bdffc24d3vboxsync if ( !(fPageGst & X86_PTE_P)
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync || (fWrite && !(fPageGst & X86_PTE_RW))
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync || (fUser && !(fPageGst & X86_PTE_US)) )
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync {
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync Log(("PGMVerifyAccess: access violation for %VGv attr %#llx vs %d:%d\n", Addr, fPageGst, fWrite, fUser));
2d53f6e472561965d363674e17f48d3bdffc24d3vboxsync return VINF_EM_RAW_GUEST_TRAP;
0e77737b0ba913683e614db11463b31ca67aacbevboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Next step is to verify if we protected this page for dirty bit tracking or for CSAM scanning
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGMShwGetPage(pVM, (RTGCPTR)Addr, NULL, NULL);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync if ( rc == VERR_PAGE_NOT_PRESENT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync || rc == VERR_PAGE_TABLE_NOT_PRESENT)
8e972b677df5ee27b99211fc7e456a5aa50f3e68vboxsync {
8e972b677df5ee27b99211fc7e456a5aa50f3e68vboxsync /*
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * Page is not present in our page tables.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Try to sync it!
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync Assert(X86_TRAP_PF_RW == X86_PTE_RW && X86_TRAP_PF_US == X86_PTE_US);
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync uint32_t uErr = fAccess & (X86_TRAP_PF_RW | X86_TRAP_PF_US);
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync rc = PGM_BTH_PFN(VerifyAccessSyncPage, pVM)(pVM, Addr, fPageGst, uErr);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (rc != VINF_SUCCESS)
806d0b554daa555364af5f87bc96eccbe760db7avboxsync return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync else
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync AssertMsg(rc == VINF_SUCCESS, ("PGMShwGetPage %VGv failed with %Vrc\n", Addr, rc));
806d0b554daa555364af5f87bc96eccbe760db7avboxsync
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync#if 0 /* def VBOX_STRICT; triggers too often now */
806d0b554daa555364af5f87bc96eccbe760db7avboxsync /*
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * This check is a bit paranoid, but useful.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync */
806d0b554daa555364af5f87bc96eccbe760db7avboxsync /** @note this will assert when writing to monitored pages (a bit annoying actually) */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync uint64_t fPageShw;
806d0b554daa555364af5f87bc96eccbe760db7avboxsync rc = PGMShwGetPage(pVM, (RTGCPTR)Addr, &fPageShw, NULL);
806d0b554daa555364af5f87bc96eccbe760db7avboxsync if ( (rc == VERR_PAGE_NOT_PRESENT || VBOX_FAILURE(rc))
806d0b554daa555364af5f87bc96eccbe760db7avboxsync || (fWrite && !(fPageShw & X86_PTE_RW))
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync || (fUser && !(fPageShw & X86_PTE_US)) )
806d0b554daa555364af5f87bc96eccbe760db7avboxsync {
806d0b554daa555364af5f87bc96eccbe760db7avboxsync AssertMsgFailed(("Unexpected access violation for %VGv! rc=%Vrc write=%d user=%d\n",
d98e61ba075ed7d0b567a5d884bc85d643fe3de7vboxsync Addr, rc, fWrite && !(fPageShw & X86_PTE_RW), fUser && !(fPageShw & X86_PTE_US)));
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync return VINF_EM_RAW_GUEST_TRAP;
806d0b554daa555364af5f87bc96eccbe760db7avboxsync }
806d0b554daa555364af5f87bc96eccbe760db7avboxsync#endif
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync if ( VBOX_SUCCESS(rc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && ( PAGE_ADDRESS(Addr) != PAGE_ADDRESS(Addr + cbSize - 1)
806d0b554daa555364af5f87bc96eccbe760db7avboxsync || Addr + cbSize < Addr))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync /* Don't recursively call PGMVerifyAccess as we might run out of stack. */
806d0b554daa555364af5f87bc96eccbe760db7avboxsync for (;;)
806d0b554daa555364af5f87bc96eccbe760db7avboxsync {
22e281e75ed636601178296c6daebda8f1d17c59vboxsync Addr += PAGE_SIZE;
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync if (cbSize > PAGE_SIZE)
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync cbSize -= PAGE_SIZE;
806d0b554daa555364af5f87bc96eccbe760db7avboxsync else
e149c362e69e5f0bbd82da11fd8163b2d29c3a72vboxsync cbSize = 1;
806d0b554daa555364af5f87bc96eccbe760db7avboxsync rc = PGMVerifyAccess(pVM, Addr, 1, fAccess);
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync if (rc != VINF_SUCCESS)
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync break;
806d0b554daa555364af5f87bc96eccbe760db7avboxsync if (PAGE_ADDRESS(Addr) == PAGE_ADDRESS(Addr + cbSize - 1))
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync break;
806d0b554daa555364af5f87bc96eccbe760db7avboxsync }
806d0b554daa555364af5f87bc96eccbe760db7avboxsync }
806d0b554daa555364af5f87bc96eccbe760db7avboxsync return rc;
806d0b554daa555364af5f87bc96eccbe760db7avboxsync}
22e281e75ed636601178296c6daebda8f1d17c59vboxsync
806d0b554daa555364af5f87bc96eccbe760db7avboxsync
806d0b554daa555364af5f87bc96eccbe760db7avboxsync#ifndef IN_GC
806d0b554daa555364af5f87bc96eccbe760db7avboxsync/**
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync * Emulation of the invlpg instruction (HC only actually).
806d0b554daa555364af5f87bc96eccbe760db7avboxsync *
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * @returns VBox status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param GCPtrPage Page to invalidate.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @remark ASSUMES the page table entry or page directory is
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * valid. Fairly safe, but there could be edge cases!
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync * @todo Flush page or page directory only if necessary!
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGMDECL(int) PGMInvalidatePage(PVM pVM, RTGCPTR GCPtrPage)
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
22e281e75ed636601178296c6daebda8f1d17c59vboxsync LogFlow(("PGMInvalidatePage: GCPtrPage=%VGv\n", GCPtrPage));
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo merge PGMGCInvalidatePage with this one */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#ifndef IN_RING3
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Notify the recompiler so it can record this instruction.
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * Failure happens when it's out of space. We'll return to HC in that case.
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync rc = REMNotifyInvalidatePage(pVM, GCPtrPage);
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync if (VBOX_FAILURE(rc))
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync return rc;
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync#endif
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync
22e281e75ed636601178296c6daebda8f1d17c59vboxsync STAM_PROFILE_START(&CTXMID(pVM->pgm.s.Stat,InvalidatePage), a);
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync rc = PGM_BTH_PFN(InvalidatePage, pVM)(pVM, GCPtrPage);
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync STAM_PROFILE_STOP(&CTXMID(pVM->pgm.s.Stat,InvalidatePage), a);
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync
806d0b554daa555364af5f87bc96eccbe760db7avboxsync#ifndef IN_RING0
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync /*
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * Check if we have a pending update of the CR3 monitoring.
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync */
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync if ( VBOX_SUCCESS(rc)
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync && (pVM->pgm.s.fSyncFlags & PGM_SYNC_MONITOR_CR3))
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync {
03319aeaef07ef63a404237f2cb56199131f4a03vboxsync pVM->pgm.s.fSyncFlags &= ~PGM_SYNC_MONITOR_CR3;
1157941288c9533575a655c660af55d13da31eefvboxsync Assert(!pVM->pgm.s.fMappingsFixed);
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync Assert(pVM->pgm.s.GCPhysCR3 == pVM->pgm.s.GCPhysGstCR3Monitored);
1157941288c9533575a655c660af55d13da31eefvboxsync rc = PGM_GST_PFN(MonitorCR3, pVM)(pVM, pVM->pgm.s.GCPhysCR3);
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync }
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync#endif
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync#ifdef IN_RING3
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /*
8e8844a522f5d335f177a0313b03067d79cce201vboxsync * Inform CSAM about the flush
7bae75e0b207aa4d4cad2a951271ad1a0e8ab9fdvboxsync */
7bae75e0b207aa4d4cad2a951271ad1a0e8ab9fdvboxsync /** @note this is to check if monitored pages have been changed; when we implement callbacks for virtual handlers, this is no longer required. */
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync CSAMR3FlushPage(pVM, GCPtrPage);
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync#endif
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync return rc;
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync}
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync#endif
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync/**
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync * Executes an instruction using the interpreter.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync *
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync * @returns VBox status code (appropriate for trap handling and GC return).
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * @param pVM VM handle.
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * @param pRegFrame Register frame.
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * @param pvFault Fault address.
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync */
22e281e75ed636601178296c6daebda8f1d17c59vboxsyncPGMDECL(int) PGMInterpretInstruction(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault)
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync{
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync uint32_t cb;
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync int rc = EMInterpretInstruction(pVM, pRegFrame, pvFault, &cb);
e149c362e69e5f0bbd82da11fd8163b2d29c3a72vboxsync if (rc == VERR_EM_INTERPRETER)
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync rc = VINF_EM_RAW_EMULATE_INSTR;
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync if (rc != VINF_SUCCESS)
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync Log(("PGMInterpretInstruction: returns %Rrc (pvFault=%VGv)\n", rc, pvFault));
57399ab65e2825c324fb9dcb4642d4ae2c232509vboxsync return rc;
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync}
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync/**
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * Gets effective page information (from the VMM page directory).
8e8844a522f5d335f177a0313b03067d79cce201vboxsync *
7bae75e0b207aa4d4cad2a951271ad1a0e8ab9fdvboxsync * @returns VBox status.
7bae75e0b207aa4d4cad2a951271ad1a0e8ab9fdvboxsync * @param pVM VM Handle.
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync * @param GCPtr Guest Context virtual address of the page.
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync * @param pfFlags Where to store the flags. These are X86_PTE_*.
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * @param pHCPhys Where to store the HC physical address of the page.
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * This is page aligned.
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * @remark You should use PGMMapGetPage() for pages in a mapping.
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync */
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsyncPGMDECL(int) PGMShwGetPage(PVM pVM, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys)
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync{
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync return PGM_SHW_PFN(GetPage,pVM)(pVM, (RTGCUINTPTR)GCPtr, pfFlags, pHCPhys);
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync}
7082d29724f6c3788977a51591b0379fd3acbf72vboxsync
7082d29724f6c3788977a51591b0379fd3acbf72vboxsync
7082d29724f6c3788977a51591b0379fd3acbf72vboxsync/**
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * Sets (replaces) the page flags for a range of pages in the shadow context.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync *
46b1ac1c3302722f93e787d0f0693965e88f5ceevboxsync * @returns VBox status.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * @param pVM VM handle.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * @param GCPtr The address of the first page.
e4ea543752422f1139923e3e506c625b0a1827c5vboxsync * @param cb The size of the range in bytes.
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * @param fFlags Page flags X86_PTE_*, excluding the page mask of course.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * @remark You must use PGMMapSetPage() for pages in a mapping.
f827fea1108b8f8a1a5f63318f6ec3cf4a9e7010vboxsync */
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsyncPGMDECL(int) PGMShwSetPage(PVM pVM, RTGCPTR GCPtr, size_t cb, uint64_t fFlags)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync{
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync return PGMShwModifyPage(pVM, GCPtr, cb, fFlags, 0);
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync}
5cf54b3ffeb7ee90685dcaec329ef71a729f5947vboxsync
806d0b554daa555364af5f87bc96eccbe760db7avboxsync
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync/**
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * Modify page flags for a range of pages in the shadow context.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync *
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * The existing flags are ANDed with the fMask and ORed with the fFlags.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync *
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * @returns VBox status code.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * @param pVM VM handle.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * @param GCPtr Virtual address of the first page in the range.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * @param cb Size (in bytes) of the range to apply the modification to.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * @param fFlags The OR mask - page flags X86_PTE_*, excluding the page mask of course.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * @param fMask The AND mask - page flags X86_PTE_*.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * Be very CAREFUL when ~'ing constants which could be 32-bit!
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync * @remark You must use PGMMapModifyPage() for pages in a mapping.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync */
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsyncPGMDECL(int) PGMShwModifyPage(PVM pVM, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask)
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync{
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync /*
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * Validate input.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync */
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync if (fFlags & X86_PTE_PAE_PG_MASK)
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync {
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync AssertMsgFailed(("fFlags=%#llx\n", fFlags));
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync return VERR_INVALID_PARAMETER;
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync }
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync if (!cb)
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync {
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync AssertFailed();
22e281e75ed636601178296c6daebda8f1d17c59vboxsync return VERR_INVALID_PARAMETER;
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync }
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync /*
e149c362e69e5f0bbd82da11fd8163b2d29c3a72vboxsync * Align the input.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync */
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync cb += (RTGCUINTPTR)GCPtr & PAGE_OFFSET_MASK;
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync cb = RT_ALIGN_Z(cb, PAGE_SIZE);
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync GCPtr = (RTGCPTR)((RTGCUINTPTR)GCPtr & PAGE_BASE_GC_MASK); /** @todo this ain't necessary, right... */
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync /*
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * Call worker.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync return PGM_SHW_PFN(ModifyPage, pVM)(pVM, (RTGCUINTPTR)GCPtr, cb, fFlags, fMask);
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync}
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync#ifndef IN_GC
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync/**
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * Gets the SHADOW page directory pointer for the specified address. Allocates
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * backing pages in case the PDPT or page dirctory is missing.
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync *
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * @returns VBox status.
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * @param pVM VM handle.
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * @param GCPtr The address.
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * @param ppPD Receives address of page directory
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync */
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsyncPGMDECL(int) PGMShwGetLongModePDPtr(PVM pVM, RTGCUINTPTR64 GCPtr, PX86PDPAE *ppPD)
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync{
22e281e75ed636601178296c6daebda8f1d17c59vboxsync PPGM pPGM = &pVM->pgm.s;
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync const unsigned iPml4e = (GCPtr >> X86_PML4_SHIFT) & X86_PML4_MASK;
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync PPGMPOOL pPool = pPGM->CTXSUFF(pPool);
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync PX86PML4E pPml4e;
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync PPGMPOOLPAGE pShwPage;
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync int rc;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync pPml4e = &pPGM->pHCPaePML4->a[iPml4e];
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync if ( !pPml4e->n.u1Present
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync && !(pPml4e->u & X86_PML4E_PG_MASK))
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync {
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync PX86PML4E pPml4eGst = &pPGM->pGstPaePML4HC->a[iPml4e];
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync Assert(!(pPml4e->u & X86_PML4E_PG_MASK));
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync rc = pgmPoolAlloc(pVM, pPml4eGst->u & X86_PML4E_PG_MASK, PGMPOOLKIND_64BIT_PDPT_FOR_64BIT_PDPT, PGMPOOL_IDX_PML4, iPml4e, &pShwPage);
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync if (rc == VERR_PGM_POOL_FLUSHED)
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync return VINF_PGM_SYNC_CR3;
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync
22e281e75ed636601178296c6daebda8f1d17c59vboxsync AssertRCReturn(rc, rc);
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync /* The PDPT was cached or created; hook it up now. */
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync pPml4e->u |= pShwPage->Core.Key;
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync }
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync else
22e281e75ed636601178296c6daebda8f1d17c59vboxsync {
8e8844a522f5d335f177a0313b03067d79cce201vboxsync pShwPage = pgmPoolGetPage(pPool, pPml4e->u & X86_PML4E_PG_MASK);
8e8844a522f5d335f177a0313b03067d79cce201vboxsync AssertReturn(pShwPage, VERR_INTERNAL_ERROR);
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync }
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync const unsigned iPdPt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64;
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync PX86PDPT pPdpt = (PX86PDPT)PGMPOOL_PAGE_2_PTR(pVM, pShwPage);
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync PX86PDPE pPdpe = &pPdpt->a[iPdPt];
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync if ( !pPdpe->n.u1Present
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync && !(pPdpe->u & X86_PDPE_PG_MASK))
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync {
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync PX86PML4E pPml4eGst = &pPGM->pGstPaePML4HC->a[iPml4e];
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync PX86PDPT pPdptGst;
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync rc = PGM_GCPHYS_2_PTR(pVM, pPml4eGst->u & X86_PML4E_PG_MASK, &pPdptGst);
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync AssertRCReturn(rc, rc);
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync Assert(!(pPdpe->u & X86_PDPE_PG_MASK));
22e281e75ed636601178296c6daebda8f1d17c59vboxsync rc = pgmPoolAlloc(pVM, pPdptGst->a[iPdPt].u & X86_PDPE_PG_MASK, PGMPOOLKIND_64BIT_PD_FOR_64BIT_PD, PGMPOOL_IDX_PDPT, iPdPt, &pShwPage);
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync if (rc == VERR_PGM_POOL_FLUSHED)
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync return VINF_PGM_SYNC_CR3;
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync AssertRCReturn(rc, rc);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync /* The PDPT was cached or created; hook it up now. */
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync pPdpe->u |= pShwPage->Core.Key;
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync }
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync else
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync {
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync pShwPage = pgmPoolGetPage(pPool, pPdpe->u & X86_PDPE_PG_MASK);
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync AssertReturn(pShwPage, VERR_INTERNAL_ERROR);
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync }
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync *ppPD = (PX86PDPAE)PGMPOOL_PAGE_2_PTR(pVM, pShwPage);
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync return VINF_SUCCESS;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync}
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync#endif
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync/**
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync * Gets effective Guest OS page information.
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync *
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync * When GCPtr is in a big page, the function will return as if it was a normal
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync * 4KB page. If the need for distinguishing between big and normal page becomes
5db1d52ffbcaa46c3d944c6c2d9c552306817d9avboxsync * necessary at a later point, a PGMGstGetPage() will be created for that
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * purpose.
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync *
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync * @returns VBox status.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * @param pVM VM Handle.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * @param GCPtr Guest Context virtual address of the page.
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync * @param pfFlags Where to store the flags. These are X86_PTE_*, even for big pages.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * @param pGCPhys Where to store the GC physical address of the page.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * This is page aligned. The fact that the
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync */
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsyncPGMDECL(int) PGMGstGetPage(PVM pVM, RTGCPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys)
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync{
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync return PGM_GST_PFN(GetPage,pVM)(pVM, (RTGCUINTPTR)GCPtr, pfFlags, pGCPhys);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync}
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync/**
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * Checks if the page is present.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync *
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync * @returns true if the page is present.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * @returns false if the page is not present.
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync * @param pVM The VM handle.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * @param GCPtr Address within the page.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync */
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsyncPGMDECL(bool) PGMGstIsPagePresent(PVM pVM, RTGCPTR GCPtr)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync{
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync int rc = PGMGstGetPage(pVM, GCPtr, NULL, NULL);
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync return VBOX_SUCCESS(rc);
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync}
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync/**
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync * Sets (replaces) the page flags for a range of pages in the guest's tables.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param GCPtr The address of the first page.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * @param cb The size of the range in bytes.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fFlags Page flags X86_PTE_*, excluding the page mask of course.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGMDECL(int) PGMGstSetPage(PVM pVM, RTGCPTR GCPtr, size_t cb, uint64_t fFlags)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return PGMGstModifyPage(pVM, GCPtr, cb, fFlags, 0);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Modify page flags for a range of pages in the guest's tables
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The existing flags are ANDed with the fMask and ORed with the fFlags.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param GCPtr Virtual address of the first page in the range.
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * @param cb Size (in bytes) of the range to apply the modification to.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fFlags The OR mask - page flags X86_PTE_*, excluding the page mask of course.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fMask The AND mask - page flags X86_PTE_*, excluding the page mask of course.
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * Be very CAREFUL when ~'ing constants which could be 32-bit!
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGMDECL(int) PGMGstModifyPage(PVM pVM, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_PROFILE_START(&CTXMID(pVM->pgm.s.Stat,GstModifyPage), a);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Validate input.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (fFlags & X86_PTE_PAE_PG_MASK)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("fFlags=%#llx\n", fFlags));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_PROFILE_STOP(&CTXMID(pVM->pgm.s.Stat,GstModifyPage), a);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VERR_INVALID_PARAMETER;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!cb)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync AssertFailed();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_PROFILE_STOP(&CTXMID(pVM->pgm.s.Stat,GstModifyPage), a);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VERR_INVALID_PARAMETER;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
5b6e2c9a765c3c72295acc15791af8a700746956vboxsync LogFlow(("PGMGstModifyPage %VGv %d bytes fFlags=%08llx fMask=%08llx\n", GCPtr, cb, fFlags, fMask));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Adjust input.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cb += (RTGCUINTPTR)GCPtr & PAGE_OFFSET_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cb = RT_ALIGN_Z(cb, PAGE_SIZE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync GCPtr = (RTGCPTR)((RTGCUINTPTR)GCPtr & PAGE_BASE_GC_MASK);
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Call worker.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync int rc = PGM_GST_PFN(ModifyPage, pVM)(pVM, (RTGCUINTPTR)GCPtr, cb, fFlags, fMask);
5ace91141404400247438502a84a418fba00c8cfvboxsync
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync STAM_PROFILE_STOP(&CTXMID(pVM->pgm.s.Stat,GstModifyPage), a);
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
5ace91141404400247438502a84a418fba00c8cfvboxsync * Gets the current CR3 register value for the shadow memory context.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns CR3 value.
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync * @param pVM The VM handle.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync */
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsyncPGMDECL(uint32_t) PGMGetHyperCR3(PVM pVM)
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync{
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync switch (pVM->pgm.s.enmShadowMode)
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync {
08bc90fc2848c80bf8270bedc883745b8398e186vboxsync case PGMMODE_32_BIT:
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync return pVM->pgm.s.HCPhys32BitPD;
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync case PGMMODE_PAE:
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync case PGMMODE_PAE_NX:
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync return pVM->pgm.s.HCPhysPaePDPT;
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync
5ace91141404400247438502a84a418fba00c8cfvboxsync case PGMMODE_AMD64:
5ace91141404400247438502a84a418fba00c8cfvboxsync case PGMMODE_AMD64_NX:
5ace91141404400247438502a84a418fba00c8cfvboxsync return pVM->pgm.s.HCPhysPaePML4;
5ace91141404400247438502a84a418fba00c8cfvboxsync
5ace91141404400247438502a84a418fba00c8cfvboxsync default:
5ace91141404400247438502a84a418fba00c8cfvboxsync AssertMsgFailed(("enmShadowMode=%d\n", pVM->pgm.s.enmShadowMode));
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync return ~0;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
49748bb305bd71f672cd083af208f4bb08c5d6abvboxsync}
49748bb305bd71f672cd083af208f4bb08c5d6abvboxsync
49748bb305bd71f672cd083af208f4bb08c5d6abvboxsync
49748bb305bd71f672cd083af208f4bb08c5d6abvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Gets the CR3 register value for the 32-Bit shadow memory context.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns CR3 value.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGMDECL(uint32_t) PGMGetHyper32BitCR3(PVM pVM)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pVM->pgm.s.HCPhys32BitPD;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Gets the CR3 register value for the PAE shadow memory context.
b9ca93dd1ad44cb8b27679dc5624be2f7b7f7af5vboxsync * @returns CR3 value.
b9ca93dd1ad44cb8b27679dc5624be2f7b7f7af5vboxsync * @param pVM The VM handle.
b9ca93dd1ad44cb8b27679dc5624be2f7b7f7af5vboxsync */
b9ca93dd1ad44cb8b27679dc5624be2f7b7f7af5vboxsyncPGMDECL(uint32_t) PGMGetHyperPaeCR3(PVM pVM)
b9ca93dd1ad44cb8b27679dc5624be2f7b7f7af5vboxsync{
b9ca93dd1ad44cb8b27679dc5624be2f7b7f7af5vboxsync return pVM->pgm.s.HCPhysPaePDPT;
7c3417bbf525c03163d54d151a277a981d5d61b6vboxsync}
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync
8b984478b755f4d3091b977d9beac9fb7434279fvboxsync/**
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync * Gets the CR3 register value for the AMD64 shadow memory context.
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync * @returns CR3 value.
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * @param pVM The VM handle.
51d4024e2984de499ecd878341898f71f55cf9e0vboxsync */
8b984478b755f4d3091b977d9beac9fb7434279fvboxsyncPGMDECL(uint32_t) PGMGetHyperAmd64CR3(PVM pVM)
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync{
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync return pVM->pgm.s.HCPhysPaePML4;
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync/**
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * Gets the current CR3 register value for the HC intermediate memory context.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns CR3 value.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGMDECL(uint32_t) PGMGetInterHCCR3(PVM pVM)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync switch (pVM->pgm.s.enmHostMode)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case SUPPAGINGMODE_32_BIT:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case SUPPAGINGMODE_32_BIT_GLOBAL:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pVM->pgm.s.HCPhysInterPD;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case SUPPAGINGMODE_PAE:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case SUPPAGINGMODE_PAE_GLOBAL:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case SUPPAGINGMODE_PAE_NX:
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync case SUPPAGINGMODE_PAE_GLOBAL_NX:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pVM->pgm.s.HCPhysInterPaePDPT;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync case SUPPAGINGMODE_AMD64:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case SUPPAGINGMODE_AMD64_GLOBAL:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case SUPPAGINGMODE_AMD64_NX:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case SUPPAGINGMODE_AMD64_GLOBAL_NX:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pVM->pgm.s.HCPhysInterPaePDPT;
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync default:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("enmHostMode=%d\n", pVM->pgm.s.enmHostMode));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return ~0;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Gets the current CR3 register value for the GC intermediate memory context.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * @returns CR3 value.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsyncPGMDECL(uint32_t) PGMGetInterGCCR3(PVM pVM)
1a25adaca81841abf5e6cdfed02eaff64941357dvboxsync{
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync switch (pVM->pgm.s.enmShadowMode)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case PGMMODE_32_BIT:
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync return pVM->pgm.s.HCPhysInterPD;
3964eef78ab9593263a3a982e26216d4d166869cvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case PGMMODE_PAE:
f02b41a7e54fc4e6b714f4e60260d94614d6e2e7vboxsync case PGMMODE_PAE_NX:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pVM->pgm.s.HCPhysInterPaePDPT;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
5b6e2c9a765c3c72295acc15791af8a700746956vboxsync case PGMMODE_AMD64:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case PGMMODE_AMD64_NX:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pVM->pgm.s.HCPhysInterPaePML4;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync default:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("enmShadowMode=%d\n", pVM->pgm.s.enmShadowMode));
5b6e2c9a765c3c72295acc15791af8a700746956vboxsync return ~0;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Gets the CR3 register value for the 32-Bit intermediate memory context.
688b55d5387d8b7c508d30141fe1a96eadecb988vboxsync * @returns CR3 value.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
b3547e42ce5221377866e3fa041b3086b7cc1562vboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGMDECL(uint32_t) PGMGetInter32BitCR3(PVM pVM)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pVM->pgm.s.HCPhysInterPD;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Gets the CR3 register value for the PAE intermediate memory context.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns CR3 value.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGMDECL(uint32_t) PGMGetInterPaeCR3(PVM pVM)
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pVM->pgm.s.HCPhysInterPaePDPT;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Gets the CR3 register value for the AMD64 intermediate memory context.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns CR3 value.
5ace91141404400247438502a84a418fba00c8cfvboxsync * @param pVM The VM handle.
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync */
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsyncPGMDECL(uint32_t) PGMGetInterAmd64CR3(PVM pVM)
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync{
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync return pVM->pgm.s.HCPhysInterPaePML4;
5ace91141404400247438502a84a418fba00c8cfvboxsync}
5ace91141404400247438502a84a418fba00c8cfvboxsync
5ace91141404400247438502a84a418fba00c8cfvboxsync
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync/**
5ace91141404400247438502a84a418fba00c8cfvboxsync * Performs and schedules necessary updates following a CR3 load or reload.
5ace91141404400247438502a84a418fba00c8cfvboxsync *
3123bb2477edc752585e4bbd8e4cfedaf87997d1vboxsync * This will normally involve mapping the guest PD or nPDPT
247b55faa8d054157f2481e68caca36f4dc9542cvboxsync *
247b55faa8d054157f2481e68caca36f4dc9542cvboxsync * @returns VBox status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @retval VINF_PGM_SYNC_CR3 if monitoring requires a CR3 sync. This can
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * safely be ignored and overridden since the FF will be set too then.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cr3 The new cr3.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fGlobal Indicates whether this is a global flush or not.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGMDECL(int) PGMFlushTLB(PVM pVM, uint64_t cr3, bool fGlobal)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_PROFILE_START(&pVM->pgm.s.StatFlushTLB, a);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Always flag the necessary updates; necessary for hardware acceleration
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
0975ae0a0fb615c945150c48e4a73187c1f4f84dvboxsync VM_FF_SET(pVM, VM_FF_PGM_SYNC_CR3_NON_GLOBAL);
78a205e3fc6719d59e8c561b3d287d3a4f879852vboxsync if (fGlobal)
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync VM_FF_SET(pVM, VM_FF_PGM_SYNC_CR3);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("PGMFlushTLB: cr3=%VX64 OldCr3=%VX64 fGlobal=%d\n", cr3, pVM->pgm.s.GCPhysCR3, fGlobal));
0975ae0a0fb615c945150c48e4a73187c1f4f84dvboxsync
3241f1be564f7351b07ce8a807673fa77a7847bcvboxsync /*
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync * Remap the CR3 content and adjust the monitoring if CR3 was actually changed.
3241f1be564f7351b07ce8a807673fa77a7847bcvboxsync */
0975ae0a0fb615c945150c48e4a73187c1f4f84dvboxsync int rc = VINF_SUCCESS;
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync RTGCPHYS GCPhysCR3;
0975ae0a0fb615c945150c48e4a73187c1f4f84dvboxsync if ( pVM->pgm.s.enmGuestMode == PGMMODE_PAE
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync || pVM->pgm.s.enmGuestMode == PGMMODE_PAE_NX
78a205e3fc6719d59e8c561b3d287d3a4f879852vboxsync || pVM->pgm.s.enmGuestMode == PGMMODE_AMD64
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync || pVM->pgm.s.enmGuestMode == PGMMODE_AMD64_NX)
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync GCPhysCR3 = (RTGCPHYS)(cr3 & X86_CR3_PAE_PAGE_MASK);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync GCPhysCR3 = (RTGCPHYS)(cr3 & X86_CR3_PAGE_MASK);
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync if (pVM->pgm.s.GCPhysCR3 != GCPhysCR3)
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync {
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync pVM->pgm.s.GCPhysCR3 = GCPhysCR3;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_PFN(MapCR3, pVM)(pVM, GCPhysCR3);
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync if (VBOX_SUCCESS(rc) && !pVM->pgm.s.fMappingsFixed)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
5cf54b3ffeb7ee90685dcaec329ef71a729f5947vboxsync pVM->pgm.s.fSyncFlags &= ~PGM_SYNC_MONITOR_CR3;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_PFN(MonitorCR3, pVM)(pVM, GCPhysCR3);
688b55d5387d8b7c508d30141fe1a96eadecb988vboxsync }
5cf54b3ffeb7ee90685dcaec329ef71a729f5947vboxsync if (fGlobal)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatFlushTLBNewCR3Global);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatFlushTLBNewCR3);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Check if we have a pending update of the CR3 monitoring.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pVM->pgm.s.fSyncFlags & PGM_SYNC_MONITOR_CR3)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync pVM->pgm.s.fSyncFlags &= ~PGM_SYNC_MONITOR_CR3;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(!pVM->pgm.s.fMappingsFixed);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_PFN(MonitorCR3, pVM)(pVM, GCPhysCR3);
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (fGlobal)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatFlushTLBSameCR3Global);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatFlushTLBSameCR3);
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_PROFILE_STOP(&pVM->pgm.s.StatFlushTLB, a);
247b55faa8d054157f2481e68caca36f4dc9542cvboxsync return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Synchronize the paging structures.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This function is called in response to the VM_FF_PGM_SYNC_CR3 and
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * VM_FF_PGM_SYNC_CR3_NONGLOBAL. Those two force action flags are set
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * in several places, most importantly whenever the CR3 is loaded.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
0975ae0a0fb615c945150c48e4a73187c1f4f84dvboxsync * @returns VBox status code.
3241f1be564f7351b07ce8a807673fa77a7847bcvboxsync * @param pVM The virtual machine.
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * @param cr0 Guest context CR0 register
3241f1be564f7351b07ce8a807673fa77a7847bcvboxsync * @param cr3 Guest context CR3 register
0975ae0a0fb615c945150c48e4a73187c1f4f84dvboxsync * @param cr4 Guest context CR4 register
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * @param fGlobal Including global page directories or not
0975ae0a0fb615c945150c48e4a73187c1f4f84dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGMDECL(int) PGMSyncCR3(PVM pVM, uint64_t cr0, uint64_t cr3, uint64_t cr4, bool fGlobal)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * We might be called when we shouldn't.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * The mode switching will ensure that the PD is resynced
1a25adaca81841abf5e6cdfed02eaff64941357dvboxsync * after every mode switch. So, if we find ourselves here
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * when in protected or real mode we can safely disable the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * FF and return immediately.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
3e6d3b0af632bdcd931b5149915c7b8be1a732cdvboxsync if (pVM->pgm.s.enmGuestMode <= PGMMODE_PROTECTED)
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync {
a11c569636fa6838bd423f4631a9660a5a84204bvboxsync Assert((cr0 & (X86_CR0_PG | X86_CR0_PE)) != (X86_CR0_PG | X86_CR0_PE));
5b6e2c9a765c3c72295acc15791af8a700746956vboxsync VM_FF_CLEAR(pVM, VM_FF_PGM_SYNC_CR3);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VM_FF_CLEAR(pVM, VM_FF_PGM_SYNC_CR3_NON_GLOBAL);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VINF_SUCCESS;
5cf54b3ffeb7ee90685dcaec329ef71a729f5947vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* If global pages are not supported, then all flushes are global */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!(cr4 & X86_CR4_PGE))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fGlobal = true;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("PGMSyncCR3: cr0=%VX64 cr3=%VX64 cr4=%VX64 fGlobal=%d[%d,%d]\n", cr0, cr3, cr4, fGlobal,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VM_FF_ISSET(pVM, VM_FF_PGM_SYNC_CR3), VM_FF_ISSET(pVM, VM_FF_PGM_SYNC_CR3_NON_GLOBAL)));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Let the 'Bth' function do the work and we'll just keep track of the flags.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_PROFILE_START(&pVM->pgm.s.CTXMID(Stat,SyncCR3), a);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = PGM_BTH_PFN(SyncCR3, pVM)(pVM, cr0, cr3, cr4, fGlobal);
688b55d5387d8b7c508d30141fe1a96eadecb988vboxsync STAM_PROFILE_STOP(&pVM->pgm.s.CTXMID(Stat,SyncCR3), a);
5cf54b3ffeb7ee90685dcaec329ef71a729f5947vboxsync AssertMsg(rc == VINF_SUCCESS || rc == VINF_PGM_SYNC_CR3 || VBOX_FAILURE(rc), ("rc=%VRc\n", rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (rc == VINF_SUCCESS)
b3547e42ce5221377866e3fa041b3086b7cc1562vboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!(pVM->pgm.s.fSyncFlags & PGM_SYNC_ALWAYS))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VM_FF_CLEAR(pVM, VM_FF_PGM_SYNC_CR3);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VM_FF_CLEAR(pVM, VM_FF_PGM_SYNC_CR3_NON_GLOBAL);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Check if we have a pending update of the CR3 monitoring.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pVM->pgm.s.fSyncFlags & PGM_SYNC_MONITOR_CR3)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVM->pgm.s.fSyncFlags &= ~PGM_SYNC_MONITOR_CR3;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(!pVM->pgm.s.fMappingsFixed);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(pVM->pgm.s.GCPhysCR3 == pVM->pgm.s.GCPhysGstCR3Monitored);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_PFN(MonitorCR3, pVM)(pVM, pVM->pgm.s.GCPhysCR3);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
5b6e2c9a765c3c72295acc15791af8a700746956vboxsync
50df3da42ff6589b0ecc4f50f2288811bc370186vboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Now flush the CR3 (guest context).
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync */
5ace91141404400247438502a84a418fba00c8cfvboxsync if (rc == VINF_SUCCESS)
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_INVL_GUEST_TLBS();
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync return rc;
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
14dfd448b0f1b9a46c4a4658a77752cb7561cd47vboxsync
6778b34cb96bef0fef23ebc461eb6a429d2907c5vboxsync/**
6778b34cb96bef0fef23ebc461eb6a429d2907c5vboxsync * Called whenever CR0 or CR4 in a way which may change
6778b34cb96bef0fef23ebc461eb6a429d2907c5vboxsync * the paging mode.
6778b34cb96bef0fef23ebc461eb6a429d2907c5vboxsync *
6778b34cb96bef0fef23ebc461eb6a429d2907c5vboxsync * @returns VBox status code fit for scheduling in GC and R0.
6778b34cb96bef0fef23ebc461eb6a429d2907c5vboxsync * @retval VINF_SUCCESS if the was no change, or it was successfully dealt with.
6778b34cb96bef0fef23ebc461eb6a429d2907c5vboxsync * @retval VINF_PGM_CHANGE_MODE if we're in GC or R0 and the mode changes.
6778b34cb96bef0fef23ebc461eb6a429d2907c5vboxsync * @param pVM VM handle.
b5b12033c1f7eaf82b038f06e2b9e464b9ddd8d2vboxsync * @param cr0 The new cr0.
d4b98dbce4cf7b3694b62d62a47553d399718dccvboxsync * @param cr4 The new cr4.
d4b98dbce4cf7b3694b62d62a47553d399718dccvboxsync * @param efer The new extended feature enable register.
d4b98dbce4cf7b3694b62d62a47553d399718dccvboxsync */
d4b98dbce4cf7b3694b62d62a47553d399718dccvboxsyncPGMDECL(int) PGMChangeMode(PVM pVM, uint64_t cr0, uint64_t cr4, uint64_t efer)
d4b98dbce4cf7b3694b62d62a47553d399718dccvboxsync{
d4b98dbce4cf7b3694b62d62a47553d399718dccvboxsync PGMMODE enmGuestMode;
d4b98dbce4cf7b3694b62d62a47553d399718dccvboxsync
97b2abd2828499b2f4c2d5721952c9570ced1ebcvboxsync /*
97b2abd2828499b2f4c2d5721952c9570ced1ebcvboxsync * Calc the new guest mode.
fd69ca9bd8b533bfa9ade45c1c2ff3116854e84avboxsync */
fd69ca9bd8b533bfa9ade45c1c2ff3116854e84avboxsync if (!(cr0 & X86_CR0_PE))
fd69ca9bd8b533bfa9ade45c1c2ff3116854e84avboxsync enmGuestMode = PGMMODE_REAL;
fd69ca9bd8b533bfa9ade45c1c2ff3116854e84avboxsync else if (!(cr0 & X86_CR0_PG))
fd69ca9bd8b533bfa9ade45c1c2ff3116854e84avboxsync enmGuestMode = PGMMODE_PROTECTED;
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync else if (!(cr4 & X86_CR4_PAE))
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync enmGuestMode = PGMMODE_32_BIT;
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync else if (!(efer & MSR_K6_EFER_LME))
fd69ca9bd8b533bfa9ade45c1c2ff3116854e84avboxsync {
5ace91141404400247438502a84a418fba00c8cfvboxsync if (!(efer & MSR_K6_EFER_NXE))
5ace91141404400247438502a84a418fba00c8cfvboxsync enmGuestMode = PGMMODE_PAE;
5a12b9772d9cf396a0ba7f54db399817ba7a65bavboxsync else
5ace91141404400247438502a84a418fba00c8cfvboxsync enmGuestMode = PGMMODE_PAE_NX;
5a12b9772d9cf396a0ba7f54db399817ba7a65bavboxsync }
5ace91141404400247438502a84a418fba00c8cfvboxsync else
5ace91141404400247438502a84a418fba00c8cfvboxsync {
5ace91141404400247438502a84a418fba00c8cfvboxsync if (!(efer & MSR_K6_EFER_NXE))
5ace91141404400247438502a84a418fba00c8cfvboxsync enmGuestMode = PGMMODE_AMD64;
5ace91141404400247438502a84a418fba00c8cfvboxsync else
5ace91141404400247438502a84a418fba00c8cfvboxsync enmGuestMode = PGMMODE_AMD64_NX;
5ace91141404400247438502a84a418fba00c8cfvboxsync }
5ace91141404400247438502a84a418fba00c8cfvboxsync
5ace91141404400247438502a84a418fba00c8cfvboxsync /*
5ace91141404400247438502a84a418fba00c8cfvboxsync * Did it change?
5ace91141404400247438502a84a418fba00c8cfvboxsync */
5a12b9772d9cf396a0ba7f54db399817ba7a65bavboxsync if (pVM->pgm.s.enmGuestMode == enmGuestMode)
5a12b9772d9cf396a0ba7f54db399817ba7a65bavboxsync return VINF_SUCCESS;
5ace91141404400247438502a84a418fba00c8cfvboxsync#ifdef IN_RING3
5ace91141404400247438502a84a418fba00c8cfvboxsync return pgmR3ChangeMode(pVM, enmGuestMode);
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync#else
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync Log(("PGMChangeMode: returns VINF_PGM_CHANGE_MODE.\n"));
5ace91141404400247438502a84a418fba00c8cfvboxsync return VINF_PGM_CHANGE_MODE;
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync#endif
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync}
5ace91141404400247438502a84a418fba00c8cfvboxsync
5ace91141404400247438502a84a418fba00c8cfvboxsync
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync/**
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * Gets the current guest paging mode.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * If you just need the CPU mode (real/protected/long), use CPUMGetGuestMode().
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns The current paging mode.
0f5d1b2abd9e82c7ee46f1327287c44856604bcbvboxsync * @param pVM The VM handle.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync */
5ace91141404400247438502a84a418fba00c8cfvboxsyncPGMDECL(PGMMODE) PGMGetGuestMode(PVM pVM)
f8b934f4817639cddebe4d3c2ae25d39a91fe448vboxsync{
20a793635760c71752932fde640ba328cab84348vboxsync return pVM->pgm.s.enmGuestMode;
5ace91141404400247438502a84a418fba00c8cfvboxsync}
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Gets the current shadow paging mode.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * @returns The current paging mode.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync */
5ace91141404400247438502a84a418fba00c8cfvboxsyncPGMDECL(PGMMODE) PGMGetShadowMode(PVM pVM)
5ace91141404400247438502a84a418fba00c8cfvboxsync{
5ace91141404400247438502a84a418fba00c8cfvboxsync return pVM->pgm.s.enmShadowMode;
5ace91141404400247438502a84a418fba00c8cfvboxsync}
5ace91141404400247438502a84a418fba00c8cfvboxsync
5ace91141404400247438502a84a418fba00c8cfvboxsync/**
5ace91141404400247438502a84a418fba00c8cfvboxsync * Gets the current host paging mode.
5ace91141404400247438502a84a418fba00c8cfvboxsync *
5ace91141404400247438502a84a418fba00c8cfvboxsync * @returns The current paging mode.
5ace91141404400247438502a84a418fba00c8cfvboxsync * @param pVM The VM handle.
5ace91141404400247438502a84a418fba00c8cfvboxsync */
fcc2858fa3a0ee65ec8426cd4caeeaa7d87bbfa4vboxsyncPGMDECL(PGMMODE) PGMGetHostMode(PVM pVM)
fcc2858fa3a0ee65ec8426cd4caeeaa7d87bbfa4vboxsync{
fcc2858fa3a0ee65ec8426cd4caeeaa7d87bbfa4vboxsync switch (pVM->pgm.s.enmHostMode)
5ace91141404400247438502a84a418fba00c8cfvboxsync {
5ace91141404400247438502a84a418fba00c8cfvboxsync case SUPPAGINGMODE_32_BIT:
5ace91141404400247438502a84a418fba00c8cfvboxsync case SUPPAGINGMODE_32_BIT_GLOBAL:
5ace91141404400247438502a84a418fba00c8cfvboxsync return PGMMODE_32_BIT;
5ace91141404400247438502a84a418fba00c8cfvboxsync
5ace91141404400247438502a84a418fba00c8cfvboxsync case SUPPAGINGMODE_PAE:
5ace91141404400247438502a84a418fba00c8cfvboxsync case SUPPAGINGMODE_PAE_GLOBAL:
5ace91141404400247438502a84a418fba00c8cfvboxsync return PGMMODE_PAE;
5ace91141404400247438502a84a418fba00c8cfvboxsync
5ace91141404400247438502a84a418fba00c8cfvboxsync case SUPPAGINGMODE_PAE_NX:
5ace91141404400247438502a84a418fba00c8cfvboxsync case SUPPAGINGMODE_PAE_GLOBAL_NX:
5ace91141404400247438502a84a418fba00c8cfvboxsync return PGMMODE_PAE_NX;
5ace91141404400247438502a84a418fba00c8cfvboxsync
5b6e2c9a765c3c72295acc15791af8a700746956vboxsync case SUPPAGINGMODE_AMD64:
b5b12033c1f7eaf82b038f06e2b9e464b9ddd8d2vboxsync case SUPPAGINGMODE_AMD64_GLOBAL:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return PGMMODE_AMD64;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case SUPPAGINGMODE_AMD64_NX:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case SUPPAGINGMODE_AMD64_GLOBAL_NX:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return PGMMODE_AMD64_NX;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync default: AssertMsgFailed(("enmHostMode=%d\n", pVM->pgm.s.enmHostMode)); break;
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync return PGMMODE_INVALID;
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync/**
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync * Get mode name.
28c928d1100d3b6a6d3506224cae25ad04732f73vboxsync *
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync * @returns read-only name string.
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync * @param enmMode The mode which name is desired.
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync */
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsyncPGMDECL(const char *) PGMGetModeName(PGMMODE enmMode)
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync{
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync switch (enmMode)
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync {
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync case PGMMODE_REAL: return "real";
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync case PGMMODE_PROTECTED: return "protected";
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync case PGMMODE_32_BIT: return "32-bit";
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync case PGMMODE_PAE: return "PAE";
28c928d1100d3b6a6d3506224cae25ad04732f73vboxsync case PGMMODE_PAE_NX: return "PAE+NX";
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync case PGMMODE_AMD64: return "AMD64";
5ace91141404400247438502a84a418fba00c8cfvboxsync case PGMMODE_AMD64_NX: return "AMD64+NX";
5ace91141404400247438502a84a418fba00c8cfvboxsync default: return "unknown mode value";
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync }
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync}
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync/**
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync * Acquire the PGM lock.
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync *
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync * @returns VBox status code
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync * @param pVM The VM to operate on.
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync */
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsyncint pgmLock(PVM pVM)
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync{
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync int rc = PDMCritSectEnter(&pVM->pgm.s.CritSect, VERR_SEM_BUSY);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#ifdef IN_GC
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (rc == VERR_SEM_BUSY)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VMMGCCallHost(pVM, VMMCALLHOST_PGM_LOCK, 0);
5b6e2c9a765c3c72295acc15791af8a700746956vboxsync#elif defined(IN_RING0)
08bc90fc2848c80bf8270bedc883745b8398e186vboxsync if (rc == VERR_SEM_BUSY)
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync rc = VMMR0CallHost(pVM, VMMCALLHOST_PGM_LOCK, 0);
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync#endif
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertRC(rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return rc;
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync}
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync/**
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * Release the PGM lock.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync *
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * @returns VBox status code
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * @param pVM The VM to operate on.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync */
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsyncvoid pgmUnlock(PVM pVM)
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync{
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync PDMCritSectLeave(&pVM->pgm.s.CritSect);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync}
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync#ifdef VBOX_STRICT
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync/**
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync * Asserts that there are no mapping conflicts.
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync *
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync * @returns Number of conflicts.
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync * @param pVM The VM Handle.
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync */
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsyncPGMDECL(unsigned) PGMAssertNoMappingConflicts(PVM pVM)
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync{
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync unsigned cErrors = 0;
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync /*
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync * Check for mapping conflicts.
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync */
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync for (PPGMMAPPING pMapping = CTXALLSUFF(pVM->pgm.s.pMappings);
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync pMapping;
0f5b937bdc21496925500f3ce418794a5a9a1351vboxsync pMapping = CTXALLSUFF(pMapping->pNext))
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync {
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync /** @todo This is slow and should be optimized, but since it's just assertions I don't care now. */
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync for (RTGCUINTPTR GCPtr = (RTGCUINTPTR)pMapping->GCPtr;
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync GCPtr <= (RTGCUINTPTR)pMapping->GCPtrLast;
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync GCPtr += PAGE_SIZE)
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync {
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync int rc = PGMGstGetPage(pVM, (RTGCPTR)GCPtr, NULL, NULL);
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync if (rc != VERR_PAGE_TABLE_NOT_PRESENT)
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync {
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync AssertMsgFailed(("Conflict at %VGv with %s\n", GCPtr, HCSTRING(pMapping->pszDesc)));
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync cErrors++;
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync break;
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync }
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync }
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync }
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync return cErrors;
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync}
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync/**
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * Asserts that everything related to the guest CR3 is correctly shadowed.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync *
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * This will call PGMAssertNoMappingConflicts() and PGMAssertHandlerAndFlagsInSync(),
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * and assert the correctness of the guest CR3 mapping before asserting that the
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * shadow page tables is in sync with the guest page tables.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync *
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * @returns Number of conflicts.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * @param pVM The VM Handle.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * @param cr3 The current guest CR3 register value.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * @param cr4 The current guest CR4 register value.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync */
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsyncPGMDECL(unsigned) PGMAssertCR3(PVM pVM, uint64_t cr3, uint64_t cr4)
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync{
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync STAM_PROFILE_START(&pVM->pgm.s.CTXMID(Stat,SyncCR3), a);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync unsigned cErrors = PGM_BTH_PFN(AssertCR3, pVM)(pVM, cr3, cr4, 0, ~(RTGCUINTPTR)0);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync STAM_PROFILE_STOP(&pVM->pgm.s.CTXMID(Stat,SyncCR3), a);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync return cErrors;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
0f5d1b2abd9e82c7ee46f1327287c44856604bcbvboxsync#endif /* VBOX_STRICT */
bc8991845b5bd7e98758795748d3d76408756793vboxsync