summaryrefslogtreecommitdiffstats
path: root/src/VBox/VMM/include/IOMInternal.h
blob: 6154a9de12e0e2c9661d5c29f1d0a4392bc0ec0d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
/* $Id: IOMInternal.h $ */
/** @file
 * IOM - Internal header file.
 */

/*
 * Copyright (C) 2006-2020 Oracle Corporation
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 */

#ifndef VMM_INCLUDED_SRC_include_IOMInternal_h
#define VMM_INCLUDED_SRC_include_IOMInternal_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif

#define IOM_WITH_CRIT_SECT_RW

#include <VBox/cdefs.h>
#include <VBox/types.h>
#include <VBox/vmm/iom.h>
#include <VBox/vmm/stam.h>
#include <VBox/vmm/pgm.h>
#include <VBox/vmm/pdmcritsect.h>
#ifdef IOM_WITH_CRIT_SECT_RW
# include <VBox/vmm/pdmcritsectrw.h>
#endif
#include <VBox/param.h>
#include <iprt/assert.h>
#include <iprt/avl.h>



/** @defgroup grp_iom_int   Internals
 * @ingroup grp_iom
 * @internal
 * @{
 */

/**
 * I/O port lookup table entry.
 */
typedef struct IOMIOPORTLOOKUPENTRY
{
    /** The first port in the range. */
    RTIOPORT                    uFirstPort;
    /** The last port in the range (inclusive). */
    RTIOPORT                    uLastPort;
    /** The registration handle/index. */
    uint16_t                    idx;
} IOMIOPORTLOOKUPENTRY;
/** Pointer to an I/O port lookup table entry. */
typedef IOMIOPORTLOOKUPENTRY *PIOMIOPORTLOOKUPENTRY;
/** Pointer to a const I/O port lookup table entry. */
typedef IOMIOPORTLOOKUPENTRY const *PCIOMIOPORTLOOKUPENTRY;

/**
 * Ring-0 I/O port handle table entry.
 */
typedef struct IOMIOPORTENTRYR0
{
    /** Pointer to user argument. */
    RTR0PTR                             pvUser;
    /** Pointer to the associated device instance, NULL if entry not used. */
    R0PTRTYPE(PPDMDEVINS)               pDevIns;
    /** Pointer to OUT callback function. */
    R0PTRTYPE(PFNIOMIOPORTNEWOUT)       pfnOutCallback;
    /** Pointer to IN callback function. */
    R0PTRTYPE(PFNIOMIOPORTNEWIN)        pfnInCallback;
    /** Pointer to string OUT callback function. */
    R0PTRTYPE(PFNIOMIOPORTNEWOUTSTRING) pfnOutStrCallback;
    /** Pointer to string IN callback function. */
    R0PTRTYPE(PFNIOMIOPORTNEWINSTRING)  pfnInStrCallback;
    /** The entry of the first statistics entry, UINT16_MAX if no stats. */
    uint16_t                            idxStats;
    /** The number of ports covered by this entry, 0 if entry not used. */
    RTIOPORT                            cPorts;
    /** Same as the handle index. */
    uint16_t                            idxSelf;
    /** IOM_IOPORT_F_XXX (copied from ring-3). */
    uint16_t                            fFlags;
} IOMIOPORTENTRYR0;
/** Pointer to a ring-0 I/O port handle table entry. */
typedef IOMIOPORTENTRYR0 *PIOMIOPORTENTRYR0;
/** Pointer to a const ring-0 I/O port handle table entry. */
typedef IOMIOPORTENTRYR0 const *PCIOMIOPORTENTRYR0;

/**
 * Ring-3 I/O port handle table entry.
 */
