IOMInternal.h revision d7e96bc7ad8785a8bae374f78c250b2754a44ff4
/* $Id$ */
/** @file
* IOM - Internal header file.
*/
/*
* Copyright (C) 2006 InnoTek Systemberatung GmbH
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation,
* in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
* distribution. VirtualBox OSE is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY of any kind.
*
* If you received this file as part of a commercial VirtualBox
* distribution, then only the terms of your commercial VirtualBox
* license agreement apply instead of the previous paragraph.
*/
#ifndef __IOMInternal_h__
#define __IOMInternal_h__
#include <VBox/cdefs.h>
#include <VBox/types.h>
#include <VBox/iom.h>
#include <VBox/stam.h>
#include <iprt/avl.h>
#if !defined(IN_IOM_R3) && !defined(IN_IOM_R0) && !defined(IN_IOM_GC)
# error "Not in IOM! This is an internal header!"
#endif
/** @defgroup grp_iom_int Internals
* @ingroup grp_iom
* @internal
* @{
*/
/**
* MMIO range descriptor, R3 version.
*/
typedef struct IOMMMIORANGER3
{
/** Avl node core with GCPhys as Key and GCPhys + cbSize - 1 as KeyLast. */
AVLROGCPHYSNODECORE Core;
/** Start physical address. */
RTGCPHYS GCPhys;
/** Size of the range. */
RTUINT cbSize;
/** Pointer to user argument. */
RTHCPTR pvUser;
/** Pointer to device instance. */
HCPTRTYPE(PPDMDEVINS) pDevIns;
/** Pointer to write callback function. */
HCPTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallback;
/** Pointer to read callback function. */
HCPTRTYPE(PFNIOMMMIOREAD) pfnReadCallback;
/** Pointer to fill (memset) callback function. */
HCPTRTYPE(PFNIOMMMIOFILL) pfnFillCallback;
/** Description / Name. For easing debugging. */
HCPTRTYPE(const char *) pszDesc;
} IOMMMIORANGER3;
/** Pointer to a MMIO range descriptor, R3 version. */
typedef struct IOMMMIORANGER3 *PIOMMMIORANGER3;
/** MMIO range descriptor, R0 version. */
typedef IOMMMIORANGER3 IOMMMIORANGER0;
/** Pointer to a MMIO range descriptor, R0 version. */
typedef PIOMMMIORANGER3 PIOMMMIORANGER0;
/**
* MMIO range descriptor, GC version.
*/
typedef struct IOMMMIORANGEGC
{
/** Avl node core with GCPhys as Key and GCPhys + cbSize - 1 as KeyLast. */
AVLROGCPHYSNODECORE Core;
/** Start physical address. */
RTGCPHYS GCPhys;
/** Size of the range. */
RTUINT cbSize;
/** Pointer to user argument. */
RTGCPTR pvUser;
/** Pointer to device instance. */
GCPTRTYPE(PPDMDEVINS) pDevIns;
/** Pointer to write callback function. */
GCPTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallback;
/** Pointer to read callback function. */
GCPTRTYPE(PFNIOMMMIOREAD) pfnReadCallback;
/** Pointer to fill (memset) callback function. */
GCPTRTYPE(PFNIOMMMIOFILL) pfnFillCallback;
/** Description / Name. For easing debugging. */
HCPTRTYPE(const char *) pszDesc;
} IOMMMIORANGEGC;
/** Pointer to a MMIO range descriptor, GC version. */
typedef struct IOMMMIORANGEGC *PIOMMMIORANGEGC;
/**
* MMIO address statistics. (one address)
*
* This is a simple way of making on demand statistics, however it's a
* bit free with the hypervisor heap memory..
*/
typedef struct IOMMMIOSTATS
{
/** Avl node core with the address as Key. */
AVLOGCPHYSNODECORE Core;
/** Number of reads to this address from R3. */
STAMCOUNTER ReadR3;
/** Number of writes to this address from R3. */
STAMCOUNTER WriteR3;
/** Number of reads to this address from R0. */
STAMCOUNTER ReadR0;
/** Number of writes to this address from R0. */
STAMCOUNTER WriteR0;
/** Number of reads to this address from GC. */
STAMCOUNTER ReadGC;
/** Number of writes to this address from GC. */
STAMCOUNTER WriteGC;
/** Profiling read handler overhead in R3. */
STAMPROFILEADV ProfReadR3;
/** Profiling write handler overhead in R3. */
STAMPROFILEADV ProfWriteR3;
/** Profiling read handler overhead in R0. */
STAMPROFILEADV ProfReadR0;
/** Profiling write handler overhead in R0. */
STAMPROFILEADV ProfWriteR0;
/** Profiling read handler overhead in GC. */
STAMPROFILEADV ProfReadGC;
/** Profiling write handler overhead in GC. */
STAMPROFILEADV ProfWriteGC;
/** Number of reads to this address from R0 which was serviced in R3. */
STAMCOUNTER ReadR0ToR3;
/** Number of writes to this address from R0 which was serviced in R3. */
STAMCOUNTER WriteR0ToR3;
/** Number of reads to this address from GC which was serviced in R3. */
STAMCOUNTER ReadGCToR3;
/** Number of writes to this address from GC which was serviced in R3. */
STAMCOUNTER WriteGCToR3;
} IOMMMIOSTATS;
/** Pointer to I/O port statistics. */
typedef IOMMMIOSTATS *PIOMMMIOSTATS;
/**
* I/O port range descriptor, R3 version.
*/
typedef struct IOMIOPORTRANGER3
{
/** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */
AVLROIOPORTNODECORE Core;
/** Start I/O port address. */
RTIOPORT Port;
/** Size of the range. */
uint16_t cPorts;
/** Pointer to user argument. */
RTHCPTR pvUser;
/** Pointer to the associated device instance. */
HCPTRTYPE(PPDMDEVINS) pDevIns;
/** Pointer to OUT callback function. */
HCPTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback;
/** Pointer to IN callback function. */
HCPTRTYPE(PFNIOMIOPORTIN) pfnInCallback;
/** Pointer to string OUT callback function. */
HCPTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;
/** Pointer to string IN callback function. */
HCPTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;
/** Description / Name. For easing debugging. */
HCPTRTYPE(const char *) pszDesc;
} IOMIOPORTRANGER3;
/** Pointer to I/O port range descriptor, R3 version. */
typedef IOMIOPORTRANGER3 *PIOMIOPORTRANGER3;
/** I/O port range descriptor, R0 version. */
typedef IOMIOPORTRANGER3 IOMIOPORTRANGER0;
/** Pointer to I/O port range descriptor, R0 version. */
typedef PIOMIOPORTRANGER3 PIOMIOPORTRANGER0;
/**
* I/O port range descriptor.
*/
typedef struct IOMIOPORTRANGEGC
{
/** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */
AVLROIOPORTNODECORE Core;
/** Start I/O port address. */
RTIOPORT Port;
/** Size of the range. */
uint16_t cPorts;
/** Pointer to user argument. */
RTGCPTR pvUser;
/** Pointer to the associated device instance. */
GCPTRTYPE(PPDMDEVINS) pDevIns;
/** Pointer to OUT callback function. */
GCPTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback;
/** Pointer to IN callback function. */
GCPTRTYPE(PFNIOMIOPORTIN) pfnInCallback;
/** Pointer to string OUT callback function. */
GCPTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;
/** Pointer to string IN callback function. */
GCPTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;
/** Description / Name. For easing debugging. */
HCPTRTYPE(const char *) pszDesc;
} IOMIOPORTRANGEGC;
/** Pointer to I/O port range descriptor, GC version. */
typedef IOMIOPORTRANGEGC *PIOMIOPORTRANGEGC;
/**
* I/O port statistics. (one I/O port)
*
* This is a simple way of making on demand statistics, however it's a
* bit free with the hypervisor heap memory..
*/
typedef struct IOMIOPORTSTATS
{
/** Avl node core with the port as Key. */
AVLOIOPORTNODECORE Core;
/** Number of INs to this port from R3. */
STAMCOUNTER InR3;
/** Number of OUTs to this port from R3. */
STAMCOUNTER OutR3;
/** Number of INs to this port from R0. */
STAMCOUNTER InR0;
/** Number of OUTs to this port from R0. */
STAMCOUNTER OutR0;
/** Number of INs to this port from GC. */
STAMCOUNTER InGC;
/** Number of OUTs to this port from GC. */
STAMCOUNTER OutGC;
/** Profiling IN handler overhead in R3. */
STAMPROFILEADV ProfInR3;
/** Profiling OUT handler overhead in R3. */
STAMPROFILEADV ProfOutR3;
/** Profiling IN handler overhead in R0. */
STAMPROFILEADV ProfInR0;
/** Profiling OUT handler overhead in R0. */
STAMPROFILEADV ProfOutR0;
/** Profiling IN handler overhead in GC. */
STAMPROFILEADV ProfInGC;
/** Profiling OUT handler overhead in GC. */
STAMPROFILEADV ProfOutGC;
/** Number of INs to this port from R0 which was serviced in R3. */
STAMCOUNTER InR0ToR3;
/** Number of OUTs to this port from R0 which was serviced in R3. */
STAMCOUNTER OutR0ToR3;
/** Number of INs to this port from GC which was serviced in R3. */
STAMCOUNTER InGCToR3;
/** Number of OUTs to this port from GC which was serviced in R3. */
STAMCOUNTER OutGCToR3;
} IOMIOPORTSTATS;
/** Pointer to I/O port statistics. */
typedef IOMIOPORTSTATS *PIOMIOPORTSTATS;
/**
* The IOM trees.
* These are offset based the nodes and root must be in the same
* memory block in HC. The locations of IOM structure and the hypervisor heap
* are quite different in HC and GC.
*/
typedef struct IOMTREES
{
/** Tree containing I/O port range descriptors registered for HC (IOMIOPORTRANGEHC). */
AVLROIOPORTTREE IOPortTreeR3;
/** Tree containing I/O port range descriptors registered for R0 (IOMIOPORTRANGER0). */
AVLROIOPORTTREE IOPortTreeR0;
/** Tree containing I/O port range descriptors registered for GC (IOMIOPORTRANGEGC). */
AVLROIOPORTTREE IOPortTreeGC;
/** Tree containing MMIO range descriptors registered for HC (IOMMMIORANGEHC). */
AVLROGCPHYSTREE MMIOTreeR3;
/** Tree containing MMIO range descriptors registered for R0 (IOMMMIORANGER0). */
AVLROGCPHYSTREE MMIOTreeR0;
/** Tree containing MMIO range descriptors registered for GC (IOMMMIORANGEGC). */
AVLROGCPHYSTREE MMIOTreeGC;
/** Tree containing I/O port statistics (IOMIOPORTSTATS). */
AVLOIOPORTTREE IOPortStatTree;
/** Tree containing MMIO statistics (IOMMMIOSTATS). */
AVLOGCPHYSTREE MMIOStatTree;
} IOMTREES;
/** Pointer to the IOM trees. */
typedef IOMTREES *PIOMTREES;
/**
* Converts an IOM pointer into a VM pointer.
* @returns Pointer to the VM structure the PGM is part of.
* @param pIOM Pointer to IOM instance data.
*/
#define IOM2VM(pIOM) ( (PVM)((char*)pIOM - pIOM->offVM) )
/**
* IOM Data (part of VM)
*/
typedef struct IOM
{
/** Offset to the VM structure. */
RTINT offVM;
/** Pointer to the trees - GC ptr. */
GCPTRTYPE(PIOMTREES) pTreesGC;
/** Pointer to the trees - HC ptr. */
HCPTRTYPE(PIOMTREES) pTreesHC;
/** @name Caching of I/O Port ranges and statistics.
* (Saves quite some time in rep outs/ins instruction emulation.)
* @{ */
HCPTRTYPE(PIOMIOPORTRANGER3) pRangeLastReadR3;
HCPTRTYPE(PIOMIOPORTRANGER3) pRangeLastWriteR3;
HCPTRTYPE(PIOMIOPORTSTATS) pStatsLastReadR3;
HCPTRTYPE(PIOMIOPORTSTATS) pStatsLastWriteR3;
HCPTRTYPE(PIOMIOPORTRANGER0) pRangeLastReadR0;
HCPTRTYPE(PIOMIOPORTRANGER0) pRangeLastWriteR0;
HCPTRTYPE(PIOMIOPORTSTATS) pStatsLastReadR0;
HCPTRTYPE(PIOMIOPORTSTATS) pStatsLastWriteR0;
GCPTRTYPE(PIOMIOPORTRANGEGC) pRangeLastReadGC;
GCPTRTYPE(PIOMIOPORTRANGEGC) pRangeLastWriteGC;
GCPTRTYPE(PIOMIOPORTSTATS) pStatsLastReadGC;
GCPTRTYPE(PIOMIOPORTSTATS) pStatsLastWriteGC;
/** @} */
/** @name I/O Port statistics.
* @{ */
STAMPROFILE StatGCIOPortHandler;
STAMCOUNTER StatGCInstIn;
STAMCOUNTER StatGCInstOut;
STAMCOUNTER StatGCInstIns;
STAMCOUNTER StatGCInstOuts;
/** @} */
/** @name MMIO statistics.
* @{ */
STAMPROFILE StatGCMMIOHandler;
STAMCOUNTER StatGCMMIOFailures;
STAMPROFILE StatGCInstMov;
STAMPROFILE StatGCInstCmp;
STAMPROFILE StatGCInstAnd;
STAMPROFILE StatGCInstTest;
STAMPROFILE StatGCInstXchg;
STAMPROFILE StatGCInstStos;
STAMPROFILE StatGCInstLods;
STAMPROFILE StatGCInstMovs;
STAMPROFILE StatGCInstMovsToMMIO;
STAMPROFILE StatGCInstMovsFromMMIO;
STAMPROFILE StatGCInstMovsMMIO;
STAMCOUNTER StatGCInstOther;
STAMCOUNTER StatGCMMIO1Byte;
STAMCOUNTER StatGCMMIO2Bytes;
STAMCOUNTER StatGCMMIO4Bytes;
RTUINT cMovsMaxBytes;
RTUINT cStosMaxBytes;
/** @} */
} IOM;
/** Pointer to IOM instance data. */
typedef IOM *PIOM;
__BEGIN_DECLS
#ifdef IN_IOM_R3
PIOMIOPORTSTATS iomr3IOPortStatsCreate(PVM pVM, RTIOPORT Port, const char *pszDesc);
PIOMMMIOSTATS iomR3MMIOStatsCreate(PVM pVM, RTGCPHYS GCPhys, const char *pszDesc);
#endif /* IN_IOM_R3 */
/**
* \#PF Handler callback for MMIO ranges.
*
* @returns VBox status code (appropriate for GC return).
*
* @param pVM VM Handle.
* @param uErrorCode CPU Error code.
* @param pRegFrame Trap register frame.
* @param pvFault The fault address (cr2).
* @param GCPhysFault The GC physical address corresponding to pvFault.
* @param pvUser Pointer to the MMIO range entry.
*/
IOMDECL(int) IOMMMIOHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser);
/**
* Gets the I/O port range for the specified I/O port in the current context.
*
* @returns Pointer to I/O port range.
* @returns NULL if no port registered.
*
* @param pIOM IOM instance data.
* @param Port Port to lookup.
*/
inline CTXALLSUFF(PIOMIOPORTRANGE) iomIOPortGetRange(PIOM pIOM, RTIOPORT Port)
{
CTXALLSUFF(PIOMIOPORTRANGE) pRange = (CTXALLSUFF(PIOMIOPORTRANGE))RTAvlroIOPortRangeGet(&pIOM->CTXSUFF(pTrees)->CTXALLSUFF(IOPortTree), Port);
return pRange;
}
/**
* Gets the I/O port range for the specified I/O port in the HC.
*
* @returns Pointer to I/O port range.
* @returns NULL if no port registered.
*
* @param pIOM IOM instance data.
* @param Port Port to lookup.
*/
inline PIOMIOPORTRANGER3 iomIOPortGetRangeHC(PIOM pIOM, RTIOPORT Port)
{
PIOMIOPORTRANGER3 pRange = (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pIOM->CTXSUFF(pTrees)->IOPortTreeR3, Port);
return pRange;
}
/**
* Gets the MMIO range for the specified physical address in the current context.
*
* @returns Pointer to MMIO range.
* @returns NULL if address not in a MMIO range.
*
* @param pIOM IOM instance data.
* @param GCPhys Physical address to lookup.
*/
inline CTXALLSUFF(PIOMMMIORANGE) iomMMIOGetRange(PIOM pIOM, RTGCPHYS GCPhys)
{
CTXALLSUFF(PIOMMMIORANGE) pRange = (CTXALLSUFF(PIOMMMIORANGE))RTAvlroGCPhysRangeGet(&pIOM->CTXSUFF(pTrees)->CTXALLSUFF(MMIOTree), GCPhys);
return pRange;
}
/**
* Gets the MMIO range for the specified physical address in the current context.
*
* @returns Pointer to MMIO range.
* @returns NULL if address not in a MMIO range.
*
* @param pIOM IOM instance data.
* @param GCPhys Physical address to lookup.
*/
inline PIOMMMIORANGER3 iomMMIOGetRangeHC(PIOM pIOM, RTGCPHYS GCPhys)
{
PIOMMMIORANGER3 pRange = (PIOMMMIORANGER3)RTAvlroGCPhysRangeGet(&pIOM->CTXSUFF(pTrees)->MMIOTreeR3, GCPhys);
return pRange;
}
#ifdef VBOX_WITH_STATISTICS
/**
* Gets the MMIO statistics record.
* @returns Pointer to MMIO stats.
* @returns NULL if not found.
*
* @param pIOM IOM instance data.
* @param GCPhys Physical address to lookup.
*/
inline PIOMMMIOSTATS iomMMIOGetStats(PIOM pIOM, RTGCPHYS GCPhys)
{
PIOMMMIOSTATS pStats = (PIOMMMIOSTATS)RTAvloGCPhysGet(&pIOM->CTXSUFF(pTrees)->MMIOStatTree, GCPhys);
return pStats;
}
#endif
__END_DECLS
#ifdef IN_RING3
#endif
/** @} */
#endif /* __IOMInternal_h__ */