IOMInline.h revision d2c6b2e8826a5ef34170fef0c72c3fc7c5c1b46a
d2ec54f7875f7e05edd56195adbeb593c947763fphitran/* $Id$ */
d2ec54f7875f7e05edd56195adbeb593c947763fphitran/** @file
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * IOM - Inlined functions.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran */
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran/*
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * Copyright (C) 2006-2011 Oracle Corporation
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * This file is part of VirtualBox Open Source Edition (OSE), as
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * available from http://www.virtualbox.org. This file is free software;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * you can redistribute it and/or modify it under the terms of the GNU
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * General Public License (GPL) as published by the Free Software
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * Foundation, in version 2 as it comes in the "COPYING" file of the
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran */
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#ifndef ___IOMInline_h
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#define ___IOMInline_h
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran/** @addtogroup grp_iom_int Internals
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @internal
2d6b5ea734bb47d251c82670646fde46af15fd69Guoli Shu * @{
d2ec54f7875f7e05edd56195adbeb593c947763fphitran */
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
28b6fd27d5ff75fe6fdeb119a21575b0652a7e70Hans Rosenfeld/**
28b6fd27d5ff75fe6fdeb119a21575b0652a7e70Hans Rosenfeld * Gets the I/O port range for the specified I/O port in the current context.
28b6fd27d5ff75fe6fdeb119a21575b0652a7e70Hans Rosenfeld *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @returns Pointer to I/O port range.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @returns NULL if no port registered.
2d6b5ea734bb47d251c82670646fde46af15fd69Guoli Shu *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @param pVM The VM handle.
2d6b5ea734bb47d251c82670646fde46af15fd69Guoli Shu * @param Port The I/O port lookup.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran */
d2ec54f7875f7e05edd56195adbeb593c947763fphitranDECLINLINE(CTX_SUFF(PIOMIOPORTRANGE)) iomIOPortGetRange(PVM pVM, RTIOPORT Port)
d2ec54f7875f7e05edd56195adbeb593c947763fphitran{
d2ec54f7875f7e05edd56195adbeb593c947763fphitran Assert(PDMCritSectIsOwner(&pVM->iom.s.CritSect));
d2ec54f7875f7e05edd56195adbeb593c947763fphitran return (CTX_SUFF(PIOMIOPORTRANGE))RTAvlroIOPortRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->CTX_SUFF(IOPortTree), Port);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran}
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran/**
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * Gets the I/O port range for the specified I/O port in the HC.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @returns Pointer to I/O port range.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @returns NULL if no port registered.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @param pVM The VM handle.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @param Port The I/O port to lookup.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran */
d2ec54f7875f7e05edd56195adbeb593c947763fphitranDECLINLINE(PIOMIOPORTRANGER3) iomIOPortGetRangeR3(PVM pVM, RTIOPORT Port)
d2ec54f7875f7e05edd56195adbeb593c947763fphitran{
d2ec54f7875f7e05edd56195adbeb593c947763fphitran Assert(PDMCritSectIsOwner(&pVM->iom.s.CritSect));
d2ec54f7875f7e05edd56195adbeb593c947763fphitran return (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortTreeR3, Port);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran}
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran/**
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * Gets the MMIO range for the specified physical address in the current context.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @returns Pointer to MMIO range.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @returns NULL if address not in a MMIO range.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @param pVM The VM handle.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @param GCPhys Physical address to lookup.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran */
d2ec54f7875f7e05edd56195adbeb593c947763fphitranDECLINLINE(PIOMMMIORANGE) iomMmioGetRange(PVM pVM, RTGCPHYS GCPhys)
d2ec54f7875f7e05edd56195adbeb593c947763fphitran{
d2ec54f7875f7e05edd56195adbeb593c947763fphitran Assert(PDMCritSectIsOwner(&pVM->iom.s.CritSect));
d2ec54f7875f7e05edd56195adbeb593c947763fphitran PIOMMMIORANGE pRange = pVM->iom.s.CTX_SUFF(pMMIORangeLast);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran if ( !pRange
d2ec54f7875f7e05edd56195adbeb593c947763fphitran || GCPhys - pRange->GCPhys >= pRange->cb)
d2ec54f7875f7e05edd56195adbeb593c947763fphitran pVM->iom.s.CTX_SUFF(pMMIORangeLast) = pRange
d2ec54f7875f7e05edd56195adbeb593c947763fphitran = (PIOMMMIORANGE)RTAvlroGCPhysRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->MMIOTree, GCPhys);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran return pRange;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran}
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran/**
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * Retain a MMIO range.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @param pRange The range to release.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran */
d2ec54f7875f7e05edd56195adbeb593c947763fphitranDECLINLINE(void) iomMmioRetainRange(PIOMMMIORANGE pRange)
d2ec54f7875f7e05edd56195adbeb593c947763fphitran{
d2ec54f7875f7e05edd56195adbeb593c947763fphitran uint32_t cRefs = ASMAtomicIncU32(&pRange->cRefs);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran Assert(cRefs > 1);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran Assert(cRefs < _1M);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran NOREF(cRefs);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran}
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran/**
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * Gets the referenced MMIO range for the specified physical address in the
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * current context.
28b6fd27d5ff75fe6fdeb119a21575b0652a7e70Hans Rosenfeld *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @returns Pointer to MMIO range.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @returns NULL if address not in a MMIO range.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @param pVM The VM handle.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @param GCPhys Physical address to lookup.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran */
d2ec54f7875f7e05edd56195adbeb593c947763fphitranDECLINLINE(PIOMMMIORANGE) iomMmioGetRangeWithRef(PVM pVM, RTGCPHYS GCPhys)
d2ec54f7875f7e05edd56195adbeb593c947763fphitran{
d2ec54f7875f7e05edd56195adbeb593c947763fphitran int rc = PDMCritSectEnter(&pVM->iom.s.CritSect, VINF_SUCCESS);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran AssertRCReturn(rc, NULL);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran PIOMMMIORANGE pRange = pVM->iom.s.CTX_SUFF(pMMIORangeLast);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran if ( !pRange
d2ec54f7875f7e05edd56195adbeb593c947763fphitran || GCPhys - pRange->GCPhys >= pRange->cb)
d2ec54f7875f7e05edd56195adbeb593c947763fphitran pVM->iom.s.CTX_SUFF(pMMIORangeLast) = pRange
d2ec54f7875f7e05edd56195adbeb593c947763fphitran = (PIOMMMIORANGE)RTAvlroGCPhysRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->MMIOTree, GCPhys);
630ff0785eaea8913473d6696818bd2b9e84756aphitran if (pRange)
d2ec54f7875f7e05edd56195adbeb593c947763fphitran iomMmioRetainRange(pRange);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran PDMCritSectLeave(&pVM->iom.s.CritSect);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran return pRange;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran}
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran/**
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * Releases a MMIO range.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @param pVM The VM handle.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @param pRange The range to release.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran */
d2ec54f7875f7e05edd56195adbeb593c947763fphitranDECLINLINE(void) iomMmioReleaseRange(PVM pVM, PIOMMMIORANGE pRange)
d2ec54f7875f7e05edd56195adbeb593c947763fphitran{
d2ec54f7875f7e05edd56195adbeb593c947763fphitran uint32_t cRefs = ASMAtomicDecU32(&pRange->cRefs);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran if (!cRefs)
d2ec54f7875f7e05edd56195adbeb593c947763fphitran iomMmioFreeRange(pVM, pRange);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran}
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#ifdef VBOX_STRICT
d2ec54f7875f7e05edd56195adbeb593c947763fphitran/**
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * Gets the MMIO range for the specified physical address in the current context.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @returns Pointer to MMIO range.
630ff0785eaea8913473d6696818bd2b9e84756aphitran * @returns NULL if address not in a MMIO range.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @param pVM The VM handle.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @param GCPhys Physical address to lookup.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran */
d2ec54f7875f7e05edd56195adbeb593c947763fphitranDECLINLINE(PIOMMMIORANGE) iomMMIOGetRangeUnsafe(PVM pVM, RTGCPHYS GCPhys)
d2ec54f7875f7e05edd56195adbeb593c947763fphitran{
d2ec54f7875f7e05edd56195adbeb593c947763fphitran PIOMMMIORANGE pRange = pVM->iom.s.CTX_SUFF(pMMIORangeLast);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran if ( !pRange
d2ec54f7875f7e05edd56195adbeb593c947763fphitran || GCPhys - pRange->GCPhys >= pRange->cb)
d2ec54f7875f7e05edd56195adbeb593c947763fphitran pVM->iom.s.CTX_SUFF(pMMIORangeLast) = pRange
d2ec54f7875f7e05edd56195adbeb593c947763fphitran = (PIOMMMIORANGE)RTAvlroGCPhysRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->MMIOTree, GCPhys);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran return pRange;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran}
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#endif /* VBOX_STRICT */
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#ifdef VBOX_WITH_STATISTICS
d2ec54f7875f7e05edd56195adbeb593c947763fphitran/**
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * Gets the MMIO statistics record.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * In ring-3 this will lazily create missing records, while in GC/R0 the caller has to
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * return the appropriate status to defer the operation to ring-3.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @returns Pointer to MMIO stats.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @returns NULL if not found (R0/GC), or out of memory (R3).
d2ec54f7875f7e05edd56195adbeb593c947763fphitran *
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @param pVM The VM handle.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @param GCPhys Physical address to lookup.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran * @param pRange The MMIO range.
d2ec54f7875f7e05edd56195adbeb593c947763fphitran */
d2ec54f7875f7e05edd56195adbeb593c947763fphitranDECLINLINE(PIOMMMIOSTATS) iomMmioGetStats(PVM pVM, RTGCPHYS GCPhys, PIOMMMIORANGE pRange)
d2ec54f7875f7e05edd56195adbeb593c947763fphitran{
d2ec54f7875f7e05edd56195adbeb593c947763fphitran PDMCritSectEnter(&pVM->iom.s.CritSect, VINF_SUCCESS);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran /* For large ranges, we'll put everything on the first byte. */
d2ec54f7875f7e05edd56195adbeb593c947763fphitran if (pRange->cb > PAGE_SIZE)
d2ec54f7875f7e05edd56195adbeb593c947763fphitran GCPhys = pRange->GCPhys;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran PIOMMMIOSTATS pStats = pVM->iom.s.CTX_SUFF(pMMIOStatsLast);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran if ( !pStats
d2ec54f7875f7e05edd56195adbeb593c947763fphitran || pStats->Core.Key != GCPhys)
d2ec54f7875f7e05edd56195adbeb593c947763fphitran {
d2ec54f7875f7e05edd56195adbeb593c947763fphitran pStats = (PIOMMMIOSTATS)RTAvloGCPhysGet(&pVM->iom.s.CTX_SUFF(pTrees)->MmioStatTree, GCPhys);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran# ifdef IN_RING3
d2ec54f7875f7e05edd56195adbeb593c947763fphitran if (!pStats)
d2ec54f7875f7e05edd56195adbeb593c947763fphitran pStats = iomR3MMIOStatsCreate(pVM, GCPhys, pRange->pszDesc);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran# endif
d2ec54f7875f7e05edd56195adbeb593c947763fphitran }
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran PDMCritSectLeave(&pVM->iom.s.CritSect);
d2ec54f7875f7e05edd56195adbeb593c947763fphitran return pStats;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran}
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#endif /* VBOX_WITH_STATISTICS */
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran/** @} */
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran#endif
d2ec54f7875f7e05edd56195adbeb593c947763fphitran
d2ec54f7875f7e05edd56195adbeb593c947763fphitran