typedef struct IOMIOPORTENTRYR3
{
    /** Pointer to user argument. */
    RTR3PTR                             pvUser;
    /** Pointer to the associated device instance. */
    R3PTRTYPE(PPDMDEVINS)               pDevIns;
    /** Pointer to OUT callback function. */
    R3PTRTYPE(PFNIOMIOPORTNEWOUT)       pfnOutCallback;
    /** Pointer to IN callback function. */
    R3PTRTYPE(PFNIOMIOPORTNEWIN)        pfnInCallback;
    /** Pointer to string OUT callback function. */
    R3PTRTYPE(PFNIOMIOPORTNEWOUTSTRING) pfnOutStrCallback;
    /** Pointer to string IN callback function. */
    R3PTRTYPE(PFNIOMIOPORTNEWINSTRING)  pfnInStrCallback;
    /** Description / Name. For easing debugging. */
    R3PTRTYPE(const char *)             pszDesc;
    /** Extended port description table, optional. */
    R3PTRTYPE(PCIOMIOPORTDESC)          paExtDescs;
    /** PCI device the registration is associated with. */
    R3PTRTYPE(PPDMPCIDEV)               pPciDev;
    /** The PCI device region (high 16-bit word) and subregion (low word),
     *  UINT32_MAX if not applicable. */
    uint32_t                            iPciRegion;
    /** The number of ports covered by this entry. */
    RTIOPORT                            cPorts;
    /** The current port mapping (duplicates lookup table). */
    RTIOPORT                            uPort;
    /** The entry of the first statistics entry, UINT16_MAX if no stats. */
    uint16_t                            idxStats;
    /** Set if mapped, clear if not.
     * Only updated when critsect is held exclusively.   */
    bool                                fMapped;
    /** Set if there is an ring-0 entry too. */
    bool                                fRing0;
    /** Set if there is an raw-mode entry too. */
    bool                                fRawMode;
    /** IOM_IOPORT_F_XXX */
    uint8_t                             fFlags;
    /** Same as the handle index. */
    uint16_t                            idxSelf;
} IOMIOPORTENTRYR3;
AssertCompileSize(IOMIOPORTENTRYR3, 9 * sizeof(RTR3PTR) + 16);
/** Pointer to a ring-3 I/O port handle table entry. */
typedef IOMIOPORTENTRYR3 *PIOMIOPORTENTRYR3;
/** Pointer to a const ring-3 I/O port handle table entry. */
typedef IOMIOPORTENTRYR3 const *PCIOMIOPORTENTRYR3;

/**
 * I/O port statistics entry (one I/O port).
 */
typedef struct IOMIOPORTSTATSENTRY
{
    /** All accesses (only updated for the first port in a range). */
    STAMCOUNTER                 Total;

    /** Number of INs to this port from R3. */
    STAMCOUNTER                 InR3;
    /** Profiling IN handler overhead in R3. */
    STAMPROFILE                 ProfInR3;
    /** Number of OUTs to this port from R3. */
    STAMCOUNTER                 OutR3;
    /** Profiling OUT handler overhead in R3. */
    STAMPROFILE                 ProfOutR3;

    /** Number of INs to this port from R0/RC. */
    STAMCOUNTER                 InRZ;
    /** Profiling IN handler overhead in R0/RC. */
    STAMPROFILE                 ProfInRZ;
    /** Number of INs to this port from R0/RC which was serviced in R3. */
    STAMCOUNTER                 InRZToR3;

    /** Number of OUTs to this port from R0/RC. */
    STAMCOUNTER                 OutRZ;
    /** Profiling OUT handler overhead in R0/RC. */
    STAMPROFILE                 ProfOutRZ;
    /** Number of OUTs to this port from R0/RC which was serviced in R3. */
    STAMCOUNTER                 OutRZToR3;
} IOMIOPORTSTATSENTRY;
/** Pointer to I/O port statistics entry. */
typedef IOMIOPORTSTATSENTRY *PIOMIOPORTSTATSENTRY;



/**
 * MMIO lookup table entry.
 */
typedef struct IOMMMIOLOOKUPENTRY
{
    /** The first port in the range. */
    RTGCPHYS                    GCPhysFirst;
    /** The last port in the range (inclusive). */
    RTGCPHYS                    GCPhysLast;
    /** The registration handle/index.
     * @todo bake this into the lower/upper bits of GCPhysFirst & GCPhysLast. */
    uint16_t                    idx;
    uint16_t                    abPadding[3];
} IOMMMIOLOOKUPENTRY;
/** Pointer to an MMIO lookup table entry. */
typedef IOMMMIOLOOKUPENTRY *PIOMMMIOLOOKUPENTRY;
/** Pointer to a const MMIO lookup table entry. */
typedef IOMMMIOLOOKUPENTRY const *PCIOMMMIOLOOKUPENTRY;

