VirtualBox

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

Last change on this file since 81237 was 81197, checked in by vboxsync, 5 years ago

IOM: More MMIO code. bugref:9218

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 34.4 KB
Line 
1/* $Id: IOMInternal.h 81197 2019-10-09 20:36:46Z vboxsync $ */
2/** @file
3 * IOM - Internal header file.
4 */
5
6/*
7 * Copyright (C) 2006-2019 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 VMM_INCLUDED_SRC_include_IOMInternal_h
19#define VMM_INCLUDED_SRC_include_IOMInternal_h
20#ifndef RT_WITHOUT_PRAGMA_ONCE
21# pragma once
22#endif
23
24#define IOM_WITH_CRIT_SECT_RW
25
26#include <VBox/cdefs.h>
27#include <VBox/types.h>
28#include <VBox/vmm/iom.h>
29#include <VBox/vmm/stam.h>
30#include <VBox/vmm/pgm.h>
31#include <VBox/vmm/pdmcritsect.h>
32#ifdef IOM_WITH_CRIT_SECT_RW
33# include <VBox/vmm/pdmcritsectrw.h>
34#endif
35#include <VBox/param.h>
36#include <iprt/assert.h>
37#include <iprt/avl.h>
38
39
40
41/** @defgroup grp_iom_int Internals
42 * @ingroup grp_iom
43 * @internal
44 * @{
45 */
46
47/**
48 * MMIO range descriptor.
49 */
50typedef struct IOMMMIORANGE
51{
52 /** Avl node core with GCPhys as Key and GCPhys + cbSize - 1 as KeyLast. */
53 AVLROGCPHYSNODECORE Core;
54 /** Start physical address. */
55 RTGCPHYS GCPhys;
56 /** Size of the range. */
57 RTGCPHYS cb;
58 /** The reference counter. */
59 uint32_t volatile cRefs;
60 /** Flags, see IOMMMIO_FLAGS_XXX. */
61 uint32_t fFlags;
62
63 /** Pointer to user argument - R0. */
64 RTR0PTR pvUserR0;
65 /** Pointer to device instance - R0. */
66 PPDMDEVINSR0 pDevInsR0;
67 /** Pointer to write callback function - R0. */
68 R0PTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallbackR0;
69 /** Pointer to read callback function - R0. */
70 R0PTRTYPE(PFNIOMMMIOREAD) pfnReadCallbackR0;
71 /** Pointer to fill (memset) callback function - R0. */
72 R0PTRTYPE(PFNIOMMMIOFILL) pfnFillCallbackR0;
73
74 /** Pointer to user argument - R3. */
75 RTR3PTR pvUserR3;
76 /** Pointer to device instance - R3. */
77 PPDMDEVINSR3 pDevInsR3;
78 /** Pointer to write callback function - R3. */
79 R3PTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallbackR3;
80 /** Pointer to read callback function - R3. */
81 R3PTRTYPE(PFNIOMMMIOREAD) pfnReadCallbackR3;
82 /** Pointer to fill (memset) callback function - R3. */
83 R3PTRTYPE(PFNIOMMMIOFILL) pfnFillCallbackR3;
84
85 /** Description / Name. For easing debugging. */
86 R3PTRTYPE(const char *) pszDesc;
87
88#if 0
89 /** Pointer to user argument - RC. */
90 RTRCPTR pvUserRC;
91 /** Pointer to device instance - RC. */
92 PPDMDEVINSRC pDevInsRC;
93 /** Pointer to write callback function - RC. */
94 RCPTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallbackRC;
95 /** Pointer to read callback function - RC. */
96 RCPTRTYPE(PFNIOMMMIOREAD) pfnReadCallbackRC;
97 /** Pointer to fill (memset) callback function - RC. */
98 RCPTRTYPE(PFNIOMMMIOFILL) pfnFillCallbackRC;
99#if HC_ARCH_BITS == 64
100 /** Padding structure length to multiple of 8 bytes. */
101 RTRCPTR RCPtrPadding;
102#endif
103#endif
104} IOMMMIORANGE;
105/** Pointer to a MMIO range descriptor, R3 version. */
106typedef struct IOMMMIORANGE *PIOMMMIORANGE;
107
108
109/**
110 * MMIO address statistics. (one address)
111 *
112 * This is a simple way of making on demand statistics, however it's a
113 * bit free with the hypervisor heap memory.
114 */
115typedef struct IOMMMIOSTATS
116{
117 /** Avl node core with the address as Key. */
118 AVLOGCPHYSNODECORE Core;
119
120 /** Number of accesses (subtract ReadRZToR3 and WriteRZToR3 to get the right
121 * number). */
122 STAMCOUNTER Accesses;
123
124 /** Profiling read handler overhead in R3. */
125 STAMPROFILE ProfReadR3;
126 /** Profiling write handler overhead in R3. */
127 STAMPROFILE ProfWriteR3;
128 /** Counting and profiling reads in R0/RC. */
129 STAMPROFILE ProfReadRZ;
130 /** Counting and profiling writes in R0/RC. */
131 STAMPROFILE ProfWriteRZ;
132
133 /** Number of reads to this address from R0/RC which was serviced in R3. */
134 STAMCOUNTER ReadRZToR3;
135 /** Number of writes to this address from R0/RC which was serviced in R3. */
136 STAMCOUNTER WriteRZToR3;
137} IOMMMIOSTATS;
138AssertCompileMemberAlignment(IOMMMIOSTATS, Accesses, 8);
139/** Pointer to I/O port statistics. */
140typedef IOMMMIOSTATS *PIOMMMIOSTATS;
141
142/**
143 * I/O port lookup table entry.
144 */
145typedef struct IOMIOPORTLOOKUPENTRY
146{
147 /** The first port in the range. */
148 RTIOPORT uFirstPort;
149 /** The last port in the range (inclusive). */
150 RTIOPORT uLastPort;
151 /** The registration handle/index. */
152 uint16_t idx;
153} IOMIOPORTLOOKUPENTRY;
154/** Pointer to an I/O port lookup table entry. */
155typedef IOMIOPORTLOOKUPENTRY *PIOMIOPORTLOOKUPENTRY;
156/** Pointer to a const I/O port lookup table entry. */
157typedef IOMIOPORTLOOKUPENTRY const *PCIOMIOPORTLOOKUPENTRY;
158
159/**
160 * Ring-0 I/O port handle table entry.
161 */
162typedef struct IOMIOPORTENTRYR0
163{
164 /** Pointer to user argument. */
165 RTR0PTR pvUser;
166 /** Pointer to the associated device instance, NULL if entry not used. */
167 R0PTRTYPE(PPDMDEVINS) pDevIns;
168 /** Pointer to OUT callback function. */
169 R0PTRTYPE(PFNIOMIOPORTNEWOUT) pfnOutCallback;
170 /** Pointer to IN callback function. */
171 R0PTRTYPE(PFNIOMIOPORTNEWIN) pfnInCallback;
172 /** Pointer to string OUT callback function. */
173 R0PTRTYPE(PFNIOMIOPORTNEWOUTSTRING) pfnOutStrCallback;
174 /** Pointer to string IN callback function. */
175 R0PTRTYPE(PFNIOMIOPORTNEWINSTRING) pfnInStrCallback;
176 /** The entry of the first statistics entry, UINT16_MAX if no stats. */
177 uint16_t idxStats;
178 /** The number of ports covered by this entry, 0 if entry not used. */
179 RTIOPORT cPorts;
180 /** Same as the handle index. */
181 uint16_t idxSelf;
182 /** IOM_IOPORT_F_XXX (copied from ring-3). */
183 uint16_t fFlags;
184} IOMIOPORTENTRYR0;
185/** Pointer to a ring-0 I/O port handle table entry. */
186typedef IOMIOPORTENTRYR0 *PIOMIOPORTENTRYR0;
187/** Pointer to a const ring-0 I/O port handle table entry. */
188typedef IOMIOPORTENTRYR0 const *PCIOMIOPORTENTRYR0;
189
190/**
191 * Ring-3 I/O port handle table entry.
192 */
193typedef struct IOMIOPORTENTRYR3
194{
195 /** Pointer to user argument. */
196 RTR3PTR pvUser;
197 /** Pointer to the associated device instance. */
198 R3PTRTYPE(PPDMDEVINS) pDevIns;
199 /** Pointer to OUT callback function. */
200 R3PTRTYPE(PFNIOMIOPORTNEWOUT) pfnOutCallback;
201 /** Pointer to IN callback function. */
202 R3PTRTYPE(PFNIOMIOPORTNEWIN) pfnInCallback;
203 /** Pointer to string OUT callback function. */
204 R3PTRTYPE(PFNIOMIOPORTNEWOUTSTRING) pfnOutStrCallback;
205 /** Pointer to string IN callback function. */
206 R3PTRTYPE(PFNIOMIOPORTNEWINSTRING) pfnInStrCallback;
207 /** Description / Name. For easing debugging. */
208 R3PTRTYPE(const char *) pszDesc;
209 /** Extended port description table, optional. */
210 R3PTRTYPE(PCIOMIOPORTDESC) paExtDescs;
211 /** PCI device the registration is associated with. */
212 R3PTRTYPE(PPDMPCIDEV) pPciDev;
213 /** The PCI device region (high 16-bit word) and subregion (low word),
214 * UINT32_MAX if not applicable. */
215 uint32_t iPciRegion;
216 /** The number of ports covered by this entry. */
217 RTIOPORT cPorts;
218 /** The current port mapping (duplicates lookup table). */
219 RTIOPORT uPort;
220 /** The entry of the first statistics entry, UINT16_MAX if no stats. */
221 uint16_t idxStats;
222 /** Set if mapped, clear if not.
223 * Only updated when critsect is held exclusively. */
224 bool fMapped;
225 /** Set if there is an ring-0 entry too. */
226 bool fRing0;
227 /** Set if there is an raw-mode entry too. */
228 bool fRawMode;
229 /** IOM_IOPORT_F_XXX */
230 uint8_t fFlags;
231 /** Same as the handle index. */
232 uint16_t idxSelf;
233} IOMIOPORTENTRYR3;
234AssertCompileSize(IOMIOPORTENTRYR3, 9 * sizeof(RTR3PTR) + 16);
235/** Pointer to a ring-3 I/O port handle table entry. */
236typedef IOMIOPORTENTRYR3 *PIOMIOPORTENTRYR3;
237/** Pointer to a const ring-3 I/O port handle table entry. */
238typedef IOMIOPORTENTRYR3 const *PCIOMIOPORTENTRYR3;
239
240/**
241 * I/O port statistics entry (one I/O port).
242 */
243typedef struct IOMIOPORTSTATSENTRY
244{
245 /** Number of INs to this port from R3. */
246 STAMCOUNTER InR3;
247 /** Profiling IN handler overhead in R3. */
248 STAMPROFILE ProfInR3;
249 /** Number of OUTs to this port from R3. */
250 STAMCOUNTER OutR3;
251 /** Profiling OUT handler overhead in R3. */
252 STAMPROFILE ProfOutR3;
253
254 /** Number of INs to this port from R0/RC. */
255 STAMCOUNTER InRZ;
256 /** Profiling IN handler overhead in R0/RC. */
257 STAMPROFILE ProfInRZ;
258 /** Number of INs to this port from R0/RC which was serviced in R3. */
259 STAMCOUNTER InRZToR3;
260
261 /** Number of OUTs to this port from R0/RC. */
262 STAMCOUNTER OutRZ;
263 /** Profiling OUT handler overhead in R0/RC. */
264 STAMPROFILE ProfOutRZ;
265 /** Number of OUTs to this port from R0/RC which was serviced in R3. */
266 STAMCOUNTER OutRZToR3;
267} IOMIOPORTSTATSENTRY;
268/** Pointer to I/O port statistics entry. */
269typedef IOMIOPORTSTATSENTRY *PIOMIOPORTSTATSENTRY;
270
271
272
273/**
274 * MMIO lookup table entry.
275 */
276typedef struct IOMMMIOLOOKUPENTRY
277{
278 /** The first port in the range. */
279 RTGCPHYS GCPhysFirst;
280 /** The last port in the range (inclusive). */
281 RTGCPHYS GCPhysLast;
282 /** The registration handle/index.
283 * @todo bake this into the lower/upper bits of GCPhysFirst & GCPhysLast. */
284 uint16_t idx;
285 uint16_t abPadding[3];
286} IOMMMIOLOOKUPENTRY;
287/** Pointer to an MMIO lookup table entry. */
288typedef IOMMMIOLOOKUPENTRY *PIOMMMIOLOOKUPENTRY;
289/** Pointer to a const MMIO lookup table entry. */
290typedef IOMMMIOLOOKUPENTRY const *PCIOMMMIOLOOKUPENTRY;
291
292/**
293 * Ring-0 MMIO handle table entry.
294 */
295typedef struct IOMMMIOENTRYR0
296{
297 /** The number of bytes covered by this entry, 0 if entry not used. */
298 RTGCPHYS cbRegion;
299 /** Pointer to user argument. */
300 RTR0PTR pvUser;
301 /** Pointer to the associated device instance, NULL if entry not used. */
302 R0PTRTYPE(PPDMDEVINS) pDevIns;
303 /** Pointer to the write callback function. */
304 R0PTRTYPE(PFNIOMMMIONEWWRITE) pfnWriteCallback;
305 /** Pointer to the read callback function. */
306 R0PTRTYPE(PFNIOMMMIONEWREAD) pfnReadCallback;
307 /** Pointer to the fill callback function. */
308 R0PTRTYPE(PFNIOMMMIONEWFILL) pfnFillCallback;
309 /** The entry of the first statistics entry, UINT16_MAX if no stats. */
310 uint16_t idxStats;
311 /** Same as the handle index. */
312 uint16_t idxSelf;
313 /** IOM_MMIO_F_XXX (copied from ring-3). */
314 uint32_t fFlags;
315} IOMMMIOENTRYR0;
316/** Pointer to a ring-0 MMIO handle table entry. */
317typedef IOMMMIOENTRYR0 *PIOMMMIOENTRYR0;
318/** Pointer to a const ring-0 MMIO handle table entry. */
319typedef IOMMMIOENTRYR0 const *PCIOMMMIOENTRYR0;
320
321/**
322 * Ring-3 MMIO handle table entry.
323 */
324typedef struct IOMMMIOENTRYR3
325{
326 /** The number of bytes covered by this entry. */
327 RTGCPHYS cbRegion;
328 /** The current mapping address (duplicates lookup table). */
329 RTGCPHYS GCPhysMapping;
330 /** Pointer to user argument. */
331 RTR3PTR pvUser;
332 /** Pointer to the associated device instance. */
333 R3PTRTYPE(PPDMDEVINS) pDevIns;
334 /** Pointer to the write callback function. */
335 R3PTRTYPE(PFNIOMMMIONEWWRITE) pfnWriteCallback;
336 /** Pointer to the read callback function. */
337 R3PTRTYPE(PFNIOMMMIONEWREAD) pfnReadCallback;
338 /** Pointer to the fill callback function. */
339 R3PTRTYPE(PFNIOMMMIONEWFILL) pfnFillCallback;
340 /** Description / Name. For easing debugging. */
341 R3PTRTYPE(const char *) pszDesc;
342 /** PCI device the registration is associated with. */
343 R3PTRTYPE(PPDMPCIDEV) pPciDev;
344 /** The PCI device region (high 16-bit word) and subregion (low word),
345 * UINT32_MAX if not applicable. */
346 uint32_t iPciRegion;
347 /** IOM_MMIO_F_XXX */
348 uint32_t fFlags;
349 /** The entry of the first statistics entry, UINT16_MAX if no stats. */
350 uint16_t idxStats;
351 /** Set if mapped, clear if not.
352 * Only updated when critsect is held exclusively. */
353 bool fMapped;
354 /** Set if there is an ring-0 entry too. */
355 bool fRing0;
356 /** Set if there is an raw-mode entry too. */
357 bool fRawMode;
358 uint8_t bPadding;
359 /** Same as the handle index. */
360 uint16_t idxSelf;
361} IOMMMIOENTRYR3;
362AssertCompileSize(IOMMMIOENTRYR3, sizeof(RTGCPHYS) * 2 + 7 * sizeof(RTR3PTR) + 16);
363/** Pointer to a ring-3 MMIO handle table entry. */
364typedef IOMMMIOENTRYR3 *PIOMMMIOENTRYR3;
365/** Pointer to a const ring-3 MMIO handle table entry. */
366typedef IOMMMIOENTRYR3 const *PCIOMMMIOENTRYR3;
367
368/**
369 * MMIO statistics entry (one MMIO).
370 */
371typedef struct IOMMMIOSTATSENTRY
372{
373 /** Number of accesses (subtract ReadRZToR3 and WriteRZToR3 to get the right
374 * number). */
375 STAMCOUNTER Accesses;
376
377 /** Profiling read handler overhead in R3. */
378 STAMPROFILE ProfReadR3;
379 /** Profiling write handler overhead in R3. */
380 STAMPROFILE ProfWriteR3;
381 /** Counting and profiling reads in R0/RC. */
382 STAMPROFILE ProfReadRZ;
383 /** Counting and profiling writes in R0/RC. */
384 STAMPROFILE ProfWriteRZ;
385
386 /** Number of reads to this address from R0/RC which was serviced in R3. */
387 STAMCOUNTER ReadRZToR3;
388 /** Number of writes to this address from R0/RC which was serviced in R3. */
389 STAMCOUNTER WriteRZToR3;
390} IOMMMIOSTATSENTRY;
391/** Pointer to MMIO statistics entry. */
392typedef IOMMMIOSTATSENTRY *PIOMMMIOSTATSENTRY;
393
394
395
396/**
397 * I/O port range descriptor, R3 version.
398 */
399typedef struct IOMIOPORTRANGER3
400{
401 /** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */
402 AVLROIOPORTNODECORE Core;
403#if HC_ARCH_BITS == 64 && !defined(RT_OS_WINDOWS)
404 uint32_t u32Alignment; /**< The sizeof(Core) differs. */
405#endif
406 /** Start I/O port address. */
407 RTIOPORT Port;
408 /** Size of the range. */
409 uint16_t cPorts;
410 /** Pointer to user argument. */
411 RTR3PTR pvUser;
412 /** Pointer to the associated device instance. */
413 R3PTRTYPE(PPDMDEVINS) pDevIns;
414 /** Pointer to OUT callback function. */
415 R3PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback;
416 /** Pointer to IN callback function. */
417 R3PTRTYPE(PFNIOMIOPORTIN) pfnInCallback;
418 /** Pointer to string OUT callback function. */
419 R3PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;
420 /** Pointer to string IN callback function. */
421 R3PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;
422 /** Description / Name. For easing debugging. */
423 R3PTRTYPE(const char *) pszDesc;
424} IOMIOPORTRANGER3;
425/** Pointer to I/O port range descriptor, R3 version. */
426typedef IOMIOPORTRANGER3 *PIOMIOPORTRANGER3;
427
428/**
429 * I/O port range descriptor, R0 version.
430 */
431typedef struct IOMIOPORTRANGER0
432{
433 /** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */
434 AVLROIOPORTNODECORE Core;
435#if HC_ARCH_BITS == 64 && !defined(RT_OS_WINDOWS)
436 uint32_t u32Alignment; /**< The sizeof(Core) differs. */
437#endif
438 /** Start I/O port address. */
439 RTIOPORT Port;
440 /** Size of the range. */
441 uint16_t cPorts;
442 /** Pointer to user argument. */
443 RTR0PTR pvUser;
444 /** Pointer to the associated device instance. */
445 R0PTRTYPE(PPDMDEVINS) pDevIns;
446 /** Pointer to OUT callback function. */
447 R0PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback;
448 /** Pointer to IN callback function. */
449 R0PTRTYPE(PFNIOMIOPORTIN) pfnInCallback;
450 /** Pointer to string OUT callback function. */
451 R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;
452 /** Pointer to string IN callback function. */
453 R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;
454 /** Description / Name. For easing debugging. */
455 R3PTRTYPE(const char *) pszDesc;
456} IOMIOPORTRANGER0;
457/** Pointer to I/O port range descriptor, R0 version. */
458typedef IOMIOPORTRANGER0 *PIOMIOPORTRANGER0;
459
460/**
461 * I/O port range descriptor, RC version.
462 */
463typedef struct IOMIOPORTRANGERC
464{
465 /** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */
466 AVLROIOPORTNODECORE Core;
467 /** Start I/O port address. */
468 RTIOPORT Port;
469 /** Size of the range. */
470 uint16_t cPorts;
471 /** Pointer to user argument. */
472 RTRCPTR pvUser;
473 /** Pointer to the associated device instance. */
474 RCPTRTYPE(PPDMDEVINS) pDevIns;
475 /** Pointer to OUT callback function. */
476 RCPTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback;
477 /** Pointer to IN callback function. */
478 RCPTRTYPE(PFNIOMIOPORTIN) pfnInCallback;
479 /** Pointer to string OUT callback function. */
480 RCPTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;
481 /** Pointer to string IN callback function. */
482 RCPTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;
483#if HC_ARCH_BITS == 64
484 RTRCPTR RCPtrAlignment; /**< pszDesc is 8 byte aligned. */
485#endif
486 /** Description / Name. For easing debugging. */
487 R3PTRTYPE(const char *) pszDesc;
488} IOMIOPORTRANGERC;
489/** Pointer to I/O port range descriptor, RC version. */
490typedef IOMIOPORTRANGERC *PIOMIOPORTRANGERC;
491
492
493/**
494 * I/O port statistics. (one I/O port)
495 *
496 * This is a simple way of making on demand statistics, however it's a
497 * bit free with the hypervisor heap memory.
498 */
499typedef struct IOMIOPORTSTATS
500{
501 /** Avl node core with the port as Key. */
502 AVLOIOPORTNODECORE Core;
503#if HC_ARCH_BITS != 64 || !defined(RT_OS_WINDOWS)
504 uint32_t u32Alignment; /**< The sizeof(Core) differs. */
505#endif
506 /** Number of INs to this port from R3. */
507 STAMCOUNTER InR3;
508 /** Profiling IN handler overhead in R3. */
509 STAMPROFILE ProfInR3;
510 /** Number of OUTs to this port from R3. */
511 STAMCOUNTER OutR3;
512 /** Profiling OUT handler overhead in R3. */
513 STAMPROFILE ProfOutR3;
514
515 /** Number of INs to this port from R0/RC. */
516 STAMCOUNTER InRZ;
517 /** Profiling IN handler overhead in R0/RC. */
518 STAMPROFILE ProfInRZ;
519 /** Number of INs to this port from R0/RC which was serviced in R3. */
520 STAMCOUNTER InRZToR3;
521
522 /** Number of OUTs to this port from R0/RC. */
523 STAMCOUNTER OutRZ;
524 /** Profiling OUT handler overhead in R0/RC. */
525 STAMPROFILE ProfOutRZ;
526 /** Number of OUTs to this port from R0/RC which was serviced in R3. */
527 STAMCOUNTER OutRZToR3;
528} IOMIOPORTSTATS;
529AssertCompileMemberAlignment(IOMIOPORTSTATS, InR3, 8);
530/** Pointer to I/O port statistics. */
531typedef IOMIOPORTSTATS *PIOMIOPORTSTATS;
532
533
534/**
535 * The IOM trees.
536 *
537 * These are offset based the nodes and root must be in the same
538 * memory block in HC. The locations of IOM structure and the hypervisor heap
539 * are quite different in R3, R0 and RC.
540 */
541typedef struct IOMTREES
542{
543 /** Tree containing I/O port range descriptors registered for HC (IOMIOPORTRANGEHC). */
544 AVLROIOPORTTREE IOPortTreeR3;
545 /** Tree containing I/O port range descriptors registered for R0 (IOMIOPORTRANGER0). */
546 AVLROIOPORTTREE IOPortTreeR0;
547#if 0
548 /** Tree containing I/O port range descriptors registered for RC (IOMIOPORTRANGERC). */
549 AVLROIOPORTTREE IOPortTreeRC;
550#endif
551
552 /** Tree containing the MMIO range descriptors (IOMMMIORANGE). */
553 AVLROGCPHYSTREE MMIOTree;
554
555 /** Tree containing I/O port statistics (IOMIOPORTSTATS). */
556 AVLOIOPORTTREE IOPortStatTree;
557 /** Tree containing MMIO statistics (IOMMMIOSTATS). */
558 AVLOGCPHYSTREE MmioStatTree;
559} IOMTREES;
560/** Pointer to the IOM trees. */
561typedef IOMTREES *PIOMTREES;
562
563
564/**
565 * IOM per virtual CPU instance data.
566 */
567typedef struct IOMCPU
568{
569 /** For saving stack space, the disassembler state is allocated here instead of
570 * on the stack. */
571 DISCPUSTATE DisState;
572
573 /**
574 * Pending I/O port write commit (VINF_IOM_R3_IOPORT_COMMIT_WRITE).
575 *
576 * This is a converted VINF_IOM_R3_IOPORT_WRITE handler return that lets the
577 * execution engine commit the instruction and then return to ring-3 to complete
578 * the I/O port write there. This avoids having to decode the instruction again
579 * in ring-3.
580 */
581 struct
582 {
583 /** The value size (0 if not pending). */
584 uint16_t cbValue;
585 /** The I/O port. */
586 RTIOPORT IOPort;
587 /** The value. */
588 uint32_t u32Value;
589 } PendingIOPortWrite;
590
591 /**
592 * Pending MMIO write commit (VINF_IOM_R3_MMIO_COMMIT_WRITE).
593 *
594 * This is a converted VINF_IOM_R3_MMIO_WRITE handler return that lets the
595 * execution engine commit the instruction, stop any more REPs, and return to
596 * ring-3 to complete the MMIO write there. The avoid the tedious decoding of
597 * the instruction again once we're in ring-3, more importantly it allows us to
598 * correctly deal with read-modify-write instructions like XCHG, OR, and XOR.
599 */
600 struct
601 {
602 /** Guest physical MMIO address. */
603 RTGCPHYS GCPhys;
604 /** The value to write. */
605 uint8_t abValue[128];
606 /** The number of bytes to write (0 if nothing pending). */
607 uint32_t cbValue;
608 /** Alignment padding. */
609 uint32_t uAlignmentPadding;
610 } PendingMmioWrite;
611
612 /** @name Caching of I/O Port and MMIO ranges and statistics.
613 * (Saves quite some time in rep outs/ins instruction emulation.)
614 * @{ */
615 /** I/O port registration index for the last read operation. */
616 uint16_t idxIoPortLastRead;
617 /** I/O port registration index for the last write operation. */
618 uint16_t idxIoPortLastWrite;
619 /** I/O port registration index for the last read string operation. */
620 uint16_t idxIoPortLastReadStr;
621 /** I/O port registration index for the last write string operation. */
622 uint16_t idxIoPortLastWriteStr;
623 uint32_t u32Padding;
624
625 R3PTRTYPE(PIOMIOPORTRANGER3) pRangeLastReadR3;
626 R3PTRTYPE(PIOMIOPORTRANGER3) pRangeLastWriteR3;
627 R3PTRTYPE(PIOMIOPORTSTATS) pStatsLastReadR3;
628 R3PTRTYPE(PIOMIOPORTSTATS) pStatsLastWriteR3;
629 R3PTRTYPE(PIOMMMIORANGE) pMMIORangeLastR3;
630 R3PTRTYPE(PIOMMMIOSTATS) pMMIOStatsLastR3;
631
632 R0PTRTYPE(PIOMIOPORTRANGER0) pRangeLastReadR0;
633 R0PTRTYPE(PIOMIOPORTRANGER0) pRangeLastWriteR0;
634 R0PTRTYPE(PIOMIOPORTSTATS) pStatsLastReadR0;
635 R0PTRTYPE(PIOMIOPORTSTATS) pStatsLastWriteR0;
636 R0PTRTYPE(PIOMMMIORANGE) pMMIORangeLastR0;
637 R0PTRTYPE(PIOMMMIOSTATS) pMMIOStatsLastR0;
638 /** @} */
639} IOMCPU;
640/** Pointer to IOM per virtual CPU instance data. */
641typedef IOMCPU *PIOMCPU;
642
643
644/**
645 * IOM Data (part of VM)
646 */
647typedef struct IOM
648{
649 /** Pointer to the trees - R3 ptr. */
650 R3PTRTYPE(PIOMTREES) pTreesR3;
651 /** Pointer to the trees - R0 ptr. */
652 R0PTRTYPE(PIOMTREES) pTreesR0;
653
654 /** MMIO physical access handler type. */
655 PGMPHYSHANDLERTYPE hMmioHandlerType;
656 uint32_t u32Padding;
657
658 /** @name I/O ports
659 * @note The updating of these variables is done exclusively from EMT(0).
660 * @{ */
661 /** Number of I/O port registrations. */
662 uint32_t cIoPortRegs;
663 /** The size of the paIoPortRegs allocation (in entries). */
664 uint32_t cIoPortAlloc;
665 /** I/O port registration table for ring-3.
666 * There is a parallel table in ring-0, IOMR0PERVM::paIoPortRegs. */
667 R3PTRTYPE(PIOMIOPORTENTRYR3) paIoPortRegs;
668 /** Number of entries in the lookup table. */
669 uint32_t cIoPortLookupEntries;
670 uint32_t u32Padding1;
671 /** I/O port lookup table. */
672 R3PTRTYPE(PIOMIOPORTLOOKUPENTRY) paIoPortLookup;
673
674 /** The number of valid entries in paioPortStats. */
675 uint32_t cIoPortStats;
676 /** The size of the paIoPortStats allocation (in entries). */
677 uint32_t cIoPortStatsAllocation;
678 /** I/O port lookup table. */
679 R3PTRTYPE(PIOMIOPORTSTATSENTRY) paIoPortStats;
680 /** Dummy stats entry so we don't need to check for NULL pointers so much. */
681 IOMIOPORTSTATSENTRY IoPortDummyStats;
682 /** @} */
683
684 /** @name MMIO ports
685 * @note The updating of these variables is done exclusively from EMT(0).
686 * @{ */
687 /** Number of MMIO registrations. */
688 uint32_t cMmioRegs;
689 /** The size of the paMmioRegs allocation (in entries). */
690 uint32_t cMmioAlloc;
691 /** MMIO registration table for ring-3.
692 * There is a parallel table in ring-0, IOMR0PERVM::paMmioRegs. */
693 R3PTRTYPE(PIOMMMIOENTRYR3) paMmioRegs;
694 /** Number of entries in the lookup table. */
695 uint32_t cMmioLookupEntries;
696 uint32_t u32Padding2;
697 /** MMIO lookup table. */
698 R3PTRTYPE(PIOMMMIOLOOKUPENTRY) paMmioLookup;
699
700 /** The number of valid entries in paioPortStats. */
701 uint32_t cMmioStats;
702 /** The size of the paMmioStats allocation (in entries). */
703 uint32_t cMmioStatsAllocation;
704 /** MMIO lookup table. */
705 R3PTRTYPE(PIOMMMIOSTATSENTRY) paMmioStats;
706 /** Dummy stats entry so we don't need to check for NULL pointers so much. */
707 IOMMMIOSTATSENTRY MmioDummyStats;
708 /** @} */
709
710
711 /** Lock serializing EMT access to IOM. */
712#ifdef IOM_WITH_CRIT_SECT_RW
713 PDMCRITSECTRW CritSect;
714#else
715 PDMCRITSECT CritSect;
716#endif
717
718#if 0 /* unused */
719 /** @name I/O Port statistics.
720 * @{ */
721 STAMCOUNTER StatInstIn;
722 STAMCOUNTER StatInstOut;
723 STAMCOUNTER StatInstIns;
724 STAMCOUNTER StatInstOuts;
725 /** @} */
726#endif
727
728 /** @name MMIO statistics.
729 * @{ */
730 STAMPROFILE StatRZMMIOHandler;
731 STAMCOUNTER StatRZMMIOFailures;
732
733 STAMPROFILE StatRZInstMov;
734 STAMPROFILE StatRZInstCmp;
735 STAMPROFILE StatRZInstAnd;
736 STAMPROFILE StatRZInstOr;
737 STAMPROFILE StatRZInstXor;
738 STAMPROFILE StatRZInstBt;
739 STAMPROFILE StatRZInstTest;
740 STAMPROFILE StatRZInstXchg;
741 STAMPROFILE StatRZInstStos;
742 STAMPROFILE StatRZInstLods;
743#ifdef IOM_WITH_MOVS_SUPPORT
744 STAMPROFILEADV StatRZInstMovs;
745 STAMPROFILE StatRZInstMovsToMMIO;
746 STAMPROFILE StatRZInstMovsFromMMIO;
747 STAMPROFILE StatRZInstMovsMMIO;
748#endif
749 STAMCOUNTER StatRZInstOther;
750
751 STAMCOUNTER StatRZMMIO1Byte;
752 STAMCOUNTER StatRZMMIO2Bytes;
753 STAMCOUNTER StatRZMMIO4Bytes;
754 STAMCOUNTER StatRZMMIO8Bytes;
755
756 STAMCOUNTER StatR3MMIOHandler;
757
758 RTUINT cMovsMaxBytes;
759 RTUINT cStosMaxBytes;
760 /** @} */
761} IOM;
762/** Pointer to IOM instance data. */
763typedef IOM *PIOM;
764
765
766/**
767 * IOM data kept in the ring-0 GVM.
768 */
769typedef struct IOMR0PERVM
770{
771 /** @name I/O ports
772 * @{ */
773 /** The higest ring-0 I/O port registration plus one. */
774 uint32_t cIoPortMax;
775 /** The size of the paIoPortRegs allocation (in entries). */
776 uint32_t cIoPortAlloc;
777 /** I/O port registration table for ring-0.
778 * There is a parallel table for ring-3, paIoPortRing3Regs. */
779 R0PTRTYPE(PIOMIOPORTENTRYR0) paIoPortRegs;
780 /** I/O port lookup table. */
781 R0PTRTYPE(PIOMIOPORTLOOKUPENTRY) paIoPortLookup;
782 /** I/O port registration table for ring-3.
783 * Also mapped to ring-3 as IOM::paIoPortRegs. */
784 R0PTRTYPE(PIOMIOPORTENTRYR3) paIoPortRing3Regs;
785 /** Handle to the allocation backing both the ring-0 and ring-3 registration
786 * tables as well as the lookup table. */
787 RTR0MEMOBJ hIoPortMemObj;
788 /** Handle to the ring-3 mapping of the lookup and ring-3 registration table. */
789 RTR0MEMOBJ hIoPortMapObj;
790#ifdef VBOX_WITH_STATISTICS
791 /** The size of the paIoPortStats allocation (in entries). */
792 uint32_t cIoPortStatsAllocation;
793 /** I/O port lookup table. */
794 R0PTRTYPE(PIOMIOPORTSTATSENTRY) paIoPortStats;
795 /** Handle to the allocation backing the I/O port statistics. */
796 RTR0MEMOBJ hIoPortStatsMemObj;
797 /** Handle to the ring-3 mapping of the I/O port statistics. */
798 RTR0MEMOBJ hIoPortStatsMapObj;
799#endif
800 /** @} */
801
802 /** @name MMIO
803 * @{ */
804 /** The higest ring-0 MMIO registration plus one. */
805 uint32_t cMmioMax;
806 /** The size of the paMmioRegs allocation (in entries). */
807 uint32_t cMmioAlloc;
808 /** MMIO registration table for ring-0.
809 * There is a parallel table for ring-3, paMmioRing3Regs. */
810 R0PTRTYPE(PIOMMMIOENTRYR0) paMmioRegs;
811 /** MMIO lookup table. */
812 R0PTRTYPE(PIOMMMIOLOOKUPENTRY) paMmioLookup;
813 /** MMIO registration table for ring-3.
814 * Also mapped to ring-3 as IOM::paMmioRegs. */
815 R0PTRTYPE(PIOMMMIOENTRYR3) paMmioRing3Regs;
816 /** Handle to the allocation backing both the ring-0 and ring-3 registration
817 * tables as well as the lookup table. */
818 RTR0MEMOBJ hMmioMemObj;
819 /** Handle to the ring-3 mapping of the lookup and ring-3 registration table. */
820 RTR0MEMOBJ hMmioMapObj;
821#ifdef VBOX_WITH_STATISTICS
822 /** The size of the paMmioStats allocation (in entries). */
823 uint32_t cMmioStatsAllocation;
824 /** MMIO lookup table. */
825 R0PTRTYPE(PIOMMMIOSTATSENTRY) paMmioStats;
826 /** Handle to the allocation backing the MMIO statistics. */
827 RTR0MEMOBJ hMmioStatsMemObj;
828 /** Handle to the ring-3 mapping of the MMIO statistics. */
829 RTR0MEMOBJ hMmioStatsMapObj;
830#endif
831 /** @} */
832
833} IOMR0PERVM;
834
835
836RT_C_DECLS_BEGIN
837
838void iomMmioFreeRange(PVMCC pVM, PIOMMMIORANGE pRange);
839#ifdef IN_RING3
840PIOMMMIOSTATS iomR3MMIOStatsCreate(PVM pVM, RTGCPHYS GCPhys, const char *pszDesc);
841DECLCALLBACK(void) iomR3IoPortInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
842void iomR3IoPortRegStats(PVM pVM, PIOMIOPORTENTRYR3 pRegEntry);
843#endif /* IN_RING3 */
844#ifdef IN_RING0
845void iomR0IoPortCleanupVM(PGVM pGVM);
846void iomR0IoPortInitPerVMData(PGVM pGVM);
847void iomR0MmioCleanupVM(PGVM pGVM);
848void iomR0MmioInitPerVMData(PGVM pGVM);
849#endif
850
851#ifndef IN_RING3
852DECLEXPORT(FNPGMRZPHYSPFHANDLER) iomMmioPfHandler;
853#endif
854PGM_ALL_CB2_PROTO(FNPGMPHYSHANDLER) iomMmioHandler;
855
856/* IOM locking helpers. */
857#ifdef IOM_WITH_CRIT_SECT_RW
858# define IOM_LOCK_EXCL(a_pVM) PDMCritSectRwEnterExcl(&(a_pVM)->iom.s.CritSect, VERR_SEM_BUSY)
859# define IOM_UNLOCK_EXCL(a_pVM) do { PDMCritSectRwLeaveExcl(&(a_pVM)->iom.s.CritSect); } while (0)
860# if 0 /* (in case needed for debugging) */
861# define IOM_LOCK_SHARED_EX(a_pVM, a_rcBusy) PDMCritSectRwEnterExcl(&(a_pVM)->iom.s.CritSect, (a_rcBusy))
862# define IOM_UNLOCK_SHARED(a_pVM) do { PDMCritSectRwLeaveExcl(&(a_pVM)->iom.s.CritSect); } while (0)
863# define IOM_IS_SHARED_LOCK_OWNER(a_pVM) PDMCritSectRwIsWriteOwner(&(a_pVM)->iom.s.CritSect)
864# else
865# define IOM_LOCK_SHARED_EX(a_pVM, a_rcBusy) PDMCritSectRwEnterShared(&(a_pVM)->iom.s.CritSect, (a_rcBusy))
866# define IOM_UNLOCK_SHARED(a_pVM) do { PDMCritSectRwLeaveShared(&(a_pVM)->iom.s.CritSect); } while (0)
867# define IOM_IS_SHARED_LOCK_OWNER(a_pVM) PDMCritSectRwIsReadOwner(&(a_pVM)->iom.s.CritSect, true)
868# endif
869# define IOM_IS_EXCL_LOCK_OWNER(a_pVM) PDMCritSectRwIsWriteOwner(&(a_pVM)->iom.s.CritSect)
870#else
871# define IOM_LOCK_EXCL(a_pVM) PDMCritSectEnter(&(a_pVM)->iom.s.CritSect, VERR_SEM_BUSY)
872# define IOM_UNLOCK_EXCL(a_pVM) do { PDMCritSectLeave(&(a_pVM)->iom.s.CritSect); } while (0)
873# define IOM_LOCK_SHARED_EX(a_pVM, a_rcBusy) PDMCritSectEnter(&(a_pVM)->iom.s.CritSect, (a_rcBusy))
874# define IOM_UNLOCK_SHARED(a_pVM) do { PDMCritSectLeave(&(a_pVM)->iom.s.CritSect); } while (0)
875# define IOM_IS_SHARED_LOCK_OWNER(a_pVM) PDMCritSectIsOwner(&(a_pVM)->iom.s.CritSect)
876# define IOM_IS_EXCL_LOCK_OWNER(a_pVM) PDMCritSectIsOwner(&(a_pVM)->iom.s.CritSect)
877#endif
878#define IOM_LOCK_SHARED(a_pVM) IOM_LOCK_SHARED_EX(a_pVM, VERR_SEM_BUSY)
879
880
881RT_C_DECLS_END
882
883
884#ifdef IN_RING3
885
886#endif
887
888/** @} */
889
890#endif /* !VMM_INCLUDED_SRC_include_IOMInternal_h */
891
Note: See TracBrowser for help on using the repository browser.

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