VirtualBox

source: vbox/trunk/src/VBox/VMM/IOMInternal.h@ 7796

Last change on this file since 7796 was 7751, checked in by vboxsync, 17 years ago

Simplified and cleaned up the MMIO code.

  • The R0 and GC MMIO range records have been merged into the R3 one.
  • Added caching of the last MMIO range and stats record like we're doing for the I/O port ranges.

TODO:

  • Drop the pszDesc parameter of the GC/R0 registration functions.
  • Do the same cleanup to the I/O port code.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 18.3 KB
Line 
1/* $Id: IOMInternal.h 7751 2008-04-04 17:10:17Z vboxsync $ */
2/** @file
3 * IOM - Internal header file.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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 ___IOMInternal_h
19#define ___IOMInternal_h
20
21#include <VBox/cdefs.h>
22#include <VBox/types.h>
23#include <VBox/iom.h>
24#include <VBox/stam.h>
25#include <VBox/pgm.h>
26#include <VBox/param.h>
27#include <iprt/avl.h>
28
29#if !defined(IN_IOM_R3) && !defined(IN_IOM_R0) && !defined(IN_IOM_GC)
30# error "Not in IOM! This is an internal header!"
31#endif
32
33
34/** @defgroup grp_iom_int Internals
35 * @ingroup grp_iom
36 * @internal
37 * @{
38 */
39
40/**
41 * MMIO range descriptor.
42 */
43typedef struct IOMMMIORANGE
44{
45 /** Avl node core with GCPhys as Key and GCPhys + cbSize - 1 as KeyLast. */
46 AVLROGCPHYSNODECORE Core;
47 /** Start physical address. */
48 RTGCPHYS GCPhys;
49 /** Size of the range. */
50 uint32_t cb;
51 uint32_t u32Alignment; /**< Alignment padding. */
52
53 /** Pointer to user argument. */
54 RTR3PTR pvUserR3;
55 /** Pointer to device instance. */
56 PPDMDEVINSR3 pDevInsR3;
57 /** Pointer to write callback function. */
58 R3PTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallbackR3;
59 /** Pointer to read callback function. */
60 R3PTRTYPE(PFNIOMMMIOREAD) pfnReadCallbackR3;
61 /** Pointer to fill (memset) callback function. */
62 R3PTRTYPE(PFNIOMMMIOFILL) pfnFillCallbackR3;
63
64 /** Pointer to user argument. */
65 RTR0PTR pvUserR0;
66 /** Pointer to device instance. */
67 PPDMDEVINSR0 pDevInsR0;
68 /** Pointer to write callback function. */
69 R0PTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallbackR0;
70 /** Pointer to read callback function. */
71 R0PTRTYPE(PFNIOMMMIOREAD) pfnReadCallbackR0;
72 /** Pointer to fill (memset) callback function. */
73 R0PTRTYPE(PFNIOMMMIOFILL) pfnFillCallbackR0;
74
75 /** Pointer to user argument. */
76 RTGCPTR pvUserGC;
77 /** Pointer to device instance. */
78 PPDMDEVINSGC pDevInsGC;
79 /** Pointer to write callback function. */
80 GCPTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallbackGC;
81 /** Pointer to read callback function. */
82 GCPTRTYPE(PFNIOMMMIOREAD) pfnReadCallbackGC;
83 /** Pointer to fill (memset) callback function. */
84 GCPTRTYPE(PFNIOMMMIOFILL) pfnFillCallbackGC;
85 RTGCPTR GCPtrAlignment; /**< Alignment padding */
86
87 /** Description / Name. For easing debugging. */
88 R3PTRTYPE(const char *) pszDesc;
89} IOMMMIORANGE;
90/** Pointer to a MMIO range descriptor, R3 version. */
91typedef struct IOMMMIORANGE *PIOMMMIORANGE;
92
93
94/**
95 * MMIO address statistics. (one address)
96 *
97 * This is a simple way of making on demand statistics, however it's a
98 * bit free with the hypervisor heap memory..
99 */
100typedef struct IOMMMIOSTATS
101{
102 /** Avl node core with the address as Key. */
103 AVLOGCPHYSNODECORE Core;
104 /** Number of reads to this address from R3. */
105 STAMCOUNTER ReadR3;
106 /** Number of writes to this address from R3. */
107 STAMCOUNTER WriteR3;
108 /** Number of reads to this address from R0. */
109 STAMCOUNTER ReadR0;
110 /** Number of writes to this address from R0. */
111 STAMCOUNTER WriteR0;
112 /** Number of reads to this address from GC. */
113 STAMCOUNTER ReadGC;
114 /** Number of writes to this address from GC. */
115 STAMCOUNTER WriteGC;
116 /** Profiling read handler overhead in R3. */
117 STAMPROFILEADV ProfReadR3;
118 /** Profiling write handler overhead in R3. */
119 STAMPROFILEADV ProfWriteR3;
120 /** Profiling read handler overhead in R0. */
121 STAMPROFILEADV ProfReadR0;
122 /** Profiling write handler overhead in R0. */
123 STAMPROFILEADV ProfWriteR0;
124 /** Profiling read handler overhead in GC. */
125 STAMPROFILEADV ProfReadGC;
126 /** Profiling write handler overhead in GC. */
127 STAMPROFILEADV ProfWriteGC;
128 /** Number of reads to this address from R0 which was serviced in R3. */
129 STAMCOUNTER ReadR0ToR3;
130 /** Number of writes to this address from R0 which was serviced in R3. */
131 STAMCOUNTER WriteR0ToR3;
132 /** Number of reads to this address from GC which was serviced in R3. */
133 STAMCOUNTER ReadGCToR3;
134 /** Number of writes to this address from GC which was serviced in R3. */
135 STAMCOUNTER WriteGCToR3;
136} IOMMMIOSTATS;
137/** Pointer to I/O port statistics. */
138typedef IOMMMIOSTATS *PIOMMMIOSTATS;
139
140
141/**
142 * I/O port range descriptor, R3 version.
143 */
144typedef struct IOMIOPORTRANGER3
145{
146 /** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */
147 AVLROIOPORTNODECORE Core;
148#if HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32 && !defined(RT_OS_WINDOWS)
149 uint32_t u32Alignment; /**< The sizeof(Core) differs. */
150#endif
151 /** Start I/O port address. */
152 RTIOPORT Port;
153 /** Size of the range. */
154 uint16_t cPorts;
155 /** Pointer to user argument. */
156 RTR3PTR pvUser;
157 /** Pointer to the associated device instance. */
158 R3PTRTYPE(PPDMDEVINS) pDevIns;
159 /** Pointer to OUT callback function. */
160 R3PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback;
161 /** Pointer to IN callback function. */
162 R3PTRTYPE(PFNIOMIOPORTIN) pfnInCallback;
163 /** Pointer to string OUT callback function. */
164 R3PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;
165 /** Pointer to string IN callback function. */
166 R3PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;
167 /** Description / Name. For easing debugging. */
168 R3PTRTYPE(const char *) pszDesc;
169} IOMIOPORTRANGER3;
170/** Pointer to I/O port range descriptor, R3 version. */
171typedef IOMIOPORTRANGER3 *PIOMIOPORTRANGER3;
172
173/**
174 * I/O port range descriptor, R0 version.
175 */
176typedef struct IOMIOPORTRANGER0
177{
178 /** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */
179 AVLROIOPORTNODECORE Core;
180#if HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32 && !defined(RT_OS_WINDOWS)
181 uint32_t u32Alignment; /**< The sizeof(Core) differs. */
182#endif
183 /** Start I/O port address. */
184 RTIOPORT Port;
185 /** Size of the range. */
186 uint16_t cPorts;
187 /** Pointer to user argument. */
188 RTR0PTR pvUser;
189 /** Pointer to the associated device instance. */
190 R0PTRTYPE(PPDMDEVINS) pDevIns;
191 /** Pointer to OUT callback function. */
192 R0PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback;
193 /** Pointer to IN callback function. */
194 R0PTRTYPE(PFNIOMIOPORTIN) pfnInCallback;
195 /** Pointer to string OUT callback function. */
196 R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;
197 /** Pointer to string IN callback function. */
198 R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;
199 /** Description / Name. For easing debugging. */
200 R3PTRTYPE(const char *) pszDesc;
201} IOMIOPORTRANGER0;
202/** Pointer to I/O port range descriptor, R0 version. */
203typedef IOMIOPORTRANGER0 *PIOMIOPORTRANGER0;
204
205/**
206 * I/O port range descriptor.
207 */
208typedef struct IOMIOPORTRANGEGC
209{
210 /** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */
211 AVLROIOPORTNODECORE Core;
212 /** Start I/O port address. */
213 RTIOPORT Port;
214 /** Size of the range. */
215 uint16_t cPorts;
216 /** Pointer to user argument. */
217 RTGCPTR pvUser;
218 /** Pointer to the associated device instance. */
219 GCPTRTYPE(PPDMDEVINS) pDevIns;
220 /** Pointer to OUT callback function. */
221 GCPTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback;
222 /** Pointer to IN callback function. */
223 GCPTRTYPE(PFNIOMIOPORTIN) pfnInCallback;
224 /** Pointer to string OUT callback function. */
225 GCPTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;
226 /** Pointer to string IN callback function. */
227 GCPTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;
228#if HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32
229 RTGCPTR GCPtrAlignment; /**< pszDesc is 8 byte aligned. */
230#endif
231 /** Description / Name. For easing debugging. */
232 R3PTRTYPE(const char *) pszDesc;
233} IOMIOPORTRANGEGC;
234/** Pointer to I/O port range descriptor, GC version. */
235typedef IOMIOPORTRANGEGC *PIOMIOPORTRANGEGC;
236
237
238/**
239 * I/O port statistics. (one I/O port)
240 *
241 * This is a simple way of making on demand statistics, however it's a
242 * bit free with the hypervisor heap memory..
243 */
244typedef struct IOMIOPORTSTATS
245{
246 /** Avl node core with the port as Key. */
247 AVLOIOPORTNODECORE Core;
248#if HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32 && !defined(RT_OS_WINDOWS)
249 uint32_t u32Alignment; /**< The sizeof(Core) differs. */
250#endif
251 /** Number of INs to this port from R3. */
252 STAMCOUNTER InR3;
253 /** Number of OUTs to this port from R3. */
254 STAMCOUNTER OutR3;
255 /** Number of INs to this port from R0. */
256 STAMCOUNTER InR0;
257 /** Number of OUTs to this port from R0. */
258 STAMCOUNTER OutR0;
259 /** Number of INs to this port from GC. */
260 STAMCOUNTER InGC;
261 /** Number of OUTs to this port from GC. */
262 STAMCOUNTER OutGC;
263 /** Profiling IN handler overhead in R3. */
264 STAMPROFILEADV ProfInR3;
265 /** Profiling OUT handler overhead in R3. */
266 STAMPROFILEADV ProfOutR3;
267 /** Profiling IN handler overhead in R0. */
268 STAMPROFILEADV ProfInR0;
269 /** Profiling OUT handler overhead in R0. */
270 STAMPROFILEADV ProfOutR0;
271 /** Profiling IN handler overhead in GC. */
272 STAMPROFILEADV ProfInGC;
273 /** Profiling OUT handler overhead in GC. */
274 STAMPROFILEADV ProfOutGC;
275 /** Number of INs to this port from R0 which was serviced in R3. */
276 STAMCOUNTER InR0ToR3;
277 /** Number of OUTs to this port from R0 which was serviced in R3. */
278 STAMCOUNTER OutR0ToR3;
279 /** Number of INs to this port from GC which was serviced in R3. */
280 STAMCOUNTER InGCToR3;
281 /** Number of OUTs to this port from GC which was serviced in R3. */
282 STAMCOUNTER OutGCToR3;
283} IOMIOPORTSTATS;
284/** Pointer to I/O port statistics. */
285typedef IOMIOPORTSTATS *PIOMIOPORTSTATS;
286
287
288/**
289 * The IOM trees.
290 * These are offset based the nodes and root must be in the same
291 * memory block in HC. The locations of IOM structure and the hypervisor heap
292 * are quite different in HC and GC.
293 */
294typedef struct IOMTREES
295{
296 /** Tree containing I/O port range descriptors registered for HC (IOMIOPORTRANGEHC). */
297 AVLROIOPORTTREE IOPortTreeR3;
298 /** Tree containing I/O port range descriptors registered for R0 (IOMIOPORTRANGER0). */
299 AVLROIOPORTTREE IOPortTreeR0;
300 /** Tree containing I/O port range descriptors registered for GC (IOMIOPORTRANGEGC). */
301 AVLROIOPORTTREE IOPortTreeGC;
302
303 /** Tree containing the MMIO range descriptors (IOMMMIORANGE). */
304 AVLROGCPHYSTREE MMIOTree;
305
306 /** Tree containing I/O port statistics (IOMIOPORTSTATS). */
307 AVLOIOPORTTREE IOPortStatTree;
308 /** Tree containing MMIO statistics (IOMMMIOSTATS). */
309 AVLOGCPHYSTREE MMIOStatTree;
310} IOMTREES;
311/** Pointer to the IOM trees. */
312typedef IOMTREES *PIOMTREES;
313
314
315/**
316 * Converts an IOM pointer into a VM pointer.
317 * @returns Pointer to the VM structure the PGM is part of.
318 * @param pIOM Pointer to IOM instance data.
319 */
320#define IOM2VM(pIOM) ( (PVM)((char*)pIOM - pIOM->offVM) )
321
322/**
323 * IOM Data (part of VM)
324 */
325typedef struct IOM
326{
327 /** Offset to the VM structure. */
328 RTINT offVM;
329
330 /** Pointer to the trees - GC ptr. */
331 GCPTRTYPE(PIOMTREES) pTreesGC;
332 /** Pointer to the trees - HC ptr. */
333 R3R0PTRTYPE(PIOMTREES) pTreesHC;
334
335 /** The ring-0 address of IOMMMIOHandler. */
336 R0PTRTYPE(PFNPGMR0PHYSHANDLER) pfnMMIOHandlerR0;
337 /** The GC address of IOMMMIOHandler. */
338 GCPTRTYPE(PFNPGMGCPHYSHANDLER) pfnMMIOHandlerGC;
339 RTGCPTR Alignment;
340
341 /** @name Caching of I/O Port and MMIO ranges and statistics.
342 * (Saves quite some time in rep outs/ins instruction emulation.)
343 * @{ */
344 R3PTRTYPE(PIOMIOPORTRANGER3) pRangeLastReadR3;
345 R3PTRTYPE(PIOMIOPORTRANGER3) pRangeLastWriteR3;
346 R3PTRTYPE(PIOMIOPORTSTATS) pStatsLastReadR3;
347 R3PTRTYPE(PIOMIOPORTSTATS) pStatsLastWriteR3;
348 R3PTRTYPE(PIOMMMIORANGE) pMMIORangeLastR3;
349 R3PTRTYPE(PIOMMMIOSTATS) pMMIOStatsLastR3;
350
351 R0PTRTYPE(PIOMIOPORTRANGER0) pRangeLastReadR0;
352 R0PTRTYPE(PIOMIOPORTRANGER0) pRangeLastWriteR0;
353 R0PTRTYPE(PIOMIOPORTSTATS) pStatsLastReadR0;
354 R0PTRTYPE(PIOMIOPORTSTATS) pStatsLastWriteR0;
355 R0PTRTYPE(PIOMMMIORANGE) pMMIORangeLastR0;
356 R0PTRTYPE(PIOMMMIOSTATS) pMMIOStatsLastR0;
357
358 GCPTRTYPE(PIOMIOPORTRANGEGC) pRangeLastReadGC;
359 GCPTRTYPE(PIOMIOPORTRANGEGC) pRangeLastWriteGC;
360 GCPTRTYPE(PIOMIOPORTSTATS) pStatsLastReadGC;
361 GCPTRTYPE(PIOMIOPORTSTATS) pStatsLastWriteGC;
362 GCPTRTYPE(PIOMMMIORANGE) pMMIORangeLastGC;
363 GCPTRTYPE(PIOMMMIOSTATS) pMMIOStatsLastGC;
364 /** @} */
365
366 /** @name I/O Port statistics.
367 * @{ */
368 STAMPROFILE StatGCIOPortHandler;
369
370 STAMCOUNTER StatGCInstIn;
371 STAMCOUNTER StatGCInstOut;
372 STAMCOUNTER StatGCInstIns;
373 STAMCOUNTER StatGCInstOuts;
374 /** @} */
375
376 /** @name MMIO statistics.
377 * @{ */
378 STAMPROFILE StatGCMMIOHandler;
379 STAMCOUNTER StatGCMMIOFailures;
380
381 STAMPROFILE StatGCInstMov;
382 STAMPROFILE StatGCInstCmp;
383 STAMPROFILE StatGCInstAnd;
384 STAMPROFILE StatGCInstTest;
385 STAMPROFILE StatGCInstXchg;
386 STAMPROFILE StatGCInstStos;
387 STAMPROFILE StatGCInstLods;
388 STAMPROFILE StatGCInstMovs;
389 STAMPROFILE StatGCInstMovsToMMIO;
390 STAMPROFILE StatGCInstMovsFromMMIO;
391 STAMPROFILE StatGCInstMovsMMIO;
392 STAMCOUNTER StatGCInstOther;
393
394 STAMCOUNTER StatGCMMIO1Byte;
395 STAMCOUNTER StatGCMMIO2Bytes;
396 STAMCOUNTER StatGCMMIO4Bytes;
397
398 RTUINT cMovsMaxBytes;
399 RTUINT cStosMaxBytes;
400 /** @} */
401
402} IOM;
403/** Pointer to IOM instance data. */
404typedef IOM *PIOM;
405
406
407__BEGIN_DECLS
408
409#ifdef IN_IOM_R3
410PIOMIOPORTSTATS iomr3IOPortStatsCreate(PVM pVM, RTIOPORT Port, const char *pszDesc);
411PIOMMMIOSTATS iomR3MMIOStatsCreate(PVM pVM, RTGCPHYS GCPhys, const char *pszDesc);
412#endif /* IN_IOM_R3 */
413
414/**
415 * \#PF Handler callback for MMIO ranges.
416 *
417 * @returns VBox status code (appropriate for GC return).
418 *
419 * @param pVM VM Handle.
420 * @param uErrorCode CPU Error code.
421 * @param pRegFrame Trap register frame.
422 * @param pvFault The fault address (cr2).
423 * @param GCPhysFault The GC physical address corresponding to pvFault.
424 * @param pvUser Pointer to the MMIO range entry.
425 */
426IOMDECL(int) IOMMMIOHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser);
427
428/**
429 * Gets the I/O port range for the specified I/O port in the current context.
430 *
431 * @returns Pointer to I/O port range.
432 * @returns NULL if no port registered.
433 *
434 * @param pIOM IOM instance data.
435 * @param Port Port to lookup.
436 */
437DECLINLINE(CTXALLSUFF(PIOMIOPORTRANGE)) iomIOPortGetRange(PIOM pIOM, RTIOPORT Port)
438{
439 CTXALLSUFF(PIOMIOPORTRANGE) pRange = (CTXALLSUFF(PIOMIOPORTRANGE))RTAvlroIOPortRangeGet(&pIOM->CTXSUFF(pTrees)->CTXALLSUFF(IOPortTree), Port);
440 return pRange;
441}
442
443/**
444 * Gets the I/O port range for the specified I/O port in the HC.
445 *
446 * @returns Pointer to I/O port range.
447 * @returns NULL if no port registered.
448 *
449 * @param pIOM IOM instance data.
450 * @param Port Port to lookup.
451 */
452DECLINLINE(PIOMIOPORTRANGER3) iomIOPortGetRangeHC(PIOM pIOM, RTIOPORT Port)
453{
454 PIOMIOPORTRANGER3 pRange = (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pIOM->CTXSUFF(pTrees)->IOPortTreeR3, Port);
455 return pRange;
456}
457
458
459/**
460 * Gets the MMIO range for the specified physical address in the current context.
461 *
462 * @returns Pointer to MMIO range.
463 * @returns NULL if address not in a MMIO range.
464 *
465 * @param pIOM IOM instance data.
466 * @param GCPhys Physical address to lookup.
467 */
468DECLINLINE(PIOMMMIORANGE) iomMMIOGetRange(PIOM pIOM, RTGCPHYS GCPhys)
469{
470 PIOMMMIORANGE pRange = CTXALLSUFF(pIOM->pMMIORangeLast);
471 if ( !pRange
472 || GCPhys - pRange->GCPhys >= pRange->cb)
473 CTXALLSUFF(pIOM->pMMIORangeLast) = pRange = (PIOMMMIORANGE)RTAvlroGCPhysRangeGet(&pIOM->CTXSUFF(pTrees)->MMIOTree, GCPhys);
474 return pRange;
475}
476
477
478#ifdef VBOX_WITH_STATISTICS
479/**
480 * Gets the MMIO statistics record.
481 *
482 * In ring-3 this will lazily create missing records, while in GC/R0 the caller has to
483 * return the appropriate status to defer the operation to ring-3.
484 *
485 * @returns Pointer to MMIO stats.
486 * @returns NULL if not found (R0/GC), or out of memory (R3).
487 *
488 * @param pIOM IOM instance data.
489 * @param GCPhys Physical address to lookup.
490 * @param pRange The MMIO range.
491 */
492DECLINLINE(PIOMMMIOSTATS) iomMMIOGetStats(PIOM pIOM, RTGCPHYS GCPhys, PIOMMMIORANGE pRange)
493{
494 /* For large ranges, we'll put everything on the first byte. */
495 if (pRange->cb > PAGE_SIZE)
496 GCPhys = pRange->GCPhys;
497
498 PIOMMMIOSTATS pStats = CTXALLSUFF(pIOM->pMMIOStatsLast);
499 if ( !pStats
500 || pStats->Core.Key != GCPhys)
501 {
502 pStats = (PIOMMMIOSTATS)RTAvloGCPhysGet(&pIOM->CTXSUFF(pTrees)->MMIOStatTree, GCPhys);
503# ifdef IN_RING3
504 if (!pStats)
505 pStats = iomR3MMIOStatsCreate(IOM2VM(pIOM), GCPhys, pRange->pszDesc);
506# endif
507 }
508 return pStats;
509}
510#endif
511
512__END_DECLS
513
514#ifdef IN_RING3
515
516#endif
517
518/** @} */
519
520#endif /* ___IOMInternal_h */
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