/**
 * Ring-0 MMIO handle table entry.
 */
typedef struct IOMMMIOENTRYR0
{
    /** The number of bytes covered by this entry, 0 if entry not used. */
    RTGCPHYS                            cbRegion;
    /** Pointer to user argument. */
    RTR0PTR                             pvUser;
    /** Pointer to the associated device instance, NULL if entry not used. */
    R0PTRTYPE(PPDMDEVINS)               pDevIns;
    /** Pointer to the write callback function. */
    R0PTRTYPE(PFNIOMMMIONEWWRITE)       pfnWriteCallback;
    /** Pointer to the read callback function. */
    R0PTRTYPE(PFNIOMMMIONEWREAD)        pfnReadCallback;
    /** Pointer to the fill callback function. */
    R0PTRTYPE(PFNIOMMMIONEWFILL)        pfnFillCallback;
    /** The entry of the first statistics entry, UINT16_MAX if no stats.
     * @note For simplicity, this is always copied from ring-3 for all entries at
     *       the end of VM creation. */
    uint16_t                            idxStats;
    /** Same as the handle index. */
    uint16_t                            idxSelf;
    /** IOM_MMIO_F_XXX (copied from ring-3). */
    uint32_t                            fFlags;
} IOMMMIOENTRYR0;
/** Pointer to a ring-0 MMIO handle table entry. */
typedef IOMMMIOENTRYR0 *PIOMMMIOENTRYR0;
/** Pointer to a const ring-0 MMIO handle table entry. */
typedef IOMMMIOENTRYR0 const *PCIOMMMIOENTRYR0;

/**
 * Ring-3 MMIO handle table entry.
 */
typedef struct IOMMMIOENTRYR3
{
    /** The number of bytes covered by this entry. */
    RTGCPHYS                            cbRegion;
    /** The current mapping address (duplicates lookup table).
     * This is set to NIL_RTGCPHYS if not mapped (exclusive lock + atomic). */
    RTGCPHYS volatile                   GCPhysMapping;
    /** Pointer to user argument. */
    RTR3PTR                             pvUser;
    /** Pointer to the associated device instance. */
    R3PTRTYPE(PPDMDEVINS)               pDevIns;
    /** Pointer to the write callback function. */
    R3PTRTYPE(PFNIOMMMIONEWWRITE)       pfnWriteCallback;
    /** Pointer to the read callback function. */
    R3PTRTYPE(PFNIOMMMIONEWREAD)        pfnReadCallback;
    /** Pointer to the fill callback function. */
    R3PTRTYPE(PFNIOMMMIONEWFILL)        pfnFillCallback;
    /** Description / Name. For easing debugging. */
    R3PTRTYPE(const char *)             pszDesc;
    /** PCI device the registration is associated with. */
    R3PTRTYPE(PPDMPCIDEV)               pPciDev;
    /** The PCI device region (high 16-bit word) and subregion (low word),
     *  UINT32_MAX if not applicable. */
    uint32_t                            iPciRegion;
    /** IOM_MMIO_F_XXX */
    uint32_t                            fFlags;
    /** The entry of the first statistics entry, UINT16_MAX if no stats. */
    uint16_t                            idxStats;
    /** Set if mapped, clear if not.
     * Only updated when critsect is held exclusively.
     * @todo remove as GCPhysMapping != NIL_RTGCPHYS serves the same purpose. */
    bool volatile                       fMapped;
    /** Set if there is an ring-0 entry too. */
    bool                                fRing0;
    /** Set if there is an raw-mode entry too. */
    bool                                fRawMode;
    uint8_t                             bPadding;
    /** Same as the handle index. */
    uint16_t                            idxSelf;
} IOMMMIOENTRYR3;
AssertCompileSize(IOMMMIOENTRYR3, sizeof(RTGCPHYS) * 2 + 7 * sizeof(RTR3PTR) + 16);
/** Pointer to a ring-3 MMIO handle table entry. */
typedef IOMMMIOENTRYR3 *PIOMMMIOENTRYR3;
/** Pointer to a const ring-3 MMIO handle table entry. */
typedef IOMMMIOENTRYR3 const *PCIOMMMIOENTRYR3;

/**
 * MMIO statistics entry (one MMIO).
 */
typedef struct IOMMMIOSTATSENTRY
{
    /** Counting and profiling reads in R0/RC. */
    STAMPROFILE                 ProfReadRZ;
    /** Number of successful read accesses. */
    STAMCOUNTER                 Reads;
    /** Number of reads to this address from R0/RC which was serviced in R3. */
    STAMCOUNTER                 ReadRZToR3;
    /** Number of complicated reads. */
    STAMCOUNTER                 ComplicatedReads;
    /** Number of reads of 0xff or 0x00. */
    STAMCOUNTER                 FFor00Reads;
    /** Profiling read handler overhead in R3. */
    STAMPROFILE                 ProfReadR3;

    /** Counting and profiling writes in R0/RC. */
    STAMPROFILE                 ProfWriteRZ;
    /** Number of successful read accesses. */
    STAMCOUNTER                 Writes;
    /** Number of writes to this address from R0/RC which was serviced in R3. */
    STAMCOUNTER                 WriteRZToR3;
    /** Number of writes to this address from R0/RC which was committed in R3. */
    STAMCOUNTER                 CommitRZToR3;
    /** Number of complicated writes. */
    STAMCOUNTER                 ComplicatedWrites;
    /** Profiling write handler overhead in R3. */
    STAMPROFILE                 ProfWriteR3;
} IOMMMIOSTATSENTRY;
/** Pointer to MMIO statistics entry. */
typedef IOMMMIOSTATSENTRY *PIOMMMIOSTATSENTRY;


/**
 * IOM per virtual CPU instance data.
 */
typedef struct IOMCPU
{
    /** For saving stack space, the disassembler state is allocated here instead of
     * on the stack. */
    DISCPUSTATE                     DisState;

    /**
     * Pending I/O port write commit (VINF_IOM_R3_IOPORT_COMMIT_WRITE).
     *
     * This is a converted VINF_IOM_R3_IOPORT_WRITE handler return that lets the
     * execution engine commit the instruction and then return to ring-3 to complete
     * the I/O port write there.  This avoids having to decode the instruction again
     * in ring-3.
     */
    struct
    {
        /** The value size (0 if not pending). */
        uint16_t                        cbValue;
        /** The I/O port. */
        RTIOPORT                        IOPort;
        /** The value. */
        uint32_t                        u32Value;
    } PendingIOPortWrite;

    /**
     * Pending MMIO write commit (VINF_IOM_R3_MMIO_COMMIT_WRITE).
     *
     * This is a converted VINF_IOM_R3_MMIO_WRITE handler return that lets the
     * execution engine commit the instruction, stop any more REPs, and return to
     * ring-3 to complete the MMIO write there.  The avoid the tedious decoding of
     * the instruction again once we're in ring-3, more importantly it allows us to
     * correctly deal with read-modify-write instructions like XCHG, OR, and XOR.
     */
    struct
    {
        /** Guest physical MMIO address. */
        RTGCPHYS                        GCPhys;
        /** The number of bytes to write (0 if nothing pending). */
        uint32_t                        cbValue;
        /** Hint. */
        uint32_t                        idxMmioRegionHint;
        /** The value to write. */
        uint8_t                         abValue[128];
    } PendingMmioWrite;

    /** @name Caching of I/O Port and MMIO ranges and statistics.
     * (Saves quite some time in rep outs/ins instruction emulation.)
     * @{ */
    /** I/O port registration index for the last read operation. */
    uint16_t                            idxIoPortLastRead;
    /** I/O port registration index for the last write operation. */
    uint16_t                            idxIoPortLastWrite;
    /** I/O port registration index for the last read string operation. */
    uint16_t                            idxIoPortLastReadStr;
    /** I/O port registration index for the last write string operation. */
    uint16_t                            idxIoPortLastWriteStr;

    /** MMIO port registration index for the last IOMR3MmioPhysHandler call.
     * @note pretty static as only used by APIC on AMD-V.  */
    uint16_t                            idxMmioLastPhysHandler;
    uint16_t                            au16Padding[3];
    /** @} */
} IOMCPU;
/** Pointer to IOM per virtual CPU instance data. */
typedef IOMCPU *PIOMCPU;


