VirtualBox

source: vbox/trunk/src/VBox/VMM/include/IOMInline.h@ 47786

Last change on this file since 47786 was 45311, checked in by vboxsync, 11 years ago

IOM: Prepared for using read/write locking, still using the old exclusive stuff though. Found and fixed an REM/IOM lock order issue.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.3 KB
Line 
1/* $Id: IOMInline.h 45311 2013-04-03 14:55:30Z vboxsync $ */
2/** @file
3 * IOM - Inlined functions.
4 */
5
6/*
7 * Copyright (C) 2006-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifndef ___IOMInline_h
19#define ___IOMInline_h
20
21/** @addtogroup grp_iom_int Internals
22 * @internal
23 * @{
24 */
25
26/**
27 * Gets the I/O port range for the specified I/O port in the current context.
28 *
29 * @returns Pointer to I/O port range.
30 * @returns NULL if no port registered.
31 *
32 * @param pVM Pointer to the VM.
33 * @param Port The I/O port lookup.
34 */
35DECLINLINE(CTX_SUFF(PIOMIOPORTRANGE)) iomIOPortGetRange(PVM pVM, RTIOPORT Port)
36{
37 Assert(IOM_IS_SHARED_LOCK_OWNER(pVM));
38 return (CTX_SUFF(PIOMIOPORTRANGE))RTAvlroIOPortRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->CTX_SUFF(IOPortTree), Port);
39}
40
41
42/**
43 * Gets the I/O port range for the specified I/O port in the HC.
44 *
45 * @returns Pointer to I/O port range.
46 * @returns NULL if no port registered.
47 *
48 * @param pVM Pointer to the VM.
49 * @param Port The I/O port to lookup.
50 */
51DECLINLINE(PIOMIOPORTRANGER3) iomIOPortGetRangeR3(PVM pVM, RTIOPORT Port)
52{
53 Assert(IOM_IS_SHARED_LOCK_OWNER(pVM));
54 return (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortTreeR3, Port);
55}
56
57
58/**
59 * Gets the MMIO range for the specified physical address in the current context.
60 *
61 * @returns Pointer to MMIO range.
62 * @returns NULL if address not in a MMIO range.
63 *
64 * @param pVM Pointer to the VM.
65 * @param pVCpu Pointer to the virtual CPU structure of the caller.
66 * @param GCPhys Physical address to lookup.
67 */
68DECLINLINE(PIOMMMIORANGE) iomMmioGetRange(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys)
69{
70 Assert(IOM_IS_SHARED_LOCK_OWNER(pVM));
71 PIOMMMIORANGE pRange = pVCpu->iom.s.CTX_SUFF(pMMIORangeLast);
72 if ( !pRange
73 || GCPhys - pRange->GCPhys >= pRange->cb)
74 pVCpu->iom.s.CTX_SUFF(pMMIORangeLast) = pRange
75 = (PIOMMMIORANGE)RTAvlroGCPhysRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->MMIOTree, GCPhys);
76 return pRange;
77}
78
79/**
80 * Retain a MMIO range.
81 *
82 * @param pRange The range to release.
83 */
84DECLINLINE(void) iomMmioRetainRange(PIOMMMIORANGE pRange)
85{
86 uint32_t cRefs = ASMAtomicIncU32(&pRange->cRefs);
87 Assert(cRefs > 1);
88 Assert(cRefs < _1M);
89 NOREF(cRefs);
90}
91
92
93/**
94 * Gets the referenced MMIO range for the specified physical address in the
95 * current context.
96 *
97 * @returns Pointer to MMIO range.
98 * @returns NULL if address not in a MMIO range.
99 *
100 * @param pVM Pointer to the VM.
101 * @param pVCpu Pointer to the virtual CPU structure of the caller.
102 * @param GCPhys Physical address to lookup.
103 */
104DECLINLINE(PIOMMMIORANGE) iomMmioGetRangeWithRef(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys)
105{
106 int rc = IOM_LOCK_SHARED_EX(pVM, VINF_SUCCESS);
107 AssertRCReturn(rc, NULL);
108
109 PIOMMMIORANGE pRange = pVCpu->iom.s.CTX_SUFF(pMMIORangeLast);
110 if ( !pRange
111 || GCPhys - pRange->GCPhys >= pRange->cb)
112 pVCpu->iom.s.CTX_SUFF(pMMIORangeLast) = pRange
113 = (PIOMMMIORANGE)RTAvlroGCPhysRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->MMIOTree, GCPhys);
114 if (pRange)
115 iomMmioRetainRange(pRange);
116
117 IOM_UNLOCK_SHARED(pVM);
118 return pRange;
119}
120
121
122/**
123 * Releases a MMIO range.
124 *
125 * @param pVM Pointer to the VM.
126 * @param pRange The range to release.
127 */
128DECLINLINE(void) iomMmioReleaseRange(PVM pVM, PIOMMMIORANGE pRange)
129{
130 uint32_t cRefs = ASMAtomicDecU32(&pRange->cRefs);
131 if (!cRefs)
132 iomMmioFreeRange(pVM, pRange);
133}
134
135
136#ifdef VBOX_STRICT
137/**
138 * Gets the MMIO range for the specified physical address in the current context.
139 *
140 * @returns Pointer to MMIO range.
141 * @returns NULL if address not in a MMIO range.
142 *
143 * @param pVM Pointer to the VM.
144 * @param pVCpu Pointer to the virtual CPU structure of the caller.
145 * @param GCPhys Physical address to lookup.
146 */
147DECLINLINE(PIOMMMIORANGE) iomMMIOGetRangeUnsafe(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys)
148{
149 PIOMMMIORANGE pRange = pVCpu->iom.s.CTX_SUFF(pMMIORangeLast);
150 if ( !pRange
151 || GCPhys - pRange->GCPhys >= pRange->cb)
152 pVCpu->iom.s.CTX_SUFF(pMMIORangeLast) = pRange
153 = (PIOMMMIORANGE)RTAvlroGCPhysRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->MMIOTree, GCPhys);
154 return pRange;
155}
156#endif /* VBOX_STRICT */
157
158
159#ifdef VBOX_WITH_STATISTICS
160/**
161 * Gets the MMIO statistics record.
162 *
163 * In ring-3 this will lazily create missing records, while in GC/R0 the caller has to
164 * return the appropriate status to defer the operation to ring-3.
165 *
166 * @returns Pointer to MMIO stats.
167 * @returns NULL if not found (R0/GC), or out of memory (R3).
168 *
169 * @param pVM Pointer to the VM.
170 * @param pVCpu Pointer to the virtual CPU structure of the caller.
171 * @param GCPhys Physical address to lookup.
172 * @param pRange The MMIO range.
173 *
174 * @remarks The caller holds the IOM critical section with shared access prior
175 * to calling this method. Upon return, the lock has been released!
176 * This is ugly, but it's a necessary evil since we cannot upgrade read
177 * locks to write locks and the whole purpose here is calling
178 * iomR3MMIOStatsCreate.
179 */
180DECLINLINE(PIOMMMIOSTATS) iomMmioGetStats(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, PIOMMMIORANGE pRange)
181{
182 Assert(IOM_IS_SHARED_LOCK_OWNER(pVM));
183
184 /* For large ranges, we'll put everything on the first byte. */
185 if (pRange->cb > PAGE_SIZE)
186 GCPhys = pRange->GCPhys;
187
188 PIOMMMIOSTATS pStats = pVCpu->iom.s.CTX_SUFF(pMMIOStatsLast);
189 if ( !pStats
190 || pStats->Core.Key != GCPhys)
191 {
192 pStats = (PIOMMMIOSTATS)RTAvloGCPhysGet(&pVM->iom.s.CTX_SUFF(pTrees)->MmioStatTree, GCPhys);
193# ifdef IN_RING3
194 if (!pStats)
195 {
196 IOM_UNLOCK_SHARED(pVM);
197 return iomR3MMIOStatsCreate(pVM, GCPhys, pRange->pszDesc);
198 }
199# endif
200 }
201
202 IOM_UNLOCK_SHARED(pVM);
203 return pStats;
204}
205#endif /* VBOX_WITH_STATISTICS */
206
207
208/** @} */
209
210#endif
211
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette