PGMHandler.cpp revision 6752e22c5aad40a438fc07dcbd9247cece5d9887
de4157257515400c2c25373591135f110227b68cvboxsync/* $Id$ */
de4157257515400c2c25373591135f110227b68cvboxsync/** @file
de4157257515400c2c25373591135f110227b68cvboxsync * PGM - Page Manager / Monitor, Access Handlers.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/*
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2006-2007 innotek GmbH
de4157257515400c2c25373591135f110227b68cvboxsync *
b263fac6f6e7fa933c7bfb2a45d598fe8e458c09vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b263fac6f6e7fa933c7bfb2a45d598fe8e458c09vboxsync * available from http://www.virtualbox.org. This file is free software;
b263fac6f6e7fa933c7bfb2a45d598fe8e458c09vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b263fac6f6e7fa933c7bfb2a45d598fe8e458c09vboxsync * General Public License as published by the Free Software Foundation,
b263fac6f6e7fa933c7bfb2a45d598fe8e458c09vboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
b263fac6f6e7fa933c7bfb2a45d598fe8e458c09vboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
b263fac6f6e7fa933c7bfb2a45d598fe8e458c09vboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * If you received this file as part of a commercial VirtualBox
de4157257515400c2c25373591135f110227b68cvboxsync * distribution, then only the terms of your commercial VirtualBox
de4157257515400c2c25373591135f110227b68cvboxsync * license agreement apply instead of the previous paragraph.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync */
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/*******************************************************************************
de4157257515400c2c25373591135f110227b68cvboxsync* Header Files *
de4157257515400c2c25373591135f110227b68cvboxsync*******************************************************************************/
de4157257515400c2c25373591135f110227b68cvboxsync#define LOG_GROUP LOG_GROUP_PGM
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/dbgf.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/pgm.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/cpum.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/iom.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/sup.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/mm.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/em.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/stam.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/csam.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/rem.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/dbgf.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/rem.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/selm.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/ssm.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include "PGMInternal.h"
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/vm.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/dbg.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/log.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <iprt/assert.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <iprt/alloc.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <iprt/asm.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <iprt/thread.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <iprt/string.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/param.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/err.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#include <VBox/hwaccm.h>
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync/*******************************************************************************
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync* Internal Functions *
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync*******************************************************************************/
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsyncstatic DECLCALLBACK(int) pgmR3HandlerPhysicalOneClear(PAVLROGCPHYSNODECORE pNode, void *pvUser);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsyncstatic DECLCALLBACK(int) pgmR3HandlerPhysicalOneSet(PAVLROGCPHYSNODECORE pNode, void *pvUser);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsyncstatic DECLCALLBACK(int) pgmR3InfoHandlersPhysicalOne(PAVLROGCPHYSNODECORE pNode, void *pvUser);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsyncstatic DECLCALLBACK(int) pgmR3InfoHandlersVirtualOne(PAVLROGCPTRNODECORE pNode, void *pvUser);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * Register a access handler for a physical range.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @returns VBox status code.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pVM VM handle.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * @param enmType Handler type. Any of the PGMPHYSHANDLERTYPE_PHYSICAL* enums.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * @param GCPhys Start physical address.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * @param GCPhysLast Last physical address. (inclusive)
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * @param pfnHandlerR3 The R3 handler.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pvUserR3 User argument to the R3 handler.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pszModR0 The R0 handler module. NULL means default R0 module.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pszHandlerR0 The R0 handler symbol name.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pvUserR0 User argument to the R0 handler.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pszModGC The GC handler module. NULL means default GC module.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pszHandlerGC The GC handler symbol name.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pvUserGC User argument to the GC handler.
de4157257515400c2c25373591135f110227b68cvboxsync * This must be a GC pointer because it will be relocated!
de4157257515400c2c25373591135f110227b68cvboxsync * @param pszDesc Pointer to description string. This must not be freed.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsyncPGMR3DECL(int) PGMR3HandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast,
de4157257515400c2c25373591135f110227b68cvboxsync PFNPGMR3PHYSHANDLER pfnHandlerR3, void *pvUserR3,
de4157257515400c2c25373591135f110227b68cvboxsync const char *pszModR0, const char *pszHandlerR0, RTR0PTR pvUserR0,
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync const char *pszModGC, const char *pszHandlerGC, RTGCPTR pvUserGC, const char *pszDesc)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync LogFlow(("PGMR3HandlerPhysicalRegister: enmType=%d GCPhys=%VGv GCPhysLast=%VGv pfnHandlerR3=%VHv pvUserHC=%VHv pszModGC=%p:{%s} pszHandlerGC=%p:{%s} pvUser=%VGv pszDesc=%s\n",
de4157257515400c2c25373591135f110227b68cvboxsync enmType, GCPhys, GCPhysLast, pfnHandlerR3, pvUserR3, pszModGC, pszModGC, pszHandlerGC, pszHandlerGC, pvUserGC, pszDesc));
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Validate input.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync if (!pszModGC)
de4157257515400c2c25373591135f110227b68cvboxsync pszModGC = VMMGC_MAIN_MODULE_NAME;
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync if (!pszModR0)
de4157257515400c2c25373591135f110227b68cvboxsync pszModR0 = VMMR0_MAIN_MODULE_NAME;
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Resolve the R0 handler.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync R0PTRTYPE(PFNPGMR0PHYSHANDLER) pfnHandlerR0 = NIL_RTR0PTR;
de4157257515400c2c25373591135f110227b68cvboxsync int rc = VINF_SUCCESS;
de4157257515400c2c25373591135f110227b68cvboxsync if (pszHandlerR0 && HWACCMR3IsAllowed(pVM))
de4157257515400c2c25373591135f110227b68cvboxsync rc = PDMR3GetSymbolR0Lazy(pVM, pszModR0, pszHandlerR0, &pfnHandlerR0);
de4157257515400c2c25373591135f110227b68cvboxsync if (VBOX_SUCCESS(rc))
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Resolve the GC handler.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync RTGCPTR pfnHandlerGC = NIL_RTGCPTR;
de4157257515400c2c25373591135f110227b68cvboxsync if (pszHandlerGC)
de4157257515400c2c25373591135f110227b68cvboxsync rc = PDMR3GetSymbolGCLazy(pVM, pszModGC, pszHandlerGC, &pfnHandlerGC);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync if (VBOX_SUCCESS(rc))
de4157257515400c2c25373591135f110227b68cvboxsync return PGMHandlerPhysicalRegisterEx(pVM, enmType, GCPhys, GCPhysLast, pfnHandlerR3, pvUserR3,
de4157257515400c2c25373591135f110227b68cvboxsync pfnHandlerR0, pvUserR0, pfnHandlerGC, pvUserGC, pszDesc);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync AssertMsgFailed(("Failed to resolve %s.%s, rc=%Vrc.\n", pszModGC, pszHandlerGC, rc));
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync else
de4157257515400c2c25373591135f110227b68cvboxsync AssertMsgFailed(("Failed to resolve %s.%s, rc=%Vrc.\n", pszModR0, pszHandlerR0, rc));
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync return rc;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * Updates the physical page access handlers.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @param pVM VM handle.
de4157257515400c2c25373591135f110227b68cvboxsync * @remark Only used when restoring a saved state.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsyncvoid pgmR3HandlerPhysicalUpdateAll(PVM pVM)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync LogFlow(("pgmHandlerPhysicalUpdateAll:\n"));
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Clear and set.
de4157257515400c2c25373591135f110227b68cvboxsync * (the right -> left on the setting pass is just bird speculating on cache hits)
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync pgmLock(pVM);
de4157257515400c2c25373591135f110227b68cvboxsync RTAvlroGCPhysDoWithAll(&pVM->pgm.s.CTXSUFF(pTrees)->PhysHandlers, true, pgmR3HandlerPhysicalOneClear, pVM);
de4157257515400c2c25373591135f110227b68cvboxsync RTAvlroGCPhysDoWithAll(&pVM->pgm.s.CTXSUFF(pTrees)->PhysHandlers, false, pgmR3HandlerPhysicalOneSet, pVM);
de4157257515400c2c25373591135f110227b68cvboxsync pgmUnlock(pVM);
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * Clears all the page level flags for one physical handler range.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @returns 0
de4157257515400c2c25373591135f110227b68cvboxsync * @param pNode Pointer to a PGMPHYSHANDLER.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pvUser VM handle.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsyncstatic DECLCALLBACK(int) pgmR3HandlerPhysicalOneClear(PAVLROGCPHYSNODECORE pNode, void *pvUser)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)pNode;
de4157257515400c2c25373591135f110227b68cvboxsync PPGMRAMRANGE pRamHint = NULL;
de4157257515400c2c25373591135f110227b68cvboxsync RTGCPHYS GCPhys = pCur->Core.Key;
de4157257515400c2c25373591135f110227b68cvboxsync RTUINT cPages = pCur->cPages;
de4157257515400c2c25373591135f110227b68cvboxsync PPGM pPGM = &((PVM)pvUser)->pgm.s;
de4157257515400c2c25373591135f110227b68cvboxsync for (;;)
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync PGMRamFlagsClearByGCPhysWithHint(pPGM, GCPhys, MM_RAM_FLAGS_PHYSICAL_HANDLER | MM_RAM_FLAGS_PHYSICAL_WRITE | MM_RAM_FLAGS_PHYSICAL_ALL, &pRamHint);
de4157257515400c2c25373591135f110227b68cvboxsync if (--cPages == 0)
de4157257515400c2c25373591135f110227b68cvboxsync return 0;
de4157257515400c2c25373591135f110227b68cvboxsync GCPhys += PAGE_SIZE;
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * Sets all the page level flags for one physical handler range.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @returns 0
de4157257515400c2c25373591135f110227b68cvboxsync * @param pNode Pointer to a PGMPHYSHANDLER.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pvUser VM handle.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsyncstatic DECLCALLBACK(int) pgmR3HandlerPhysicalOneSet(PAVLROGCPHYSNODECORE pNode, void *pvUser)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)pNode;
de4157257515400c2c25373591135f110227b68cvboxsync unsigned fFlags = pgmHandlerPhysicalCalcFlags(pCur);
de4157257515400c2c25373591135f110227b68cvboxsync PPGMRAMRANGE pRamHint = NULL;
de4157257515400c2c25373591135f110227b68cvboxsync RTGCPHYS GCPhys = pCur->Core.Key;
de4157257515400c2c25373591135f110227b68cvboxsync RTUINT cPages = pCur->cPages;
de4157257515400c2c25373591135f110227b68cvboxsync PPGM pPGM = &((PVM)pvUser)->pgm.s;
de4157257515400c2c25373591135f110227b68cvboxsync for (;;)
de4157257515400c2c25373591135f110227b68cvboxsync {
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync PGMRamFlagsSetByGCPhysWithHint(pPGM, GCPhys, fFlags, &pRamHint);
de4157257515400c2c25373591135f110227b68cvboxsync if (--cPages == 0)
de4157257515400c2c25373591135f110227b68cvboxsync return 0;
de4157257515400c2c25373591135f110227b68cvboxsync GCPhys += PAGE_SIZE;
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * Register a access handler for a virtual range.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @returns VBox status code.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pVM VM handle.
de4157257515400c2c25373591135f110227b68cvboxsync * @param enmType Handler type. Any of the PGMVIRTHANDLERTYPE_* enums.
de4157257515400c2c25373591135f110227b68cvboxsync * @param GCPtr Start address.
de4157257515400c2c25373591135f110227b68cvboxsync * @param GCPtrLast Last address (inclusive).
de4157257515400c2c25373591135f110227b68cvboxsync * @param pfnInvalidateHC The HC invalidate callback (can be 0)
de4157257515400c2c25373591135f110227b68cvboxsync * @param pfnHandlerHC The HC handler.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pszHandlerGC The GC handler symbol name.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pszModGC The GC handler module.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pszDesc Pointer to description string. This must not be freed.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync/** @todo rename this function to PGMR3HandlerVirtualRegister */
de4157257515400c2c25373591135f110227b68cvboxsyncPGMR3DECL(int) PGMR3HandlerVirtualRegister(PVM pVM, PGMVIRTHANDLERTYPE enmType, RTGCPTR GCPtr, RTGCPTR GCPtrLast,
de4157257515400c2c25373591135f110227b68cvboxsync PFNPGMHCVIRTINVALIDATE pfnInvalidateHC,
de4157257515400c2c25373591135f110227b68cvboxsync PFNPGMHCVIRTHANDLER pfnHandlerHC,
de4157257515400c2c25373591135f110227b68cvboxsync const char *pszHandlerGC, const char *pszModGC,
de4157257515400c2c25373591135f110227b68cvboxsync const char *pszDesc)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync LogFlow(("PGMR3HandlerVirtualRegisterEx: enmType=%d GCPtr=%VGv GCPtrLast=%VGv pszHandlerGC=%p:{%s} pszModGC=%p:{%s} pszDesc=%s\n",
de4157257515400c2c25373591135f110227b68cvboxsync enmType, GCPtr, GCPtrLast, pszHandlerGC, pszHandlerGC, pszModGC, pszModGC, pszDesc));
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Validate input.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync if (!pszModGC)
de4157257515400c2c25373591135f110227b68cvboxsync pszModGC = VMMGC_MAIN_MODULE_NAME;
de4157257515400c2c25373591135f110227b68cvboxsync if (!pszModGC || !*pszModGC || !pszHandlerGC || !*pszHandlerGC)
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync AssertMsgFailed(("pfnHandlerGC or/and pszModGC is missing\n"));
de4157257515400c2c25373591135f110227b68cvboxsync return VERR_INVALID_PARAMETER;
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Resolve the GC handler.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync RTGCPTR pfnHandlerGC;
de4157257515400c2c25373591135f110227b68cvboxsync int rc = PDMR3GetSymbolGCLazy(pVM, pszModGC, pszHandlerGC, &pfnHandlerGC);
de4157257515400c2c25373591135f110227b68cvboxsync if (VBOX_SUCCESS(rc))
de4157257515400c2c25373591135f110227b68cvboxsync return PGMHandlerVirtualRegisterEx(pVM, enmType, GCPtr, GCPtrLast, pfnInvalidateHC, pfnHandlerHC, pfnHandlerGC, pszDesc);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync AssertMsgFailed(("Failed to resolve %s.%s, rc=%Vrc.\n", pszModGC, pszHandlerGC, rc));
de4157257515400c2c25373591135f110227b68cvboxsync return rc;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * Register an access handler for a virtual range.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @returns VBox status code.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pVM VM handle.
de4157257515400c2c25373591135f110227b68cvboxsync * @param enmType Handler type. Any of the PGMVIRTHANDLERTYPE_* enums.
de4157257515400c2c25373591135f110227b68cvboxsync * @param GCPtr Start address.
de4157257515400c2c25373591135f110227b68cvboxsync * @param GCPtrLast Last address (inclusive).
de4157257515400c2c25373591135f110227b68cvboxsync * @param pfnInvalidateHC The HC invalidate callback (can be 0)
de4157257515400c2c25373591135f110227b68cvboxsync * @param pfnHandlerHC The HC handler.
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync * @param pfnHandlerGC The GC handler.
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync * @param pszDesc Pointer to description string. This must not be freed.
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsync */
66d43d6192fb8fbb95c01515ba64f8a1e678a863vboxsync/** @todo rename this to PGMR3HandlerVirtualRegisterEx. */
ccc948c886b751603889a67909fbd4a5fcaeac85vboxsyncPGMDECL(int) PGMHandlerVirtualRegisterEx(PVM pVM, PGMVIRTHANDLERTYPE enmType, RTGCPTR GCPtr, RTGCPTR GCPtrLast,
de4157257515400c2c25373591135f110227b68cvboxsync PFNPGMHCVIRTINVALIDATE pfnInvalidateHC,
de4157257515400c2c25373591135f110227b68cvboxsync PFNPGMHCVIRTHANDLER pfnHandlerHC, RTGCPTR pfnHandlerGC,
de4157257515400c2c25373591135f110227b68cvboxsync HCPTRTYPE(const char *) pszDesc)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync Log(("PGMR3HandlerVirtualRegister: enmType=%d GCPtr=%RGv GCPtrLast=%RGv pfnHandlerGC=%RGv pszDesc=%s\n", enmType, GCPtr, GCPtrLast, pfnHandlerGC, pszDesc));
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Validate input.
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync */
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync switch (enmType)
de4157257515400c2c25373591135f110227b68cvboxsync {
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync case PGMVIRTHANDLERTYPE_NORMAL:
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync case PGMVIRTHANDLERTYPE_ALL:
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync case PGMVIRTHANDLERTYPE_WRITE:
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync case PGMVIRTHANDLERTYPE_EIP:
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync if (!pfnHandlerHC)
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync {
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync AssertMsgFailed(("No HC handler specified!!\n"));
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync return VERR_INVALID_PARAMETER;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync }
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync break;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync case PGMVIRTHANDLERTYPE_HYPERVISOR:
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync if (pfnHandlerHC)
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync {
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync AssertMsgFailed(("HC handler specified for hypervisor range!?!\n"));
de4157257515400c2c25373591135f110227b68cvboxsync return VERR_INVALID_PARAMETER;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync }
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync break;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync default:
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync AssertMsgFailed(("Invalid enmType! enmType=%d\n", enmType));
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync return VERR_INVALID_PARAMETER;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync }
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync if (GCPtrLast < GCPtr)
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync {
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync AssertMsgFailed(("GCPtrLast < GCPtr (%#x < %#x)\n", GCPtrLast, GCPtr));
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync return VERR_INVALID_PARAMETER;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync }
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync if (!pfnHandlerGC)
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync AssertMsgFailed(("pfnHandlerGC is missing\n"));
de4157257515400c2c25373591135f110227b68cvboxsync return VERR_INVALID_PARAMETER;
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Allocate and initialize a new entry.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync unsigned cPages = (RT_ALIGN((RTGCUINTPTR)GCPtrLast + 1, PAGE_SIZE) - ((RTGCUINTPTR)GCPtr & PAGE_BASE_GC_MASK)) >> PAGE_SHIFT;
de4157257515400c2c25373591135f110227b68cvboxsync PPGMVIRTHANDLER pNew;
de4157257515400c2c25373591135f110227b68cvboxsync int rc = MMHyperAlloc(pVM, RT_OFFSETOF(PGMVIRTHANDLER, aPhysToVirt[cPages]), 0, MM_TAG_PGM_HANDLERS, (void **)&pNew); /** @todo r=bird: incorrect member name PhysToVirt? */
de4157257515400c2c25373591135f110227b68cvboxsync if (VBOX_FAILURE(rc))
de4157257515400c2c25373591135f110227b68cvboxsync return rc;
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync pNew->Core.Key = GCPtr;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->Core.KeyLast = GCPtrLast;
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync pNew->enmType = enmType;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->pfnInvalidateHC = pfnInvalidateHC;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync pNew->pfnHandlerGC = pfnHandlerGC;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync pNew->pfnHandlerHC = pfnHandlerHC;
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync pNew->pszDesc = pszDesc;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->GCPtr = GCPtr;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->GCPtrLast = GCPtrLast;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->cb = GCPtrLast - GCPtr + 1;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->cPages = cPages;
de4157257515400c2c25373591135f110227b68cvboxsync /* Will be synced at next guest execution attempt. */
de4157257515400c2c25373591135f110227b68cvboxsync while (cPages-- > 0)
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync pNew->aPhysToVirt[cPages].Core.Key = NIL_RTGCPHYS;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->aPhysToVirt[cPages].Core.KeyLast = NIL_RTGCPHYS;
de4157257515400c2c25373591135f110227b68cvboxsync pNew->aPhysToVirt[cPages].offVirtHandler = -RT_OFFSETOF(PGMVIRTHANDLER, aPhysToVirt[cPages]);
de4157257515400c2c25373591135f110227b68cvboxsync pNew->aPhysToVirt[cPages].offNextAlias = 0;
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Try to insert it into the tree.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * The current implementation doesn't allow multiple handlers for
de4157257515400c2c25373591135f110227b68cvboxsync * the same range this makes everything much simpler and faster.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync pgmLock(pVM);
de4157257515400c2c25373591135f110227b68cvboxsync if (pVM->pgm.s.pTreesHC->VirtHandlers != 0)
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrGetBestFit(&pVM->pgm.s.CTXSUFF(pTrees)->VirtHandlers, pNew->Core.Key, true);
de4157257515400c2c25373591135f110227b68cvboxsync if (!pCur || GCPtr > pCur->GCPtrLast || GCPtrLast < pCur->GCPtr)
de4157257515400c2c25373591135f110227b68cvboxsync pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrGetBestFit(&pVM->pgm.s.CTXSUFF(pTrees)->VirtHandlers, pNew->Core.Key, false);
de4157257515400c2c25373591135f110227b68cvboxsync if (pCur && GCPtr <= pCur->GCPtrLast && GCPtrLast >= pCur->GCPtr)
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * The LDT sometimes conflicts with the IDT and LDT ranges while being
de4157257515400c2c25373591135f110227b68cvboxsync * updated on linux. So, we don't assert simply log it.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync Log(("PGMR3HandlerVirtualRegister: Conflict with existing range %RGv-%RGv (%s), req. %RGv-%RGv (%s)\n",
de4157257515400c2c25373591135f110227b68cvboxsync pCur->GCPtr, pCur->GCPtrLast, pCur->pszDesc, GCPtr, GCPtrLast, pszDesc));
de4157257515400c2c25373591135f110227b68cvboxsync MMHyperFree(pVM, pNew);
de4157257515400c2c25373591135f110227b68cvboxsync pgmUnlock(pVM);
de4157257515400c2c25373591135f110227b68cvboxsync return VERR_PGM_HANDLER_VIRTUAL_CONFLICT;
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync if (RTAvlroGCPtrInsert(&pVM->pgm.s.CTXSUFF(pTrees)->VirtHandlers, &pNew->Core))
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync if (enmType != PGMVIRTHANDLERTYPE_HYPERVISOR)
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync pVM->pgm.s.fPhysCacheFlushPending = true;
de4157257515400c2c25373591135f110227b68cvboxsync pVM->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL | PGM_SYNC_CLEAR_PGM_POOL;
de4157257515400c2c25373591135f110227b68cvboxsync VM_FF_SET(pVM, VM_FF_PGM_SYNC_CR3);
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync pgmUnlock(pVM);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync#ifdef VBOX_WITH_STATISTICS
de4157257515400c2c25373591135f110227b68cvboxsync char szPath[256];
de4157257515400c2c25373591135f110227b68cvboxsync RTStrPrintf(szPath, sizeof(szPath), "/PGM/VirtHandler/Calls/%VGv-%VGv", pNew->GCPtr, pNew->GCPtrLast);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync rc = STAMR3Register(pVM, &pNew->Stat, STAMTYPE_PROFILE, STAMVISIBILITY_USED, szPath, STAMUNIT_TICKS_PER_CALL, pszDesc);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync AssertRC(rc);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync#endif
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync return VINF_SUCCESS;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync }
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync pgmUnlock(pVM);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync AssertFailed();
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync MMHyperFree(pVM, pNew);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync return VERR_PGM_HANDLER_VIRTUAL_CONFLICT;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync}
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync/**
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * Modify the page invalidation callback handler for a registered virtual range
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * (add more when needed)
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @returns VBox status code.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pVM VM handle.
de4157257515400c2c25373591135f110227b68cvboxsync * @param GCPtr Start address.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pfnInvalidateHC The HC invalidate callback (can be 0)
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync */
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsyncPGMDECL(int) PGMHandlerVirtualChangeInvalidateCallback(PVM pVM, RTGCPTR GCPtr, PFNPGMHCVIRTINVALIDATE pfnInvalidateHC)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync pgmLock(pVM);
de4157257515400c2c25373591135f110227b68cvboxsync PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrGet(&pVM->pgm.s.pTreesHC->VirtHandlers, GCPtr);
de4157257515400c2c25373591135f110227b68cvboxsync if (pCur)
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync pCur->pfnInvalidateHC = pfnInvalidateHC;
de4157257515400c2c25373591135f110227b68cvboxsync pgmUnlock(pVM);
de4157257515400c2c25373591135f110227b68cvboxsync return VINF_SUCCESS;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync pgmUnlock(pVM);
de4157257515400c2c25373591135f110227b68cvboxsync AssertMsgFailed(("Range %#x not found!\n", GCPtr));
de4157257515400c2c25373591135f110227b68cvboxsync return VERR_INVALID_PARAMETER;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * Deregister an access handler for a virtual range.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @returns VBox status code.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pVM VM handle.
de4157257515400c2c25373591135f110227b68cvboxsync * @param GCPtr Start address.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsyncPGMDECL(int) PGMHandlerVirtualDeregister(PVM pVM, RTGCPTR GCPtr)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync /*
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * Find the handler.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * We naturally assume GCPtr is a unique specification.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync pgmLock(pVM);
de4157257515400c2c25373591135f110227b68cvboxsync PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrRemove(&pVM->pgm.s.CTXSUFF(pTrees)->VirtHandlers, GCPtr);
de4157257515400c2c25373591135f110227b68cvboxsync if (pCur)
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync Log(("PGMR3HandlerVirtualDeregister: Removing Virtual (%d) Range %#x-%#x %s\n", pCur->enmType,
de4157257515400c2c25373591135f110227b68cvboxsync pCur->GCPtr, pCur->GCPtrLast, pCur->pszDesc));
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsync * Reset the flags and remove phys2virt nodes.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync PPGM pPGM = &pVM->pgm.s;
c69091b522190cc83264ed458a05c6b2660a167cvboxsync for (unsigned iPage = 0; iPage < pCur->cPages; iPage++)
de4157257515400c2c25373591135f110227b68cvboxsync if (pCur->aPhysToVirt[iPage].offNextAlias & PGMPHYS2VIRTHANDLER_IN_TREE)
de4157257515400c2c25373591135f110227b68cvboxsync pgmHandlerVirtualClearPage(pPGM, pCur, iPage);
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Schedule CR3 sync (if required) and the memory.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync STAM_DEREG(pVM, &pCur->Stat);
de4157257515400c2c25373591135f110227b68cvboxsync if (pCur->enmType != PGMVIRTHANDLERTYPE_HYPERVISOR)
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync pVM->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL | PGM_SYNC_CLEAR_PGM_POOL;
de4157257515400c2c25373591135f110227b68cvboxsync VM_FF_SET(pVM, VM_FF_PGM_SYNC_CR3);
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync MMHyperFree(pVM, pCur);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync pgmUnlock(pVM);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync return VINF_SUCCESS;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync }
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync pgmUnlock(pVM);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync AssertMsgFailed(("Range %#x not found!\n", GCPtr));
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync return VERR_INVALID_PARAMETER;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * Arguments for pgmR3InfoHandlersPhysicalOne and pgmR3InfoHandlersVirtualOne.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsynctypedef struct PGMHANDLERINFOARG
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync /** The output helpers.*/
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsync PCDBGFINFOHLP pHlp;
de4157257515400c2c25373591135f110227b68cvboxsync /** Set if statistics should be dumped. */
de4157257515400c2c25373591135f110227b68cvboxsync bool fStats;
de4157257515400c2c25373591135f110227b68cvboxsync} PGMHANDLERINFOARG, *PPGMHANDLERINFOARG;
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * Info callback for 'pgmhandlers'.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @param pHlp The output helpers.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pszArgs The arguments. phys or virt.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync */
de4157257515400c2c25373591135f110227b68cvboxsyncDECLCALLBACK(void) pgmR3InfoHandlers(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Test input.
de4157257515400c2c25373591135f110227b68cvboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync PGMHANDLERINFOARG Args = { pHlp, true };
de4157257515400c2c25373591135f110227b68cvboxsync bool fPhysical = !pszArgs || !*pszArgs;
de4157257515400c2c25373591135f110227b68cvboxsync bool fVirtual = fPhysical;
de4157257515400c2c25373591135f110227b68cvboxsync if (!fPhysical)
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync fPhysical = strstr(pszArgs, "phys") != NULL;
de4157257515400c2c25373591135f110227b68cvboxsync fVirtual = strstr(pszArgs, "virt") != NULL;
de4157257515400c2c25373591135f110227b68cvboxsync Args.fStats = strstr(pszArgs, "nost") == NULL;
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync /*
de4157257515400c2c25373591135f110227b68cvboxsync * Dump the handlers.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync */
de4157257515400c2c25373591135f110227b68cvboxsync if (fPhysical)
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync pHlp->pfnPrintf(pHlp,
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync "Physical handlers: (PhysHandlers=%d (%#x))\n"
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync "From - To (incl) HandlerHC UserHC HandlerGC UserGC Type Description\n",
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync pVM->pgm.s.pTreesHC->PhysHandlers, pVM->pgm.s.pTreesHC->PhysHandlers);
de4157257515400c2c25373591135f110227b68cvboxsync RTAvlroGCPhysDoWithAll(&pVM->pgm.s.pTreesHC->PhysHandlers, true, pgmR3InfoHandlersPhysicalOne, &Args);
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync if (fVirtual)
de4157257515400c2c25373591135f110227b68cvboxsync {
de4157257515400c2c25373591135f110227b68cvboxsync pHlp->pfnPrintf(pHlp,
de4157257515400c2c25373591135f110227b68cvboxsync "Virtual handlers:\n"
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync "From - To (excl) HandlerHC HandlerGC Type Description\n");
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync RTAvlroGCPtrDoWithAll(&pVM->pgm.s.pTreesHC->VirtHandlers, true, pgmR3InfoHandlersVirtualOne, &Args);
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * Displays one physical handler range.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync *
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * @returns 0
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * @param pNode Pointer to a PGMPHYSHANDLER.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync * @param pvUser Pointer to command helper functions.
de4157257515400c2c25373591135f110227b68cvboxsync */
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsyncstatic DECLCALLBACK(int) pgmR3InfoHandlersPhysicalOne(PAVLROGCPHYSNODECORE pNode, void *pvUser)
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync{
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)pNode;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync PPGMHANDLERINFOARG pArgs= (PPGMHANDLERINFOARG)pvUser;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync PCDBGFINFOHLP pHlp = pArgs->pHlp;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync const char *pszType;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync switch (pCur->enmType)
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync {
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync case PGMPHYSHANDLERTYPE_MMIO: pszType = "MMIO "; break;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync case PGMPHYSHANDLERTYPE_PHYSICAL: pszType = "Natural"; break;
de4157257515400c2c25373591135f110227b68cvboxsync case PGMPHYSHANDLERTYPE_PHYSICAL_WRITE: pszType = "Write "; break;
de4157257515400c2c25373591135f110227b68cvboxsync case PGMPHYSHANDLERTYPE_PHYSICAL_ALL: pszType = "All "; break;
de4157257515400c2c25373591135f110227b68cvboxsync default: pszType = "????"; break;
de4157257515400c2c25373591135f110227b68cvboxsync }
de4157257515400c2c25373591135f110227b68cvboxsync pHlp->pfnPrintf(pHlp,
de4157257515400c2c25373591135f110227b68cvboxsync "%VGp - %VGp %VHv %VHv %VGv %VGv %s %s\n",
5a9f1d57ea268b1d88ff2492d9d59a696b1c693evboxsync pCur->Core.Key, pCur->Core.KeyLast, pCur->pfnHandlerR3, pCur->pvUserR3, pCur->pfnHandlerGC, pCur->pvUserGC, pszType, pCur->pszDesc);
de4157257515400c2c25373591135f110227b68cvboxsync#ifdef VBOX_WITH_STATISTICS
de4157257515400c2c25373591135f110227b68cvboxsync if (pArgs->fStats)
5f809eed9fe4d8f7f317e8102657eb877fd5fbdavboxsync pHlp->pfnPrintf(pHlp, " cPeriods: %9RU64 cTicks: %11RU64 Min: %11RU64 Avg: %11RU64 Max: %11RU64\n",
de4157257515400c2c25373591135f110227b68cvboxsync pCur->Stat.cPeriods, pCur->Stat.cTicks, pCur->Stat.cTicksMin,
de4157257515400c2c25373591135f110227b68cvboxsync pCur->Stat.cPeriods ? pCur->Stat.cTicks / pCur->Stat.cPeriods : 0, pCur->Stat.cTicksMax);
de4157257515400c2c25373591135f110227b68cvboxsync#endif
de4157257515400c2c25373591135f110227b68cvboxsync return 0;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync
de4157257515400c2c25373591135f110227b68cvboxsync/**
de4157257515400c2c25373591135f110227b68cvboxsync * Displays one virtual handler range.
de4157257515400c2c25373591135f110227b68cvboxsync *
de4157257515400c2c25373591135f110227b68cvboxsync * @returns 0
de4157257515400c2c25373591135f110227b68cvboxsync * @param pNode Pointer to a PGMVIRTHANDLER.
de4157257515400c2c25373591135f110227b68cvboxsync * @param pvUser Pointer to command helper functions.
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync */
de4157257515400c2c25373591135f110227b68cvboxsyncstatic DECLCALLBACK(int) pgmR3InfoHandlersVirtualOne(PAVLROGCPTRNODECORE pNode, void *pvUser)
de4157257515400c2c25373591135f110227b68cvboxsync{
de4157257515400c2c25373591135f110227b68cvboxsync PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)pNode;
de4157257515400c2c25373591135f110227b68cvboxsync PPGMHANDLERINFOARG pArgs= (PPGMHANDLERINFOARG)pvUser;
de4157257515400c2c25373591135f110227b68cvboxsync PCDBGFINFOHLP pHlp = pArgs->pHlp;
de4157257515400c2c25373591135f110227b68cvboxsync const char *pszType;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync switch (pCur->enmType)
de4157257515400c2c25373591135f110227b68cvboxsync {
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync case PGMVIRTHANDLERTYPE_NORMAL: pszType = "Natural"; break;
de4157257515400c2c25373591135f110227b68cvboxsync case PGMVIRTHANDLERTYPE_WRITE: pszType = "Write "; break;
de4157257515400c2c25373591135f110227b68cvboxsync case PGMVIRTHANDLERTYPE_ALL: pszType = "All "; break;
de4157257515400c2c25373591135f110227b68cvboxsync case PGMVIRTHANDLERTYPE_EIP: pszType = "EIP "; break;
de4157257515400c2c25373591135f110227b68cvboxsync case PGMVIRTHANDLERTYPE_HYPERVISOR: pszType = "WriteHyp "; break;
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync default: pszType = "????"; break;
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync }
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync pHlp->pfnPrintf(pHlp, "%08x - %08x %08x %08x %s %s\n",
75479ee94ecd639290ae67b38c9497d9492f89e1vboxsync pCur->GCPtr, pCur->GCPtrLast, pCur->pfnHandlerHC, pCur->pfnHandlerGC, pszType, pCur->pszDesc);
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync#ifdef VBOX_WITH_STATISTICS
9f0a3520e48fa74caec1abadb643db5710ad97e0vboxsync if (pArgs->fStats)
de4157257515400c2c25373591135f110227b68cvboxsync pHlp->pfnPrintf(pHlp, " cPeriods: %9RU64 cTicks: %11RU64 Min: %11RU64 Avg: %11RU64 Max: %11RU64\n",
de4157257515400c2c25373591135f110227b68cvboxsync pCur->Stat.cPeriods, pCur->Stat.cTicks, pCur->Stat.cTicksMin,
de4157257515400c2c25373591135f110227b68cvboxsync pCur->Stat.cPeriods ? pCur->Stat.cTicks / pCur->Stat.cPeriods : 0, pCur->Stat.cTicksMax);
de4157257515400c2c25373591135f110227b68cvboxsync#endif
de4157257515400c2c25373591135f110227b68cvboxsync return 0;
de4157257515400c2c25373591135f110227b68cvboxsync}
de4157257515400c2c25373591135f110227b68cvboxsync
2a047f0d7ee5964456dbc4dec9925031482588abvboxsync