/**
 * IOM Data (part of VM)
 */
typedef struct IOM
{
    /** @name I/O ports
     * @note The updating of these variables is done exclusively from EMT(0).
     * @{ */
    /** Number of I/O port registrations. */
    uint32_t                        cIoPortRegs;
    /** The size of the paIoPortRegs allocation (in entries). */
    uint32_t                        cIoPortAlloc;
    /** I/O port registration table for ring-3.
     * There is a parallel table in ring-0, IOMR0PERVM::paIoPortRegs. */
    R3PTRTYPE(PIOMIOPORTENTRYR3)    paIoPortRegs;
    /** Number of entries in the lookup table. */
    uint32_t                        cIoPortLookupEntries;
    uint32_t                        u32Padding1;
    /** I/O port lookup table. */
    R3PTRTYPE(PIOMIOPORTLOOKUPENTRY) paIoPortLookup;

    /** The number of valid entries in paioPortStats. */
    uint32_t                        cIoPortStats;
    /** The size of the paIoPortStats allocation (in entries). */
    uint32_t                        cIoPortStatsAllocation;
    /** I/O port lookup table.   */
    R3PTRTYPE(PIOMIOPORTSTATSENTRY) paIoPortStats;
    /** Dummy stats entry so we don't need to check for NULL pointers so much. */
    IOMIOPORTSTATSENTRY             IoPortDummyStats;
    /** @} */

    /** @name MMIO ports
     * @note The updating of these variables is done exclusively from EMT(0).
     * @{ */
    /** MMIO physical access handler type, new style.   */
    PGMPHYSHANDLERTYPE              hNewMmioHandlerType;
    /** Number of MMIO registrations. */
    uint32_t                        cMmioRegs;
    /** The size of the paMmioRegs allocation (in entries). */
    uint32_t                        cMmioAlloc;
    /** MMIO registration table for ring-3.
     * There is a parallel table in ring-0, IOMR0PERVM::paMmioRegs. */
    R3PTRTYPE(PIOMMMIOENTRYR3)      paMmioRegs;
    /** Number of entries in the lookup table. */
    uint32_t                        cMmioLookupEntries;
    uint32_t                        u32Padding2;
    /** MMIO lookup table. */
    R3PTRTYPE(PIOMMMIOLOOKUPENTRY)  paMmioLookup;

    /** The number of valid entries in paioPortStats. */
    uint32_t                        cMmioStats;
    /** The size of the paMmioStats allocation (in entries). */
    uint32_t                        cMmioStatsAllocation;
    /** MMIO lookup table.   */
    R3PTRTYPE(PIOMMMIOSTATSENTRY)   paMmioStats;
    /** Dummy stats entry so we don't need to check for NULL pointers so much. */
    IOMMMIOSTATSENTRY               MmioDummyStats;
    /** @} */


    /** Lock serializing EMT access to IOM. */
#ifdef IOM_WITH_CRIT_SECT_RW
    PDMCRITSECTRW                   CritSect;
#else
    PDMCRITSECT                     CritSect;
#endif

    /** @name I/O Port statistics.
     * @{ */
    STAMCOUNTER                     StatIoPortIn;
    STAMCOUNTER                     StatIoPortOut;
    STAMCOUNTER                     StatIoPortInS;
    STAMCOUNTER                     StatIoPortOutS;
    STAMCOUNTER                     StatIoPortCommits;
    /** @} */

    /** @name MMIO statistics.
     * @{ */
    STAMPROFILE                     StatMmioPfHandler;
    STAMPROFILE                     StatMmioPhysHandler;
    STAMCOUNTER                     StatMmioHandlerR3;
    STAMCOUNTER                     StatMmioHandlerR0;
    STAMCOUNTER                     StatMmioReadsR0ToR3;
    STAMCOUNTER                     StatMmioWritesR0ToR3;
    STAMCOUNTER                     StatMmioCommitsR0ToR3;
    STAMCOUNTER                     StatMmioCommitsDirect;
    STAMCOUNTER                     StatMmioCommitsPgm;
    STAMCOUNTER                     StatMmioStaleMappings;
    STAMCOUNTER                     StatMmioDevLockContentionR0;
    /** @} */
} IOM;
/** Pointer to IOM instance data. */
typedef IOM *PIOM;


