PGMAll.cpp revision 134a71c1528b56afe4db843ab63ec5a5b849535b
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * PGM - Page Manager and Monitor - All context code.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * 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* Header Files *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync*******************************************************************************/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*******************************************************************************
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync* Structures and Typedefs *
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync*******************************************************************************/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Stated structure for PGM_GST_NAME(HandlerVirtualUpdate) that's
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * passed to PGM_GST_NAME(VirtHandlerUpdateOne) during enumeration.
afed5ab737f4aacfae3fe73776f40e989190a7cavboxsynctypedef struct PGMHVUSTATE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** The VM handle. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** The todo flags. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** The CR4 register value. */
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync/*******************************************************************************
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync* Internal Functions *
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync*******************************************************************************/
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync * Shadow - 32-bit mode
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Guest - real mode */
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/* Guest - protected mode */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_32BIT_PROT(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_32BIT_PT_FOR_PHYS
22e281e75ed636601178296c6daebda8f1d17c59vboxsync/* Guest - 32-bit mode */
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 * Shadow - PAE mode
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_REAL(name)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync/* Guest - real mode */
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/* Guest - protected mode */
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/* Guest - 32-bit mode */
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/* Guest - PAE mode */
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 * Shadow - AMD64 mode
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Guest - protected mode */
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/* Guest - AMD64 mode */
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
576d4214137bce409cdcf01e8df4a0bca5e0b2d1vboxsync * #PF Handler.
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.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGMDECL(int) PGMTrap0eHandler(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("PGMTrap0eHandler: uErr=%#x pvFault=%VGv eip=%VGv\n", uErr, pvFault, pRegFrame->eip));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_STATS({ pVM->pgm.s.CTXSUFF(pStatTrap0eAttribution) = NULL; } );
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Error code stats.
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatGCTrap0eUSNotPresentWrite);
909f4391cc20b4a3a9a2d3f8718084b669663ab2vboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatGCTrap0eUSNotPresentRead);
3ecd8008b81f02a04220705ae0033142af363280vboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatGCTrap0eUSReserved);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { /* Supervisor */
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatGCTrap0eSVNotPresentWrite);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatGCTrap0eSVNotPresentRead);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatGCTrap0eSVReserved);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Call the worker.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = PGM_BTH_PFN(Trap0eHandler, pVM)(pVM, uErr, pRegFrame, pvFault);
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);
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync * Prefetch a page
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Typically used to sync commonly used pages before entering raw mode
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * after a CR3 reload.
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.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGMDECL(int) PGMPrefetchPage(PVM pVM, RTGCPTR GCPtrPage)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = PGM_BTH_PFN(PrefetchPage, pVM)(pVM, (RTGCUINTPTR)GCPtrPage);
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync AssertMsg(rc == VINF_SUCCESS || rc == VINF_PGM_SYNC_CR3 || VBOX_FAILURE(rc), ("rc=%Vrc\n", rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Gets the mapping corresponding to the specified address (if any).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns Pointer to the mapping.
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync * @returns NULL if not
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The virtual machine.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param GCPtr The guest context pointer.
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync PPGMMAPPING pMapping = CTXALLSUFF(pVM->pgm.s.pMappings);
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync if ((uintptr_t)GCPtr - (uintptr_t)pMapping->GCPtr < pMapping->cb)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatGCSyncPTConflict);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * Verifies a range of pages for read or write access
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * Only checks the guest's page tables
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_*))
22e281e75ed636601178296c6daebda8f1d17c59vboxsyncPGMDECL(int) PGMIsValidAccess(PVM pVM, RTGCUINTPTR Addr, uint32_t cbSize, uint32_t fAccess)
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * Validate input.
1843553dbdf4e46417158b4c6348c503adf10740vboxsync AssertMsgFailed(("PGMIsValidAccess: invalid access type %08x\n", fAccess));
1843553dbdf4e46417158b4c6348c503adf10740vboxsync int rc = PGMGstGetPage(pVM, (RTGCPTR)Addr, &fPage, NULL);
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync Log(("PGMIsValidAccess: access violation for %VGv rc=%d\n", Addr, rc));
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * Check if the access would cause a page fault
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * Note that hypervisor page directories are not present in the guest's tables, so this check
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * is sufficient.
1843553dbdf4e46417158b4c6348c503adf10740vboxsync Log(("PGMIsValidAccess: access violation for %VGv attr %#llx vs %d:%d\n", Addr, fPage, fWrite, fUser));
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync && PAGE_ADDRESS(Addr) != PAGE_ADDRESS(Addr + cbSize))
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync return PGMIsValidAccess(pVM, Addr + PAGE_SIZE, (cbSize > PAGE_SIZE) ? cbSize - PAGE_SIZE : 1, fAccess);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Verifies a range of pages for read or write access
e52f819639386db020b2a635b47a415248c7fbf9vboxsync * Supports handling of pages marked for dirty bit tracking and CSAM
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_*))
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsyncPGMDECL(int) PGMVerifyAccess(PVM pVM, RTGCUINTPTR Addr, uint32_t cbSize, uint32_t fAccess)
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * Validate input.
0e77737b0ba913683e614db11463b31ca67aacbevboxsync AssertMsgFailed(("PGMVerifyAccess: invalid access type %08x\n", fAccess));
0e77737b0ba913683e614db11463b31ca67aacbevboxsync int rc = PGMGstGetPage(pVM, (RTGCPTR)Addr, &fPageGst, NULL);
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync Log(("PGMVerifyAccess: access violation for %VGv rc=%d\n", Addr, rc));
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * Check if the access would cause a page fault
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * Note that hypervisor page directories are not present in the guest's tables, so this check
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * is sufficient.
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync Log(("PGMVerifyAccess: access violation for %VGv attr %#llx vs %d:%d\n", Addr, fPageGst, fWrite, fUser));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Next step is to verify if we protected this page for dirty bit tracking or for CSAM scanning
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGMShwGetPage(pVM, (RTGCPTR)Addr, NULL, NULL);
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * Page is not present in our page tables.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Try to sync it!
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);
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync AssertMsg(rc == VINF_SUCCESS, ("PGMShwGetPage %VGv failed with %Vrc\n", Addr, rc));
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync#if 0 /* def VBOX_STRICT; triggers too often now */
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * This check is a bit paranoid, but useful.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync /** @note this will assert when writing to monitored pages (a bit annoying actually) */
806d0b554daa555364af5f87bc96eccbe760db7avboxsync rc = PGMShwGetPage(pVM, (RTGCPTR)Addr, &fPageShw, NULL);
806d0b554daa555364af5f87bc96eccbe760db7avboxsync if ( (rc == VERR_PAGE_NOT_PRESENT || VBOX_FAILURE(rc))
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)));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && ( PAGE_ADDRESS(Addr) != PAGE_ADDRESS(Addr + cbSize - 1)
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync /* Don't recursively call PGMVerifyAccess as we might run out of stack. */
806d0b554daa555364af5f87bc96eccbe760db7avboxsync if (PAGE_ADDRESS(Addr) == PAGE_ADDRESS(Addr + cbSize - 1))
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync * Emulation of the invlpg instruction (HC only actually).
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!
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGMDECL(int) PGMInvalidatePage(PVM pVM, RTGCPTR GCPtrPage)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync LogFlow(("PGMInvalidatePage: GCPtrPage=%VGv\n", GCPtrPage));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo merge PGMGCInvalidatePage with this one */
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.
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);
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * Check if we have a pending update of the CR3 monitoring.
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync Assert(pVM->pgm.s.GCPhysCR3 == pVM->pgm.s.GCPhysGstCR3Monitored);
1157941288c9533575a655c660af55d13da31eefvboxsync rc = PGM_GST_PFN(MonitorCR3, pVM)(pVM, pVM->pgm.s.GCPhysCR3);
8e8844a522f5d335f177a0313b03067d79cce201vboxsync * Inform CSAM about the flush
7bae75e0b207aa4d4cad2a951271ad1a0e8ab9fdvboxsync /** @note this is to check if monitored pages have been changed; when we implement callbacks for virtual handlers, this is no longer required. */
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync * Executes an instruction using the interpreter.
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.
22e281e75ed636601178296c6daebda8f1d17c59vboxsyncPGMDECL(int) PGMInterpretInstruction(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault)
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync int rc = EMInterpretInstruction(pVM, pRegFrame, pvFault, &cb);
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync Log(("PGMInterpretInstruction: returns %Rrc (pvFault=%VGv)\n", rc, pvFault));
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * Gets effective page information (from the VMM page directory).
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.
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsyncPGMDECL(int) PGMShwGetPage(PVM pVM, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys)
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync return PGM_SHW_PFN(GetPage,pVM)(pVM, (RTGCUINTPTR)GCPtr, pfFlags, pHCPhys);
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * Sets (replaces) the page flags for a range of pages in the shadow context.
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.
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsyncPGMDECL(int) PGMShwSetPage(PVM pVM, RTGCPTR GCPtr, size_t cb, uint64_t fFlags)
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync return PGMShwModifyPage(pVM, GCPtr, cb, fFlags, 0);
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * Modify page flags for a range of pages in the shadow context.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * The existing flags are ANDed with the fMask and ORed with the fFlags.
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.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsyncPGMDECL(int) PGMShwModifyPage(PVM pVM, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask)
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * Validate input.
e149c362e69e5f0bbd82da11fd8163b2d29c3a72vboxsync * Align the input.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync GCPtr = (RTGCPTR)((RTGCUINTPTR)GCPtr & PAGE_BASE_GC_MASK); /** @todo this ain't necessary, right... */
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * Call worker.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync return PGM_SHW_PFN(ModifyPage, pVM)(pVM, (RTGCUINTPTR)GCPtr, cb, fFlags, fMask);
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 * @returns VBox status.
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * @param pVM VM handle.
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * @param GCPtr The address.
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * @param ppPD Receives address of page directory
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsyncPGMDECL(int) PGMShwGetLongModePDPtr(PVM pVM, RTGCUINTPTR64 GCPtr, PX86PDPAE *ppPD)
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync const unsigned iPml4e = (GCPtr >> X86_PML4_SHIFT) & X86_PML4_MASK;
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync PX86PML4E pPml4eGst = &pPGM->pGstPaePML4HC->a[iPml4e];
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync rc = pgmPoolAlloc(pVM, pPml4eGst->u & X86_PML4E_PG_MASK, PGMPOOLKIND_64BIT_PDPT_FOR_64BIT_PDPT, PGMPOOL_IDX_PML4, iPml4e, &pShwPage);
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync /* The PDPT was cached or created; hook it up now. */
8e8844a522f5d335f177a0313b03067d79cce201vboxsync pShwPage = pgmPoolGetPage(pPool, pPml4e->u & X86_PML4E_PG_MASK);
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync const unsigned iPdPt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64;
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync PX86PDPT pPdpt = (PX86PDPT)PGMPOOL_PAGE_2_PTR(pVM, pShwPage);
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync PX86PML4E pPml4eGst = &pPGM->pGstPaePML4HC->a[iPml4e];
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync rc = PGM_GCPHYS_2_PTR(pVM, pPml4eGst->u & X86_PML4E_PG_MASK, &pPdptGst);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync rc = pgmPoolAlloc(pVM, pPdptGst->a[iPdPt].u & X86_PDPE_PG_MASK, PGMPOOLKIND_64BIT_PD_FOR_64BIT_PD, PGMPOOL_IDX_PDPT, iPdPt, &pShwPage);
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync /* The PDPT was cached or created; hook it up now. */
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync pShwPage = pgmPoolGetPage(pPool, pPdpe->u & X86_PDPE_PG_MASK);
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync *ppPD = (PX86PDPAE)PGMPOOL_PAGE_2_PTR(pVM, pShwPage);
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync * Gets effective Guest OS page information.
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
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
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsyncPGMDECL(int) PGMGstGetPage(PVM pVM, RTGCPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys)
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync return PGM_GST_PFN(GetPage,pVM)(pVM, (RTGCUINTPTR)GCPtr, pfFlags, pGCPhys);
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * Checks if the page is present.
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.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsyncPGMDECL(bool) PGMGstIsPagePresent(PVM pVM, RTGCPTR GCPtr)
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync * Sets (replaces) the page flags for a range of pages in the guest's tables.
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.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGMDECL(int) PGMGstSetPage(PVM pVM, RTGCPTR GCPtr, size_t cb, uint64_t fFlags)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return PGMGstModifyPage(pVM, GCPtr, cb, fFlags, 0);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Modify page flags for a range of pages in the guest's tables
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The existing flags are ANDed with the fMask and ORed with the fFlags.
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!
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGMDECL(int) PGMGstModifyPage(PVM pVM, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_PROFILE_START(&CTXMID(pVM->pgm.s.Stat,GstModifyPage), a);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Validate input.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_PROFILE_STOP(&CTXMID(pVM->pgm.s.Stat,GstModifyPage), a);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_PROFILE_STOP(&CTXMID(pVM->pgm.s.Stat,GstModifyPage), a);
5b6e2c9a765c3c72295acc15791af8a700746956vboxsync LogFlow(("PGMGstModifyPage %VGv %d bytes fFlags=%08llx fMask=%08llx\n", GCPtr, cb, fFlags, fMask));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Adjust input.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync GCPtr = (RTGCPTR)((RTGCUINTPTR)GCPtr & PAGE_BASE_GC_MASK);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Call worker.
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync int rc = PGM_GST_PFN(ModifyPage, pVM)(pVM, (RTGCUINTPTR)GCPtr, cb, fFlags, fMask);
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync STAM_PROFILE_STOP(&CTXMID(pVM->pgm.s.Stat,GstModifyPage), a);
5ace91141404400247438502a84a418fba00c8cfvboxsync * Gets the current CR3 register value for the shadow memory context.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns CR3 value.
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync * @param pVM The VM handle.
5ace91141404400247438502a84a418fba00c8cfvboxsync AssertMsgFailed(("enmShadowMode=%d\n", pVM->pgm.s.enmShadowMode));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Gets the CR3 register value for the 32-Bit shadow memory context.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns CR3 value.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Gets the CR3 register value for the PAE shadow memory context.
b9ca93dd1ad44cb8b27679dc5624be2f7b7f7af5vboxsync * @returns CR3 value.
b9ca93dd1ad44cb8b27679dc5624be2f7b7f7af5vboxsync * @param pVM The VM handle.
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync * Gets the CR3 register value for the AMD64 shadow memory context.
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync * @returns CR3 value.
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * @param pVM The VM handle.
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * Gets the current CR3 register value for the HC intermediate memory context.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns CR3 value.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("enmHostMode=%d\n", pVM->pgm.s.enmHostMode));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Gets the current CR3 register value for the GC intermediate memory context.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * @returns CR3 value.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("enmShadowMode=%d\n", pVM->pgm.s.enmShadowMode));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Gets the CR3 register value for the 32-Bit intermediate memory context.
688b55d5387d8b7c508d30141fe1a96eadecb988vboxsync * @returns CR3 value.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Gets the CR3 register value for the PAE intermediate memory context.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns CR3 value.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Gets the CR3 register value for the AMD64 intermediate memory context.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns CR3 value.
5ace91141404400247438502a84a418fba00c8cfvboxsync * @param pVM The VM handle.
5ace91141404400247438502a84a418fba00c8cfvboxsync * Performs and schedules necessary updates following a CR3 load or reload.
3123bb2477edc752585e4bbd8e4cfedaf87997d1vboxsync * This will normally involve mapping the guest PD or nPDPT
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.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGMDECL(int) PGMFlushTLB(PVM pVM, uint64_t cr3, bool fGlobal)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Always flag the necessary updates; necessary for hardware acceleration
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("PGMFlushTLB: cr3=%VX64 OldCr3=%VX64 fGlobal=%d\n", cr3, pVM->pgm.s.GCPhysCR3, fGlobal));
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync * Remap the CR3 content and adjust the monitoring if CR3 was actually changed.
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync GCPhysCR3 = (RTGCPHYS)(cr3 & X86_CR3_PAE_PAGE_MASK);
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync if (VBOX_SUCCESS(rc) && !pVM->pgm.s.fMappingsFixed)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatFlushTLBNewCR3Global);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Check if we have a pending update of the CR3 monitoring.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_COUNTER_INC(&pVM->pgm.s.StatFlushTLBSameCR3Global);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Synchronize the paging structures.
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.
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
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPGMDECL(int) PGMSyncCR3(PVM pVM, uint64_t cr0, uint64_t cr3, uint64_t cr4, bool fGlobal)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * We might be called when we shouldn't.
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.
a11c569636fa6838bd423f4631a9660a5a84204bvboxsync Assert((cr0 & (X86_CR0_PG | X86_CR0_PE)) != (X86_CR0_PG | X86_CR0_PE));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* If global pages are not supported, then all flushes are global */
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 * Let the 'Bth' function do the work and we'll just keep track of the flags.
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 * Check if we have a pending update of the CR3 monitoring.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(pVM->pgm.s.GCPhysCR3 == pVM->pgm.s.GCPhysGstCR3Monitored);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_PFN(MonitorCR3, pVM)(pVM, pVM->pgm.s.GCPhysCR3);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Now flush the CR3 (guest context).
6778b34cb96bef0fef23ebc461eb6a429d2907c5vboxsync * Called whenever CR0 or CR4 in a way which may change
6778b34cb96bef0fef23ebc461eb6a429d2907c5vboxsync * the paging mode.
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.
d4b98dbce4cf7b3694b62d62a47553d399718dccvboxsyncPGMDECL(int) PGMChangeMode(PVM pVM, uint64_t cr0, uint64_t cr4, uint64_t efer)
97b2abd2828499b2f4c2d5721952c9570ced1ebcvboxsync * Calc the new guest mode.
5ace91141404400247438502a84a418fba00c8cfvboxsync * Did it change?
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync Log(("PGMChangeMode: returns VINF_PGM_CHANGE_MODE.\n"));
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * Gets the current guest paging mode.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * If you just need the CPU mode (real/protected/long), use CPUMGetGuestMode().
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns The current paging mode.
0f5d1b2abd9e82c7ee46f1327287c44856604bcbvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Gets the current shadow paging mode.
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * @returns The current paging mode.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
5ace91141404400247438502a84a418fba00c8cfvboxsync * Gets the current host paging mode.
5ace91141404400247438502a84a418fba00c8cfvboxsync * @returns The current paging mode.
5ace91141404400247438502a84a418fba00c8cfvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync default: AssertMsgFailed(("enmHostMode=%d\n", pVM->pgm.s.enmHostMode)); break;
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync * Get mode name.
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync * @returns read-only name string.
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync * @param enmMode The mode which name is desired.
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsyncPGMDECL(const char *) PGMGetModeName(PGMMODE enmMode)
5ace91141404400247438502a84a418fba00c8cfvboxsync default: return "unknown mode value";
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync * Acquire the PGM lock.
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync * @returns VBox status code
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync * @param pVM The VM to operate on.
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync int rc = PDMCritSectEnter(&pVM->pgm.s.CritSect, VERR_SEM_BUSY);
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * Release the PGM lock.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * @returns VBox status code
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * @param pVM The VM to operate on.
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync * Asserts that there are no mapping conflicts.
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync * @returns Number of conflicts.
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync * @param pVM The VM Handle.
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsyncPGMDECL(unsigned) PGMAssertNoMappingConflicts(PVM pVM)
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync unsigned cErrors = 0;
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync * Check for mapping conflicts.
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync for (PPGMMAPPING pMapping = CTXALLSUFF(pVM->pgm.s.pMappings);
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 int rc = PGMGstGetPage(pVM, (RTGCPTR)GCPtr, NULL, NULL);
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync AssertMsgFailed(("Conflict at %VGv with %s\n", GCPtr, HCSTRING(pMapping->pszDesc)));
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * Asserts that everything related to the guest CR3 is correctly shadowed.
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 * @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.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsyncPGMDECL(unsigned) PGMAssertCR3(PVM pVM, uint64_t cr3, uint64_t cr4)
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);
0f5d1b2abd9e82c7ee46f1327287c44856604bcbvboxsync#endif /* VBOX_STRICT */