VirtualBox

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

最後變更 在這個檔案從81605是 81463,由 vboxsync 提交於 5 年 前

IOM: Commit stats. bugref:9218

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id Revision
檔案大小: 35.9 KB
 
1/* $Id: IOMInternal.h 81463 2019-10-23 00:56:39Z 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.alldomusa.eu.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 * @note For simplicity, this is always copied from ring-3 for all entries at
311 * the end of VM creation. */
312 uint16_t idxStats;
313 /** Same as the handle index. */
314 uint16_t idxSelf;
315 /** IOM_MMIO_F_XXX (copied from ring-3). */
316 uint32_t fFlags;
317} IOMMMIOENTRYR0;
318/** Pointer to a ring-0 MMIO handle table entry. */
319typedef IOMMMIOENTRYR0 *PIOMMMIOENTRYR0;
320/** Pointer to a const ring-0 MMIO handle table entry. */
321typedef IOMMMIOENTRYR0 const *PCIOMMMIOENTRYR0;
322
323/**
324 * Ring-3 MMIO handle table entry.
325 */
326typedef struct IOMMMIOENTRYR3
327{
328 /** The number of bytes covered by this entry. */
329 RTGCPHYS cbRegion;
330 /** The current mapping address (duplicates lookup table).
331 * This is set to NIL_RTGCPHYS if not mapped (exclusive lock + atomic). */
332 RTGCPHYS volatile GCPhysMapping;
333 /** Pointer to user argument. */
334 RTR3PTR pvUser;
335 /** Pointer to the associated device instance. */
336 R3PTRTYPE(PPDMDEVINS) pDevIns;
337 /** Pointer to the write callback function. */
338 R3PTRTYPE(PFNIOMMMIONEWWRITE) pfnWriteCallback;
339 /** Pointer to the read callback function. */
340 R3PTRTYPE(PFNIOMMMIONEWREAD) pfnReadCallback;
341 /** Pointer to the fill callback function. */
342 R3PTRTYPE(PFNIOMMMIONEWFILL) pfnFillCallback;
343 /** Description / Name. For easing debugging. */
344 R3PTRTYPE(const char *) pszDesc;
345 /** PCI device the registration is associated with. */
346 R3PTRTYPE(PPDMPCIDEV) pPciDev;
347 /** The PCI device region (high 16-bit word) and subregion (low word),
348 * UINT32_MAX if not applicable. */
349 uint32_t iPciRegion;
350 /** IOM_MMIO_F_XXX */
351 uint32_t fFlags;
352 /** The entry of the first statistics entry, UINT16_MAX if no stats. */
353 uint16_t idxStats;
354 /** Set if mapped, clear if not.
355 * Only updated when critsect is held exclusively.
356 * @todo remove as GCPhysMapping != NIL_RTGCPHYS serves the same purpose. */
357 bool volatile fMapped;
358 /** Set if there is an ring-0 entry too. */
359 bool fRing0;
360 /** Set if there is an raw-mode entry too. */
361 bool fRawMode;
362 uint8_t bPadding;
363 /** Same as the handle index. */
364 uint16_t idxSelf;
365} IOMMMIOENTRYR3;
366AssertCompileSize(IOMMMIOENTRYR3, sizeof(RTGCPHYS) * 2 + 7 * sizeof(RTR3PTR) + 16);
367/** Pointer to a ring-3 MMIO handle table entry. */
368typedef IOMMMIOENTRYR3 *PIOMMMIOENTRYR3;
369/** Pointer to a const ring-3 MMIO handle table entry. */
370typedef IOMMMIOENTRYR3 const *PCIOMMMIOENTRYR3;
371
372/**
373 * MMIO statistics entry (one MMIO).
374 */
375typedef struct IOMMMIOSTATSENTRY
376{
377 /** Counting and profiling reads in R0/RC. */
378 STAMPROFILE ProfReadRZ;
379 /** Number of successful read accesses. */
380 STAMCOUNTER Reads;
381 /** Number of reads to this address from R0/RC which was serviced in R3. */
382 STAMCOUNTER ReadRZToR3;
383 /** Number of complicated reads. */
384 STAMCOUNTER ComplicatedReads;
385 /** Number of reads of 0xff or 0x00. */
386 STAMCOUNTER FFor00Reads;
387 /** Profiling read handler overhead in R3. */
388 STAMPROFILE ProfReadR3;
389
390 /** Counting and profiling writes in R0/RC. */
391 STAMPROFILE ProfWriteRZ;
392 /** Number of successful read accesses. */
393 STAMCOUNTER Writes;
394 /** Number of writes to this address from R0/RC which was serviced in R3. */
395 STAMCOUNTER WriteRZToR3;
396 /** Number of writes to this address from R0/RC which was committed in R3. */
397 STAMCOUNTER CommitRZToR3;
398 /** Number of complicated writes. */
399 STAMCOUNTER ComplicatedWrites;
400 /** Profiling write handler overhead in R3. */
401 STAMPROFILE ProfWriteR3;
402} IOMMMIOSTATSENTRY;
403/** Pointer to MMIO statistics entry. */
404typedef IOMMMIOSTATSENTRY *PIOMMMIOSTATSENTRY;
405
406
407
408/**
409 * I/O port range descriptor, R3 version.
410 */
411typedef struct IOMIOPORTRANGER3
412{
413 /** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */
414 AVLROIOPORTNODECORE Core;
415#if HC_ARCH_BITS == 64 && !defined(RT_OS_WINDOWS)
416 uint32_t u32Alignment; /**< The sizeof(Core) differs. */
417#endif
418 /** Start I/O port address. */
419 RTIOPORT Port;
420 /** Size of the range. */
421 uint16_t cPorts;
422 /** Pointer to user argument. */
423 RTR3PTR pvUser;
424 /** Pointer to the associated device instance. */
425 R3PTRTYPE(PPDMDEVINS) pDevIns;
426 /** Pointer to OUT callback function. */
427 R3PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback;
428 /** Pointer to IN callback function. */
429 R3PTRTYPE(PFNIOMIOPORTIN) pfnInCallback;
430 /** Pointer to string OUT callback function. */
431 R3PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;
432 /** Pointer to string IN callback function. */
433 R3PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;
434 /** Description / Name. For easing debugging. */
435 R3PTRTYPE(const char *) pszDesc;
436} IOMIOPORTRANGER3;
437/** Pointer to I/O port range descriptor, R3 version. */
438typedef IOMIOPORTRANGER3 *PIOMIOPORTRANGER3;
439
440/**
441 * I/O port range descriptor, R0 version.
442 */
443typedef struct IOMIOPORTRANGER0
444{
445 /** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */
446 AVLROIOPORTNODECORE Core;
447#if HC_ARCH_BITS == 64 && !defined(RT_OS_WINDOWS)
448 uint32_t u32Alignment; /**< The sizeof(Core) differs. */
449#endif
450 /** Start I/O port address. */
451 RTIOPORT Port;
452 /** Size of the range. */
453 uint16_t cPorts;
454 /** Pointer to user argument. */
455 RTR0PTR pvUser;
456 /** Pointer to the associated device instance. */
457 R0PTRTYPE(PPDMDEVINS) pDevIns;
458 /** Pointer to OUT callback function. */
459 R0PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback;
460 /** Pointer to IN callback function. */
461 R0PTRTYPE(PFNIOMIOPORTIN) pfnInCallback;
462 /** Pointer to string OUT callback function. */
463 R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;
464 /** Pointer to string IN callback function. */
465 R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;
466 /** Description / Name. For easing debugging. */
467 R3PTRTYPE(const char *) pszDesc;
468} IOMIOPORTRANGER0;
469/** Pointer to I/O port range descriptor, R0 version. */
470typedef IOMIOPORTRANGER0 *PIOMIOPORTRANGER0;
471
472/**
473 * I/O port range descriptor, RC version.
474 */
475typedef struct IOMIOPORTRANGERC
476{
477 /** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */
478 AVLROIOPORTNODECORE Core;
479 /** Start I/O port address. */
480 RTIOPORT Port;
481 /** Size of the range. */
482 uint16_t cPorts;
483 /** Pointer to user argument. */
484 RTRCPTR pvUser;
485 /** Pointer to the associated device instance. */
486 RCPTRTYPE(PPDMDEVINS) pDevIns;
487 /** Pointer to OUT callback function. */
488 RCPTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback;
489 /** Pointer to IN callback function. */
490 RCPTRTYPE(PFNIOMIOPORTIN) pfnInCallback;
491 /** Pointer to string OUT callback function. */
492 RCPTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;
493 /** Pointer to string IN callback function. */
494 RCPTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;
495#if HC_ARCH_BITS == 64
496 RTRCPTR RCPtrAlignment; /**< pszDesc is 8 byte aligned. */
497#endif
498 /** Description / Name. For easing debugging. */
499 R3PTRTYPE(const char *) pszDesc;
500} IOMIOPORTRANGERC;
501/** Pointer to I/O port range descriptor, RC version. */
502typedef IOMIOPORTRANGERC *PIOMIOPORTRANGERC;
503
504
505/**
506 * I/O port statistics. (one I/O port)
507 *
508 * This is a simple way of making on demand statistics, however it's a
509 * bit free with the hypervisor heap memory.
510 */
511typedef struct IOMIOPORTSTATS
512{
513 /** Avl node core with the port as Key. */
514 AVLOIOPORTNODECORE Core;
515#if HC_ARCH_BITS != 64 || !defined(RT_OS_WINDOWS)
516 uint32_t u32Alignment; /**< The sizeof(Core) differs. */
517#endif
518 /** Number of INs to this port from R3. */
519 STAMCOUNTER InR3;
520 /** Profiling IN handler overhead in R3. */
521 STAMPROFILE ProfInR3;
522 /** Number of OUTs to this port from R3. */
523 STAMCOUNTER OutR3;
524 /** Profiling OUT handler overhead in R3. */
525 STAMPROFILE ProfOutR3;
526
527 /** Number of INs to this port from R0/RC. */
528 STAMCOUNTER InRZ;
529 /** Profiling IN handler overhead in R0/RC. */
530 STAMPROFILE ProfInRZ;
531 /** Number of INs to this port from R0/RC which was serviced in R3. */
532 STAMCOUNTER InRZToR3;
533
534 /** Number of OUTs to this port from R0/RC. */
535 STAMCOUNTER OutRZ;
536 /** Profiling OUT handler overhead in R0/RC. */
537 STAMPROFILE ProfOutRZ;
538 /** Number of OUTs to this port from R0/RC which was serviced in R3. */
539 STAMCOUNTER OutRZToR3;
540} IOMIOPORTSTATS;
541AssertCompileMemberAlignment(IOMIOPORTSTATS, InR3, 8);
542/** Pointer to I/O port statistics. */
543typedef IOMIOPORTSTATS *PIOMIOPORTSTATS;
544
545
546/**
547 * The IOM trees.
548 *
549 * These are offset based the nodes and root must be in the same
550 * memory block in HC. The locations of IOM structure and the hypervisor heap
551 * are quite different in R3, R0 and RC.
552 */
553typedef struct IOMTREES
554{
555 /** Tree containing I/O port range descriptors registered for HC (IOMIOPORTRANGEHC). */
556 AVLROIOPORTTREE IOPortTreeR3;
557 /** Tree containing I/O port range descriptors registered for R0 (IOMIOPORTRANGER0). */
558 AVLROIOPORTTREE IOPortTreeR0;
559#if 0
560 /** Tree containing I/O port range descriptors registered for RC (IOMIOPORTRANGERC). */
561 AVLROIOPORTTREE IOPortTreeRC;
562#endif
563
564 /** Tree containing the MMIO range descriptors (IOMMMIORANGE). */
565 AVLROGCPHYSTREE MMIOTree;
566
567 /** Tree containing I/O port statistics (IOMIOPORTSTATS). */
568 AVLOIOPORTTREE IOPortStatTree;
569 /** Tree containing MMIO statistics (IOMMMIOSTATS). */
570 AVLOGCPHYSTREE MmioStatTree;
571} IOMTREES;
572/** Pointer to the IOM trees. */
573typedef IOMTREES *PIOMTREES;
574
575
576/**
577 * IOM per virtual CPU instance data.
578 */
579typedef struct IOMCPU
580{
581 /** For saving stack space, the disassembler state is allocated here instead of
582 * on the stack. */
583 DISCPUSTATE DisState;
584
585 /**
586 * Pending I/O port write commit (VINF_IOM_R3_IOPORT_COMMIT_WRITE).
587 *
588 * This is a converted VINF_IOM_R3_IOPORT_WRITE handler return that lets the
589 * execution engine commit the instruction and then return to ring-3 to complete
590 * the I/O port write there. This avoids having to decode the instruction again
591 * in ring-3.
592 */
593 struct
594 {
595 /** The value size (0 if not pending). */
596 uint16_t cbValue;
597 /** The I/O port. */
598 RTIOPORT IOPort;
599 /** The value. */
600 uint32_t u32Value;
601 } PendingIOPortWrite;
602
603 /**
604 * Pending MMIO write commit (VINF_IOM_R3_MMIO_COMMIT_WRITE).
605 *
606 * This is a converted VINF_IOM_R3_MMIO_WRITE handler return that lets the
607 * execution engine commit the instruction, stop any more REPs, and return to
608 * ring-3 to complete the MMIO write there. The avoid the tedious decoding of
609 * the instruction again once we're in ring-3, more importantly it allows us to
610 * correctly deal with read-modify-write instructions like XCHG, OR, and XOR.
611 */
612 struct
613 {
614 /** Guest physical MMIO address. */
615 RTGCPHYS GCPhys;
616 /** The number of bytes to write (0 if nothing pending). */
617 uint32_t cbValue;
618 /** Hint. */
619 uint32_t idxMmioRegionHint;
620 /** The value to write. */
621 uint8_t abValue[128];
622 } PendingMmioWrite;
623
624 /** @name Caching of I/O Port and MMIO ranges and statistics.
625 * (Saves quite some time in rep outs/ins instruction emulation.)
626 * @{ */
627 /** I/O port registration index for the last read operation. */
628 uint16_t idxIoPortLastRead;
629 /** I/O port registration index for the last write operation. */
630 uint16_t idxIoPortLastWrite;
631 /** I/O port registration index for the last read string operation. */
632 uint16_t idxIoPortLastReadStr;
633 /** I/O port registration index for the last write string operation. */
634 uint16_t idxIoPortLastWriteStr;
635
636 /** MMIO port registration index for the last IOMR3MmioPhysHandler call.
637 * @note pretty static as only used by APIC on AMD-V. */
638 uint16_t idxMmioLastPhysHandler;
639 uint16_t u16Padding;
640
641 R3PTRTYPE(PIOMIOPORTRANGER3) pRangeLastReadR3;
642 R3PTRTYPE(PIOMIOPORTRANGER3) pRangeLastWriteR3;
643 R3PTRTYPE(PIOMIOPORTSTATS) pStatsLastReadR3;
644 R3PTRTYPE(PIOMIOPORTSTATS) pStatsLastWriteR3;
645 R3PTRTYPE(PIOMMMIORANGE) pMMIORangeLastR3;
646 R3PTRTYPE(PIOMMMIOSTATS) pMMIOStatsLastR3;
647
648 R0PTRTYPE(PIOMIOPORTRANGER0) pRangeLastReadR0;
649 R0PTRTYPE(PIOMIOPORTRANGER0) pRangeLastWriteR0;
650 R0PTRTYPE(PIOMIOPORTSTATS) pStatsLastReadR0;
651 R0PTRTYPE(PIOMIOPORTSTATS) pStatsLastWriteR0;
652 R0PTRTYPE(PIOMMMIORANGE) pMMIORangeLastR0;
653 R0PTRTYPE(PIOMMMIOSTATS) pMMIOStatsLastR0;
654 /** @} */
655} IOMCPU;
656/** Pointer to IOM per virtual CPU instance data. */
657typedef IOMCPU *PIOMCPU;
658
659
660/**
661 * IOM Data (part of VM)
662 */
663typedef struct IOM
664{
665 /** Pointer to the trees - R3 ptr. */
666 R3PTRTYPE(PIOMTREES) pTreesR3;
667 /** Pointer to the trees - R0 ptr. */
668 R0PTRTYPE(PIOMTREES) pTreesR0;
669
670 /** MMIO physical access handler type. */
671 PGMPHYSHANDLERTYPE hMmioHandlerType;
672 /** MMIO physical access handler type, new style. */
673 PGMPHYSHANDLERTYPE hNewMmioHandlerType;
674
675 /** @name I/O ports
676 * @note The updating of these variables is done exclusively from EMT(0).
677 * @{ */
678 /** Number of I/O port registrations. */
679 uint32_t cIoPortRegs;
680 /** The size of the paIoPortRegs allocation (in entries). */
681 uint32_t cIoPortAlloc;
682 /** I/O port registration table for ring-3.
683 * There is a parallel table in ring-0, IOMR0PERVM::paIoPortRegs. */
684 R3PTRTYPE(PIOMIOPORTENTRYR3) paIoPortRegs;
685 /** Number of entries in the lookup table. */
686 uint32_t cIoPortLookupEntries;
687 uint32_t u32Padding1;
688 /** I/O port lookup table. */
689 R3PTRTYPE(PIOMIOPORTLOOKUPENTRY) paIoPortLookup;
690
691 /** The number of valid entries in paioPortStats. */
692 uint32_t cIoPortStats;
693 /** The size of the paIoPortStats allocation (in entries). */
694 uint32_t cIoPortStatsAllocation;
695 /** I/O port lookup table. */
696 R3PTRTYPE(PIOMIOPORTSTATSENTRY) paIoPortStats;
697 /** Dummy stats entry so we don't need to check for NULL pointers so much. */
698 IOMIOPORTSTATSENTRY IoPortDummyStats;
699 /** @} */
700
701 /** @name MMIO ports
702 * @note The updating of these variables is done exclusively from EMT(0).
703 * @{ */
704 /** Number of MMIO registrations. */
705 uint32_t cMmioRegs;
706 /** The size of the paMmioRegs allocation (in entries). */
707 uint32_t cMmioAlloc;
708 /** MMIO registration table for ring-3.
709 * There is a parallel table in ring-0, IOMR0PERVM::paMmioRegs. */
710 R3PTRTYPE(PIOMMMIOENTRYR3) paMmioRegs;
711 /** Number of entries in the lookup table. */
712 uint32_t cMmioLookupEntries;
713 uint32_t u32Padding2;
714 /** MMIO lookup table. */
715 R3PTRTYPE(PIOMMMIOLOOKUPENTRY) paMmioLookup;
716
717 /** The number of valid entries in paioPortStats. */
718 uint32_t cMmioStats;
719 /** The size of the paMmioStats allocation (in entries). */
720 uint32_t cMmioStatsAllocation;
721 /** MMIO lookup table. */
722 R3PTRTYPE(PIOMMMIOSTATSENTRY) paMmioStats;
723 /** Dummy stats entry so we don't need to check for NULL pointers so much. */
724 IOMMMIOSTATSENTRY MmioDummyStats;
725 /** @} */
726
727
728 /** Lock serializing EMT access to IOM. */
729#ifdef IOM_WITH_CRIT_SECT_RW
730 PDMCRITSECTRW CritSect;
731#else
732 PDMCRITSECT CritSect;
733#endif
734
735#if 0 /* unused */
736 /** @name I/O Port statistics.
737 * @{ */
738 STAMCOUNTER StatInstIn;
739 STAMCOUNTER StatInstOut;
740 STAMCOUNTER StatInstIns;
741 STAMCOUNTER StatInstOuts;
742 /** @} */
743#endif
744
745 /** @name MMIO statistics.
746 * @{ */
747 STAMCOUNTER StatIoPortCommits;
748
749 STAMCOUNTER StatMMIOStaleMappings;
750 STAMPROFILE StatRZMMIOHandler;
751 STAMCOUNTER StatRZMMIOReadsToR3;
752 STAMCOUNTER StatRZMMIOWritesToR3;
753 STAMCOUNTER StatRZMMIOCommitsToR3;
754 STAMCOUNTER StatRZMMIODevLockContention;
755
756 STAMCOUNTER StatMmioPfHandlerNew;
757 STAMCOUNTER StatMmioPhysHandlerNew;
758 STAMCOUNTER StatMmioHandlerNewR3;
759 STAMCOUNTER StatMmioHandlerNewR0;
760 STAMCOUNTER StatMmioCommitsDirect;
761 STAMCOUNTER StatMmioCommitsPgm;
762
763 STAMCOUNTER StatR3MMIOHandler;
764
765 STAMCOUNTER StatMmioHandlerR3;
766 STAMCOUNTER StatMmioHandlerR0;
767
768 RTUINT cMovsMaxBytes;
769 RTUINT cStosMaxBytes;
770 /** @} */
771} IOM;
772/** Pointer to IOM instance data. */
773typedef IOM *PIOM;
774
775
776/**
777 * IOM data kept in the ring-0 GVM.
778 */
779typedef struct IOMR0PERVM
780{
781 /** @name I/O ports
782 * @{ */
783 /** The higest ring-0 I/O port registration plus one. */
784 uint32_t cIoPortMax;
785 /** The size of the paIoPortRegs allocation (in entries). */
786 uint32_t cIoPortAlloc;
787 /** I/O port registration table for ring-0.
788 * There is a parallel table for ring-3, paIoPortRing3Regs. */
789 R0PTRTYPE(PIOMIOPORTENTRYR0) paIoPortRegs;
790 /** I/O port lookup table. */
791 R0PTRTYPE(PIOMIOPORTLOOKUPENTRY) paIoPortLookup;
792 /** I/O port registration table for ring-3.
793 * Also mapped to ring-3 as IOM::paIoPortRegs. */
794 R0PTRTYPE(PIOMIOPORTENTRYR3) paIoPortRing3Regs;
795 /** Handle to the allocation backing both the ring-0 and ring-3 registration
796 * tables as well as the lookup table. */
797 RTR0MEMOBJ hIoPortMemObj;
798 /** Handle to the ring-3 mapping of the lookup and ring-3 registration table. */
799 RTR0MEMOBJ hIoPortMapObj;
800#ifdef VBOX_WITH_STATISTICS
801 /** The size of the paIoPortStats allocation (in entries). */
802 uint32_t cIoPortStatsAllocation;
803 /** Prevents paIoPortStats from growing, set by IOMR0IoPortSyncStatisticsIndices(). */
804 bool fIoPortStatsFrozen;
805 /** I/O port lookup table. */
806 R0PTRTYPE(PIOMIOPORTSTATSENTRY) paIoPortStats;
807 /** Handle to the allocation backing the I/O port statistics. */
808 RTR0MEMOBJ hIoPortStatsMemObj;
809 /** Handle to the ring-3 mapping of the I/O port statistics. */
810 RTR0MEMOBJ hIoPortStatsMapObj;
811#endif
812 /** @} */
813
814 /** @name MMIO
815 * @{ */
816 /** The higest ring-0 MMIO registration plus one. */
817 uint32_t cMmioMax;
818 /** The size of the paMmioRegs allocation (in entries). */
819 uint32_t cMmioAlloc;
820 /** MMIO registration table for ring-0.
821 * There is a parallel table for ring-3, paMmioRing3Regs. */
822 R0PTRTYPE(PIOMMMIOENTRYR0) paMmioRegs;
823 /** MMIO lookup table. */
824 R0PTRTYPE(PIOMMMIOLOOKUPENTRY) paMmioLookup;
825 /** MMIO registration table for ring-3.
826 * Also mapped to ring-3 as IOM::paMmioRegs. */
827 R0PTRTYPE(PIOMMMIOENTRYR3) paMmioRing3Regs;
828 /** Handle to the allocation backing both the ring-0 and ring-3 registration
829 * tables as well as the lookup table. */
830 RTR0MEMOBJ hMmioMemObj;
831 /** Handle to the ring-3 mapping of the lookup and ring-3 registration table. */
832 RTR0MEMOBJ hMmioMapObj;
833#ifdef VBOX_WITH_STATISTICS
834 /** The size of the paMmioStats allocation (in entries). */
835 uint32_t cMmioStatsAllocation;
836 /* Prevents paMmioStats from growing, set by IOMR0MmioSyncStatisticsIndices(). */
837 bool fMmioStatsFrozen;
838 /** MMIO lookup table. */
839 R0PTRTYPE(PIOMMMIOSTATSENTRY) paMmioStats;
840 /** Handle to the allocation backing the MMIO statistics. */
841 RTR0MEMOBJ hMmioStatsMemObj;
842 /** Handle to the ring-3 mapping of the MMIO statistics. */
843 RTR0MEMOBJ hMmioStatsMapObj;
844#endif
845 /** @} */
846
847} IOMR0PERVM;
848
849
850RT_C_DECLS_BEGIN
851
852void iomMmioFreeRange(PVMCC pVM, PIOMMMIORANGE pRange);
853#ifdef IN_RING3
854PIOMMMIOSTATS iomR3MMIOStatsCreate(PVM pVM, RTGCPHYS GCPhys, const char *pszDesc);
855DECLCALLBACK(void) iomR3IoPortInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
856void iomR3IoPortRegStats(PVM pVM, PIOMIOPORTENTRYR3 pRegEntry);
857DECLCALLBACK(void) iomR3MmioInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
858void iomR3MmioRegStats(PVM pVM, PIOMMMIOENTRYR3 pRegEntry);
859VBOXSTRICTRC iomR3MmioCommitWorker(PVM pVM, PVMCPU pVCpu, PIOMMMIOENTRYR3 pRegEntry, RTGCPHYS offRegion); /* IOMAllMmioNew.cpp */
860#endif /* IN_RING3 */
861#ifdef IN_RING0
862void iomR0IoPortCleanupVM(PGVM pGVM);
863void iomR0IoPortInitPerVMData(PGVM pGVM);
864void iomR0MmioCleanupVM(PGVM pGVM);
865void iomR0MmioInitPerVMData(PGVM pGVM);
866#endif
867VBOXSTRICTRC iomMmioCommonPfHandlerOld(PVMCC pVM, PVMCPUCC pVCpu, uint32_t uErrorCode, PCPUMCTXCORE pCtxCore,
868 RTGCPHYS GCPhysFault, void *pvUser);
869
870#ifndef IN_RING3
871DECLEXPORT(FNPGMRZPHYSPFHANDLER) iomMmioPfHandler;
872DECLEXPORT(FNPGMRZPHYSPFHANDLER) iomMmioPfHandlerNew;
873#endif
874PGM_ALL_CB2_PROTO(FNPGMPHYSHANDLER) iomMmioHandler;
875PGM_ALL_CB2_PROTO(FNPGMPHYSHANDLER) iomMmioHandlerNew;
876
877/* IOM locking helpers. */
878#ifdef IOM_WITH_CRIT_SECT_RW
879# define IOM_LOCK_EXCL(a_pVM) PDMCritSectRwEnterExcl(&(a_pVM)->iom.s.CritSect, VERR_SEM_BUSY)
880# define IOM_UNLOCK_EXCL(a_pVM) do { PDMCritSectRwLeaveExcl(&(a_pVM)->iom.s.CritSect); } while (0)
881# if 0 /* (in case needed for debugging) */
882# define IOM_LOCK_SHARED_EX(a_pVM, a_rcBusy) PDMCritSectRwEnterExcl(&(a_pVM)->iom.s.CritSect, (a_rcBusy))
883# define IOM_UNLOCK_SHARED(a_pVM) do { PDMCritSectRwLeaveExcl(&(a_pVM)->iom.s.CritSect); } while (0)
884# define IOM_IS_SHARED_LOCK_OWNER(a_pVM) PDMCritSectRwIsWriteOwner(&(a_pVM)->iom.s.CritSect)
885# else
886# define IOM_LOCK_SHARED_EX(a_pVM, a_rcBusy) PDMCritSectRwEnterShared(&(a_pVM)->iom.s.CritSect, (a_rcBusy))
887# define IOM_UNLOCK_SHARED(a_pVM) do { PDMCritSectRwLeaveShared(&(a_pVM)->iom.s.CritSect); } while (0)
888# define IOM_IS_SHARED_LOCK_OWNER(a_pVM) PDMCritSectRwIsReadOwner(&(a_pVM)->iom.s.CritSect, true)
889# endif
890# define IOM_IS_EXCL_LOCK_OWNER(a_pVM) PDMCritSectRwIsWriteOwner(&(a_pVM)->iom.s.CritSect)
891#else
892# define IOM_LOCK_EXCL(a_pVM) PDMCritSectEnter(&(a_pVM)->iom.s.CritSect, VERR_SEM_BUSY)
893# define IOM_UNLOCK_EXCL(a_pVM) do { PDMCritSectLeave(&(a_pVM)->iom.s.CritSect); } while (0)
894# define IOM_LOCK_SHARED_EX(a_pVM, a_rcBusy) PDMCritSectEnter(&(a_pVM)->iom.s.CritSect, (a_rcBusy))
895# define IOM_UNLOCK_SHARED(a_pVM) do { PDMCritSectLeave(&(a_pVM)->iom.s.CritSect); } while (0)
896# define IOM_IS_SHARED_LOCK_OWNER(a_pVM) PDMCritSectIsOwner(&(a_pVM)->iom.s.CritSect)
897# define IOM_IS_EXCL_LOCK_OWNER(a_pVM) PDMCritSectIsOwner(&(a_pVM)->iom.s.CritSect)
898#endif
899#define IOM_LOCK_SHARED(a_pVM) IOM_LOCK_SHARED_EX(a_pVM, VERR_SEM_BUSY)
900
901
902RT_C_DECLS_END
903
904
905#ifdef IN_RING3
906
907#endif
908
909/** @} */
910
911#endif /* !VMM_INCLUDED_SRC_include_IOMInternal_h */
912
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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