/**
 * IOM data kept in the ring-0 GVM.
 */
typedef struct IOMR0PERVM
{
    /** @name I/O ports
     * @{ */
    /** The higest ring-0 I/O port registration plus one. */
    uint32_t                        cIoPortMax;
    /** The size of the paIoPortRegs allocation (in entries). */
    uint32_t                        cIoPortAlloc;
    /** I/O port registration table for ring-0.
     * There is a parallel table for ring-3, paIoPortRing3Regs. */
    R0PTRTYPE(PIOMIOPORTENTRYR0)    paIoPortRegs;
    /** I/O port lookup table. */
    R0PTRTYPE(PIOMIOPORTLOOKUPENTRY) paIoPortLookup;
    /** I/O port registration table for ring-3.
     * Also mapped to ring-3 as IOM::paIoPortRegs. */
    R0PTRTYPE(PIOMIOPORTENTRYR3)    paIoPortRing3Regs;
    /** Handle to the allocation backing both the ring-0 and ring-3 registration
     * tables as well as the lookup table. */
    RTR0MEMOBJ                      hIoPortMemObj;
    /** Handle to the ring-3 mapping of the lookup and ring-3 registration table. */
    RTR0MEMOBJ                      hIoPortMapObj;
#ifdef VBOX_WITH_STATISTICS
    /** The size of the paIoPortStats allocation (in entries). */
    uint32_t                        cIoPortStatsAllocation;
    /** Prevents paIoPortStats from growing, set by IOMR0IoPortSyncStatisticsIndices(). */
    bool                            fIoPortStatsFrozen;
    /** I/O port lookup table.   */
    R0PTRTYPE(PIOMIOPORTSTATSENTRY) paIoPortStats;
    /** Handle to the allocation backing the I/O port statistics. */
    RTR0MEMOBJ                      hIoPortStatsMemObj;
    /** Handle to the ring-3 mapping of the I/O port statistics. */
    RTR0MEMOBJ                      hIoPortStatsMapObj;
#endif
    /** @} */

    /** @name MMIO
     * @{ */
    /** The higest ring-0 MMIO registration plus one. */
    uint32_t                        cMmioMax;
    /** The size of the paMmioRegs allocation (in entries). */
    uint32_t                        cMmioAlloc;
    /** MMIO registration table for ring-0.
     * There is a parallel table for ring-3, paMmioRing3Regs. */
    R0PTRTYPE(PIOMMMIOENTRYR0)      paMmioRegs;
    /** MMIO lookup table. */
    R0PTRTYPE(PIOMMMIOLOOKUPENTRY)  paMmioLookup;
    /** MMIO registration table for ring-3.
     * Also mapped to ring-3 as IOM::paMmioRegs. */
    R0PTRTYPE(PIOMMMIOENTRYR3)      paMmioRing3Regs;
    /** Handle to the allocation backing both the ring-0 and ring-3 registration
     * tables as well as the lookup table. */
    RTR0MEMOBJ                      hMmioMemObj;
    /** Handle to the ring-3 mapping of the lookup and ring-3 registration table. */
    RTR0MEMOBJ                      hMmioMapObj;
#ifdef VBOX_WITH_STATISTICS
    /** The size of the paMmioStats allocation (in entries). */
    uint32_t                        cMmioStatsAllocation;
    /* Prevents paMmioStats from growing, set by IOMR0MmioSyncStatisticsIndices(). */
    bool                            fMmioStatsFrozen;
    /** MMIO lookup table.   */
    R0PTRTYPE(PIOMMMIOSTATSENTRY)   paMmioStats;
    /** Handle to the allocation backing the MMIO statistics. */
    RTR0MEMOBJ                      hMmioStatsMemObj;
    /** Handle to the ring-3 mapping of the MMIO statistics. */
    RTR0MEMOBJ                      hMmioStatsMapObj;
#endif
    /** @} */

} IOMR0PERVM;


RT_C_DECLS_BEGIN

