VirtualBox

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

Last change on this file since 107044 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.8 KB
Line 
1/* $Id: IOMInline.h 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * IOM - Inlined functions.
4 */
5
6/*
7 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#ifndef VMM_INCLUDED_SRC_include_IOMInline_h
29#define VMM_INCLUDED_SRC_include_IOMInline_h
30#ifndef RT_WITHOUT_PRAGMA_ONCE
31# pragma once
32#endif
33
34#include <iprt/errcore.h>
35
36/** @addtogroup grp_iom_int Internals
37 * @internal
38 * @{
39 */
40
41
42/**
43 * Gets the I/O port entry for the specified I/O port in the current context.
44 *
45 * @returns Pointer to I/O port entry.
46 * @returns NULL if no port registered.
47 *
48 * @param pVM The cross context VM structure.
49 * @param uPort The I/O port to lookup.
50 * @param poffPort Where to return the port offset relative to the
51 * start of the I/O port range.
52 * @param pidxLastHint Pointer to IOMCPU::idxIoPortLastRead or
53 * IOMCPU::idxIoPortLastWrite.
54 *
55 * @note In ring-0 it is possible to get an uninitialized entry (pDevIns is
56 * NULL, cPorts is 0), in which case there should be ring-3 handlers
57 * for the entry. Use IOMIOPORTENTRYR0::idxSelf to get the ring-3
58 * entry.
59 *
60 * @note This code is almost identical to iomMmioGetEntry, so keep in sync.
61 */
62DECLINLINE(CTX_SUFF(PIOMIOPORTENTRY)) iomIoPortGetEntry(PVMCC pVM, RTIOPORT uPort, PRTIOPORT poffPort, uint16_t *pidxLastHint)
63{
64 Assert(IOM_IS_SHARED_LOCK_OWNER(pVM));
65
66#ifdef IN_RING0
67 uint32_t iEnd = RT_MIN(pVM->iom.s.cIoPortLookupEntries, pVM->iomr0.s.cIoPortAlloc);
68 PCIOMIOPORTLOOKUPENTRY paLookup = pVM->iomr0.s.paIoPortLookup;
69#else
70 uint32_t iEnd = pVM->iom.s.cIoPortLookupEntries;
71 PCIOMIOPORTLOOKUPENTRY paLookup = pVM->iom.s.paIoPortLookup;
72#endif
73 if (iEnd > 0)
74 {
75 uint32_t iFirst = 0;
76 uint32_t i = *pidxLastHint;
77 if (i < iEnd)
78 { /* likely */ }
79 else
80 i = iEnd / 2;
81 for (;;)
82 {
83 PCIOMIOPORTLOOKUPENTRY pCur = &paLookup[i];
84 if (pCur->uFirstPort > uPort)
85 {
86 if (i > iFirst)
87 iEnd = i;
88 else
89 break;
90 }
91 else if (pCur->uLastPort < uPort)
92 {
93 i += 1;
94 if (i < iEnd)
95 iFirst = i;
96 else
97 break;
98 }
99 else
100 {
101 *pidxLastHint = (uint16_t)i;
102 *poffPort = uPort - pCur->uFirstPort;
103
104 /*
105 * Translate the 'idx' member into a pointer.
106 */
107 size_t const idx = pCur->idx;
108#ifdef IN_RING0
109 AssertMsg(idx < pVM->iom.s.cIoPortRegs && idx < pVM->iomr0.s.cIoPortAlloc,
110 ("%#zx vs %#x/%x (port %#x)\n", idx, pVM->iom.s.cIoPortRegs, pVM->iomr0.s.cIoPortMax, uPort));
111 if (idx < pVM->iomr0.s.cIoPortAlloc)
112 return &pVM->iomr0.s.paIoPortRegs[idx];
113#else
114 if (idx < pVM->iom.s.cIoPortRegs)
115 return &pVM->iom.s.paIoPortRegs[idx];
116 AssertMsgFailed(("%#zx vs %#x (port %#x)\n", idx, pVM->iom.s.cIoPortRegs, uPort));
117#endif
118 break;
119 }
120
121 i = iFirst + (iEnd - iFirst) / 2;
122 }
123 }
124 *poffPort = 0;
125 return NULL;
126}
127
128
129#ifdef VBOX_WITH_STATISTICS
130/**
131 * Gets the statistics entry for an I/O port.
132 *
133 * @returns Pointer to stats. Instead of NULL, a pointer to IoPortDummyStats is
134 * returned, so the caller does not need to check for NULL.
135 *
136 * @param pVM The cross context VM structure.
137 * @param pRegEntry The I/O port entry to get stats for.
138 * @param offPort The offset of the port relative to the start of the
139 * registration entry.
140 */
141DECLINLINE(PIOMIOPORTSTATSENTRY) iomIoPortGetStats(PVMCC pVM, CTX_SUFF(PIOMIOPORTENTRY) pRegEntry, uint16_t offPort)
142{
143 size_t idxStats = pRegEntry->idxStats;
144 idxStats += offPort;
145# ifdef IN_RING0
146 if (idxStats < pVM->iomr0.s.cIoPortStatsAllocation)
147 return &pVM->iomr0.s.paIoPortStats[idxStats];
148# else
149 if (idxStats < pVM->iom.s.cIoPortStats)
150 return &pVM->iom.s.paIoPortStats[idxStats];
151# endif
152 return &pVM->iom.s.IoPortDummyStats;
153}
154#endif
155
156
157/**
158 * Gets the MMIO region entry for the specified address in the current context.
159 *
160 * @returns Pointer to MMIO region entry.
161 * @returns NULL if no MMIO region registered for the given address.
162 *
163 * @param pVM The cross context VM structure.
164 * @param GCPhys The address to lookup.
165 * @param poffRegion Where to return the byte offset into the MMIO
166 * region that corresponds to @a GCPhys.
167 * @param pidxLastHint Pointer to IOMCPU::idxMmioLastRead,
168 * IOMCPU::idxMmioLastWrite, or similar.
169 *
170 * @note In ring-0 it is possible to get an uninitialized entry (pDevIns is
171 * NULL, cbRegion is 0), in which case there should be ring-3 handlers
172 * for the entry. Use IOMMMIOENTRYR0::idxSelf to get the ring-3 entry.
173 *
174 * @note This code is almost identical to iomIoPortGetEntry, so keep in sync.
175 */
176DECLINLINE(CTX_SUFF(PIOMMMIOENTRY)) iomMmioGetEntry(PVMCC pVM, RTGCPHYS GCPhys, PRTGCPHYS poffRegion, uint16_t *pidxLastHint)
177{
178 Assert(IOM_IS_SHARED_LOCK_OWNER(pVM));
179
180#ifdef IN_RING0
181 uint32_t iEnd = RT_MIN(pVM->iom.s.cMmioLookupEntries, pVM->iomr0.s.cMmioAlloc);
182 PCIOMMMIOLOOKUPENTRY paLookup = pVM->iomr0.s.paMmioLookup;
183#else
184 uint32_t iEnd = pVM->iom.s.cMmioLookupEntries;
185 PCIOMMMIOLOOKUPENTRY paLookup = pVM->iom.s.paMmioLookup;
186#endif
187 if (iEnd > 0)
188 {
189 uint32_t iFirst = 0;
190 uint32_t i = *pidxLastHint;
191 if (i < iEnd)
192 { /* likely */ }
193 else
194 i = iEnd / 2;
195 for (;;)
196 {
197 PCIOMMMIOLOOKUPENTRY pCur = &paLookup[i];
198 if (pCur->GCPhysFirst > GCPhys)
199 {
200 if (i > iFirst)
201 iEnd = i;
202 else
203 break;
204 }
205 else if (pCur->GCPhysLast < GCPhys)
206 {
207 i += 1;
208 if (i < iEnd)
209 iFirst = i;
210 else
211 break;
212 }
213 else
214 {
215 *pidxLastHint = (uint16_t)i;
216 *poffRegion = GCPhys - pCur->GCPhysFirst;
217
218 /*
219 * Translate the 'idx' member into a pointer.
220 */
221 size_t const idx = pCur->idx;
222#ifdef IN_RING0
223 AssertMsg(idx < pVM->iom.s.cMmioRegs && idx < pVM->iomr0.s.cMmioAlloc,
224 ("%#zx vs %#x/%x (GCPhys=%RGp)\n", idx, pVM->iom.s.cMmioRegs, pVM->iomr0.s.cMmioMax, GCPhys));
225 if (idx < pVM->iomr0.s.cMmioAlloc)
226 return &pVM->iomr0.s.paMmioRegs[idx];
227#else
228 if (idx < pVM->iom.s.cMmioRegs)
229 return &pVM->iom.s.paMmioRegs[idx];
230 AssertMsgFailed(("%#zx vs %#x (GCPhys=%RGp)\n", idx, pVM->iom.s.cMmioRegs, GCPhys));
231#endif
232 break;
233 }
234
235 i = iFirst + (iEnd - iFirst) / 2;
236 }
237 }
238 *poffRegion = 0;
239 return NULL;
240}
241
242
243#ifdef VBOX_WITH_STATISTICS
244/**
245 * Gets the statistics entry for an MMIO region.
246 *
247 * @returns Pointer to stats. Instead of NULL, a pointer to MmioDummyStats is
248 * returned, so the caller does not need to check for NULL.
249 *
250 * @param pVM The cross context VM structure.
251 * @param pRegEntry The I/O port entry to get stats for.
252 */
253DECLINLINE(PIOMMMIOSTATSENTRY) iomMmioGetStats(PVMCC pVM, CTX_SUFF(PIOMMMIOENTRY) pRegEntry)
254{
255 size_t idxStats = pRegEntry->idxStats;
256# ifdef IN_RING0
257 if (idxStats < pVM->iomr0.s.cMmioStatsAllocation)
258 return &pVM->iomr0.s.paMmioStats[idxStats];
259# else
260 if (idxStats < pVM->iom.s.cMmioStats)
261 return &pVM->iom.s.paMmioStats[idxStats];
262# endif
263 return &pVM->iom.s.MmioDummyStats;
264}
265#endif
266
267/** @} */
268
269#endif /* !VMM_INCLUDED_SRC_include_IOMInline_h */
270
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