#ifdef IN_RING3
DECLCALLBACK(void)  iomR3IoPortInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
void                iomR3IoPortRegStats(PVM pVM, PIOMIOPORTENTRYR3 pRegEntry);
DECLCALLBACK(void)  iomR3MmioInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
void                iomR3MmioRegStats(PVM pVM, PIOMMMIOENTRYR3 pRegEntry);
VBOXSTRICTRC        iomR3MmioCommitWorker(PVM pVM, PVMCPU pVCpu, PIOMMMIOENTRYR3 pRegEntry, RTGCPHYS offRegion); /* IOMAllMmioNew.cpp */
#endif /* IN_RING3 */
#ifdef IN_RING0
void                iomR0IoPortCleanupVM(PGVM pGVM);
void                iomR0IoPortInitPerVMData(PGVM pGVM);
void                iomR0MmioCleanupVM(PGVM pGVM);
void                iomR0MmioInitPerVMData(PGVM pGVM);
#endif

#ifndef IN_RING3
DECLEXPORT(FNPGMRZPHYSPFHANDLER)    iomMmioPfHandlerNew;
#endif
PGM_ALL_CB2_PROTO(FNPGMPHYSHANDLER) iomMmioHandlerNew;

/* IOM locking helpers. */
#ifdef IOM_WITH_CRIT_SECT_RW
# define IOM_LOCK_EXCL(a_pVM)                   PDMCritSectRwEnterExcl(&(a_pVM)->iom.s.CritSect, VERR_SEM_BUSY)
# define IOM_UNLOCK_EXCL(a_pVM)                 do { PDMCritSectRwLeaveExcl(&(a_pVM)->iom.s.CritSect); } while (0)
# if 0 /* (in case needed for debugging) */
# define IOM_LOCK_SHARED_EX(a_pVM, a_rcBusy)    PDMCritSectRwEnterExcl(&(a_pVM)->iom.s.CritSect, (a_rcBusy))
# define IOM_UNLOCK_SHARED(a_pVM)               do { PDMCritSectRwLeaveExcl(&(a_pVM)->iom.s.CritSect); } while (0)
# define IOM_IS_SHARED_LOCK_OWNER(a_pVM)        PDMCritSectRwIsWriteOwner(&(a_pVM)->iom.s.CritSect)
# else
# define IOM_LOCK_SHARED_EX(a_pVM, a_rcBusy)    PDMCritSectRwEnterShared(&(a_pVM)->iom.s.CritSect, (a_rcBusy))
# define IOM_UNLOCK_SHARED(a_pVM)               do { PDMCritSectRwLeaveShared(&(a_pVM)->iom.s.CritSect); } while (0)
# define IOM_IS_SHARED_LOCK_OWNER(a_pVM)        PDMCritSectRwIsReadOwner(&(a_pVM)->iom.s.CritSect, true)
# endif
# define IOM_IS_EXCL_LOCK_OWNER(a_pVM)          PDMCritSectRwIsWriteOwner(&(a_pVM)->iom.s.CritSect)
#else
# define IOM_LOCK_EXCL(a_pVM)                   PDMCritSectEnter(&(a_pVM)->iom.s.CritSect, VERR_SEM_BUSY)
# define IOM_UNLOCK_EXCL(a_pVM)                 do { PDMCritSectLeave(&(a_pVM)->iom.s.CritSect); } while (0)
# define IOM_LOCK_SHARED_EX(a_pVM, a_rcBusy)    PDMCritSectEnter(&(a_pVM)->iom.s.CritSect, (a_rcBusy))
# define IOM_UNLOCK_SHARED(a_pVM)               do { PDMCritSectLeave(&(a_pVM)->iom.s.CritSect); } while (0)
# define IOM_IS_SHARED_LOCK_OWNER(a_pVM)        PDMCritSectIsOwner(&(a_pVM)->iom.s.CritSect)
# define IOM_IS_EXCL_LOCK_OWNER(a_pVM)          PDMCritSectIsOwner(&(a_pVM)->iom.s.CritSect)
#endif
#define IOM_LOCK_SHARED(a_pVM)                  IOM_LOCK_SHARED_EX(a_pVM, VERR_SEM_BUSY)


RT_C_DECLS_END


#ifdef IN_RING3

#endif

/** @} */

#endif /* !VMM_INCLUDED_SRC_include_IOMInternal_h */