VirtualBox

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

Last change on this file since 72580 was 69474, checked in by vboxsync, 7 years ago

*: scm updates - header files should have 'svn:keywords=Id Revision' too (doesn't mean they have to use them).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 18.4 KB
Line 
1/* $Id: IOMInternal.h 69474 2017-10-28 13:12:06Z vboxsync $ */
2/** @file
3 * IOM - Internal header file.
4 */
5
6/*
7 * Copyright (C) 2006-2017 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 ___IOMInternal_h
19#define ___IOMInternal_h
20
21#define IOM_WITH_CRIT_SECT_RW
22
23#include <VBox/cdefs.h>
24#include <VBox/types.h>
25#include <VBox/vmm/iom.h>
26#include <VBox/vmm/stam.h>
27#include <VBox/vmm/pgm.h>
28#include <VBox/vmm/pdmcritsect.h>
29#ifdef IOM_WITH_CRIT_SECT_RW
30# include <VBox/vmm/pdmcritsectrw.h>
31#endif
32#include <VBox/param.h>
33#include <iprt/assert.h>
34#include <iprt/avl.h>
35
36
37
38/** @defgroup grp_iom_int Internals
39 * @ingroup grp_iom
40 * @internal
41 * @{
42 */
43
44/**
45 * MMIO range descriptor.
46 */
47typedef struct IOMMMIORANGE
48{
49 /** Avl node core with GCPhys as Key and GCPhys + cbSize - 1 as KeyLast. */
50 AVLROGCPHYSNODECORE Core;
51 /** Start physical address. */
52 RTGCPHYS GCPhys;
53 /** Size of the range. */
54 RTGCPHYS cb;
55 /** The reference counter. */
56 uint32_t volatile cRefs;
57 /** Flags, see IOMMMIO_FLAGS_XXX. */
58 uint32_t fFlags;
59
60 /** Pointer to user argument - R0. */
61 RTR0PTR pvUserR0;
62 /** Pointer to device instance - R0. */
63 PPDMDEVINSR0 pDevInsR0;
64 /** Pointer to write callback function - R0. */
65 R0PTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallbackR0;
66 /** Pointer to read callback function - R0. */
67 R0PTRTYPE(PFNIOMMMIOREAD) pfnReadCallbackR0;
68 /** Pointer to fill (memset) callback function - R0. */
69 R0PTRTYPE(PFNIOMMMIOFILL) pfnFillCallbackR0;
70
71 /** Pointer to user argument - R3. */
72 RTR3PTR pvUserR3;
73 /** Pointer to device instance - R3. */
74 PPDMDEVINSR3 pDevInsR3;
75 /** Pointer to write callback function - R3. */
76 R3PTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallbackR3;
77 /** Pointer to read callback function - R3. */
78 R3PTRTYPE(PFNIOMMMIOREAD) pfnReadCallbackR3;
79 /** Pointer to fill (memset) callback function - R3. */
80 R3PTRTYPE(PFNIOMMMIOFILL) pfnFillCallbackR3;
81
82 /** Description / Name. For easing debugging. */
83 R3PTRTYPE(const char *) pszDesc;
84
85 /** Pointer to user argument - RC. */
86 RTRCPTR pvUserRC;
87 /** Pointer to device instance - RC. */
88 PPDMDEVINSRC pDevInsRC;
89 /** Pointer to write callback function - RC. */
90 RCPTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallbackRC;
91 /** Pointer to read callback function - RC. */
92 RCPTRTYPE(PFNIOMMMIOREAD) pfnReadCallbackRC;
93 /** Pointer to fill (memset) callback function - RC. */
94 RCPTRTYPE(PFNIOMMMIOFILL) pfnFillCallbackRC;
95#if HC_ARCH_BITS == 64
96 /** Padding structure length to multiple of 8 bytes. */
97 RTRCPTR RCPtrPadding;
98#endif
99} IOMMMIORANGE;
100/** Pointer to a MMIO range descriptor, R3 version. */
101typedef struct IOMMMIORANGE *PIOMMMIORANGE;
102
103
104/**
105 * MMIO address statistics. (one address)
106 *
107 * This is a simple way of making on demand statistics, however it's a
108 * bit free with the hypervisor heap memory.
109 */
110typedef struct IOMMMIOSTATS
111{
112 /** Avl node core with the address as Key. */
113 AVLOGCPHYSNODECORE Core;
114
115 /** Number of accesses (subtract ReadRZToR3 and WriteRZToR3 to get the right
116 * number). */
117 STAMCOUNTER Accesses;
118
119 /** Profiling read handler overhead in R3. */
120 STAMPROFILE ProfReadR3;
121 /** Profiling write handler overhead in R3. */
122 STAMPROFILE ProfWriteR3;
123 /** Counting and profiling reads in R0/RC. */
124 STAMPROFILE ProfReadRZ;
125 /** Counting and profiling writes in R0/RC. */
126 STAMPROFILE ProfWriteRZ;
127
128 /** Number of reads to this address from R0/RC which was serviced in R3. */
129 STAMCOUNTER ReadRZToR3;
130 /** Number of writes to this address from R0/RC which was serviced in R3. */
131 STAMCOUNTER WriteRZToR3;
132} IOMMMIOSTATS;
133AssertCompileMemberAlignment(IOMMMIOSTATS, Accesses, 8);
134/** Pointer to I/O port statistics. */
135typedef IOMMMIOSTATS *PIOMMMIOSTATS;
136
137
138/**
139 * I/O port range descriptor, R3 version.
140 */
141typedef struct IOMIOPORTRANGER3
142{
143 /** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */
144 AVLROIOPORTNODECORE Core;
145#if HC_ARCH_BITS == 64 && !defined(RT_OS_WINDOWS)
146 uint32_t u32Alignment; /**< The sizeof(Core) differs. */
147#endif
148 /** Start I/O port address. */
149 RTIOPORT Port;
150 /** Size of the range. */
151 uint16_t cPorts;
152 /** Pointer to user argument. */
153 RTR3PTR pvUser;
154 /** Pointer to the associated device instance. */
155 R3PTRTYPE(PPDMDEVINS) pDevIns;
156 /** Pointer to OUT callback function. */
157 R3PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback;
158 /** Pointer to IN callback function. */
159 R3PTRTYPE(PFNIOMIOPORTIN) pfnInCallback;
160 /** Pointer to string OUT callback function. */
161 R3PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;
162 /** Pointer to string IN callback function. */
163 R3PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;
164 /** Description / Name. For easing debugging. */
165 R3PTRTYPE(const char *) pszDesc;
166} IOMIOPORTRANGER3;
167/** Pointer to I/O port range descriptor, R3 version. */
168typedef IOMIOPORTRANGER3 *PIOMIOPORTRANGER3;
169
170/**
171 * I/O port range descriptor, R0 version.
172 */
173typedef struct IOMIOPORTRANGER0
174{
175 /** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */
176 AVLROIOPORTNODECORE Core;
177#if HC_ARCH_BITS == 64 && !defined(RT_OS_WINDOWS)
178 uint32_t u32Alignment; /**< The sizeof(Core) differs. */
179#endif
180 /** Start I/O port address. */
181 RTIOPORT Port;
182 /** Size of the range. */
183 uint16_t cPorts;
184 /** Pointer to user argument. */
185 RTR0PTR pvUser;
186 /** Pointer to the associated device instance. */
187 R0PTRTYPE(PPDMDEVINS) pDevIns;
188 /** Pointer to OUT callback function. */
189 R0PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback;
190 /** Pointer to IN callback function. */
191 R0PTRTYPE(PFNIOMIOPORTIN) pfnInCallback;
192 /** Pointer to string OUT callback function. */
193 R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;
194 /** Pointer to string IN callback function. */
195 R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;
196 /** Description / Name. For easing debugging. */
197 R3PTRTYPE(const char *) pszDesc;
198} IOMIOPORTRANGER0;
199/** Pointer to I/O port range descriptor, R0 version. */
200typedef IOMIOPORTRANGER0 *PIOMIOPORTRANGER0;
201
202/**
203 * I/O port range descriptor, RC version.
204 */
205typedef struct IOMIOPORTRANGERC
206{
207 /** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */
208 AVLROIOPORTNODECORE Core;
209 /** Start I/O port address. */
210 RTIOPORT Port;
211 /** Size of the range. */
212 uint16_t cPorts;
213 /** Pointer to user argument. */
214 RTRCPTR pvUser;
215 /** Pointer to the associated device instance. */
216 RCPTRTYPE(PPDMDEVINS) pDevIns;
217 /** Pointer to OUT callback function. */
218 RCPTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback;
219 /** Pointer to IN callback function. */
220 RCPTRTYPE(PFNIOMIOPORTIN) pfnInCallback;
221 /** Pointer to string OUT callback function. */
222 RCPTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;
223 /** Pointer to string IN callback function. */
224 RCPTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;
225#if HC_ARCH_BITS == 64
226 RTRCPTR RCPtrAlignment; /**< pszDesc is 8 byte aligned. */
227#endif
228 /** Description / Name. For easing debugging. */
229 R3PTRTYPE(const char *) pszDesc;
230} IOMIOPORTRANGERC;
231/** Pointer to I/O port range descriptor, RC version. */
232typedef IOMIOPORTRANGERC *PIOMIOPORTRANGERC;
233
234
235/**
236 * I/O port statistics. (one I/O port)
237 *
238 * This is a simple way of making on demand statistics, however it's a
239 * bit free with the hypervisor heap memory.
240 */
241typedef struct IOMIOPORTSTATS
242{
243 /** Avl node core with the port as Key. */
244 AVLOIOPORTNODECORE Core;
245#if HC_ARCH_BITS != 64 || !defined(RT_OS_WINDOWS)
246 uint32_t u32Alignment; /**< The sizeof(Core) differs. */
247#endif
248 /** Number of INs to this port from R3. */
249 STAMCOUNTER InR3;
250 /** Profiling IN handler overhead in R3. */
251 STAMPROFILE ProfInR3;
252 /** Number of OUTs to this port from R3. */
253 STAMCOUNTER OutR3;
254 /** Profiling OUT handler overhead in R3. */
255 STAMPROFILE ProfOutR3;
256
257 /** Number of INs to this port from R0/RC. */
258 STAMCOUNTER InRZ;
259 /** Profiling IN handler overhead in R0/RC. */
260 STAMPROFILE ProfInRZ;
261 /** Number of INs to this port from R0/RC which was serviced in R3. */
262 STAMCOUNTER InRZToR3;
263
264 /** Number of OUTs to this port from R0/RC. */
265 STAMCOUNTER OutRZ;
266 /** Profiling OUT handler overhead in R0/RC. */
267 STAMPROFILE ProfOutRZ;
268 /** Number of OUTs to this port from R0/RC which was serviced in R3. */
269 STAMCOUNTER OutRZToR3;
270} IOMIOPORTSTATS;
271AssertCompileMemberAlignment(IOMIOPORTSTATS, InR3, 8);
272/** Pointer to I/O port statistics. */
273typedef IOMIOPORTSTATS *PIOMIOPORTSTATS;
274
275
276/**
277 * The IOM trees.
278 * These are offset based the nodes and root must be in the same
279 * memory block in HC. The locations of IOM structure and the hypervisor heap
280 * are quite different in R3, R0 and RC.
281 */
282typedef struct IOMTREES
283{
284 /** Tree containing I/O port range descriptors registered for HC (IOMIOPORTRANGEHC). */
285 AVLROIOPORTTREE IOPortTreeR3;
286 /** Tree containing I/O port range descriptors registered for R0 (IOMIOPORTRANGER0). */
287 AVLROIOPORTTREE IOPortTreeR0;
288 /** Tree containing I/O port range descriptors registered for RC (IOMIOPORTRANGERC). */
289 AVLROIOPORTTREE IOPortTreeRC;
290
291 /** Tree containing the MMIO range descriptors (IOMMMIORANGE). */
292 AVLROGCPHYSTREE MMIOTree;
293
294 /** Tree containing I/O port statistics (IOMIOPORTSTATS). */
295 AVLOIOPORTTREE IOPortStatTree;
296 /** Tree containing MMIO statistics (IOMMMIOSTATS). */
297 AVLOGCPHYSTREE MmioStatTree;
298} IOMTREES;
299/** Pointer to the IOM trees. */
300typedef IOMTREES *PIOMTREES;
301
302
303/**
304 * Converts an IOM pointer into a VM pointer.
305 * @returns Pointer to the VM structure the PGM is part of.
306 * @param pIOM Pointer to IOM instance data.
307 */
308#define IOM2VM(pIOM) ( (PVM)((char*)pIOM - pIOM->offVM) )
309
310/**
311 * IOM Data (part of VM)
312 */
313typedef struct IOM
314{
315 /** Offset to the VM structure. */
316 RTINT offVM;
317
318 /** Pointer to the trees - RC ptr. */
319 RCPTRTYPE(PIOMTREES) pTreesRC;
320 /** Pointer to the trees - R3 ptr. */
321 R3PTRTYPE(PIOMTREES) pTreesR3;
322 /** Pointer to the trees - R0 ptr. */
323 R0PTRTYPE(PIOMTREES) pTreesR0;
324
325 /** MMIO physical access handler type. */
326 PGMPHYSHANDLERTYPE hMmioHandlerType;
327 uint32_t u32Padding;
328
329 /** Lock serializing EMT access to IOM. */
330#ifdef IOM_WITH_CRIT_SECT_RW
331 PDMCRITSECTRW CritSect;
332#else
333 PDMCRITSECT CritSect;
334#endif
335
336 /** @name I/O Port statistics.
337 * @{ */
338 STAMCOUNTER StatInstIn;
339 STAMCOUNTER StatInstOut;
340 STAMCOUNTER StatInstIns;
341 STAMCOUNTER StatInstOuts;
342 /** @} */
343
344 /** @name MMIO statistics.
345 * @{ */
346 STAMPROFILE StatRZMMIOHandler;
347 STAMCOUNTER StatRZMMIOFailures;
348
349 STAMPROFILE StatRZInstMov;
350 STAMPROFILE StatRZInstCmp;
351 STAMPROFILE StatRZInstAnd;
352 STAMPROFILE StatRZInstOr;
353 STAMPROFILE StatRZInstXor;
354 STAMPROFILE StatRZInstBt;
355 STAMPROFILE StatRZInstTest;
356 STAMPROFILE StatRZInstXchg;
357 STAMPROFILE StatRZInstStos;
358 STAMPROFILE StatRZInstLods;
359#ifdef IOM_WITH_MOVS_SUPPORT
360 STAMPROFILEADV StatRZInstMovs;
361 STAMPROFILE StatRZInstMovsToMMIO;
362 STAMPROFILE StatRZInstMovsFromMMIO;
363 STAMPROFILE StatRZInstMovsMMIO;
364#endif
365 STAMCOUNTER StatRZInstOther;
366
367 STAMCOUNTER StatRZMMIO1Byte;
368 STAMCOUNTER StatRZMMIO2Bytes;
369 STAMCOUNTER StatRZMMIO4Bytes;
370 STAMCOUNTER StatRZMMIO8Bytes;
371
372 STAMCOUNTER StatR3MMIOHandler;
373
374 RTUINT cMovsMaxBytes;
375 RTUINT cStosMaxBytes;
376 /** @} */
377} IOM;
378/** Pointer to IOM instance data. */
379typedef IOM *PIOM;
380
381
382/**
383 * IOM per virtual CPU instance data.
384 */
385typedef struct IOMCPU
386{
387 /** For saving stack space, the disassembler state is allocated here instead of
388 * on the stack. */
389 DISCPUSTATE DisState;
390
391 /**
392 * Pending I/O port write commit (VINF_IOM_R3_IOPORT_COMMIT_WRITE).
393 *
394 * This is a converted VINF_IOM_R3_IOPORT_WRITE handler return that lets the
395 * execution engine commit the instruction and then return to ring-3 to complete
396 * the I/O port write there. This avoids having to decode the instruction again
397 * in ring-3.
398 */
399 struct
400 {
401 /** The value size (0 if not pending). */
402 uint16_t cbValue;
403 /** The I/O port. */
404 RTIOPORT IOPort;
405 /** The value. */
406 uint32_t u32Value;
407 } PendingIOPortWrite;
408
409 /**
410 * Pending MMIO write commit (VINF_IOM_R3_MMIO_COMMIT_WRITE).
411 *
412 * This is a converted VINF_IOM_R3_MMIO_WRITE handler return that lets the
413 * execution engine commit the instruction, stop any more REPs, and return to
414 * ring-3 to complete the MMIO write there. The avoid the tedious decoding of
415 * the instruction again once we're in ring-3, more importantly it allows us to
416 * correctly deal with read-modify-write instructions like XCHG, OR, and XOR.
417 */
418 struct
419 {
420 /** Guest physical MMIO address. */
421 RTGCPHYS GCPhys;
422 /** The value to write. */
423 uint8_t abValue[128];
424 /** The number of bytes to write (0 if nothing pending). */
425 uint32_t cbValue;
426 /** Alignment padding. */
427 uint32_t uAlignmentPadding;
428 } PendingMmioWrite;
429
430 /** @name Caching of I/O Port and MMIO ranges and statistics.
431 * (Saves quite some time in rep outs/ins instruction emulation.)
432 * @{ */
433 R3PTRTYPE(PIOMIOPORTRANGER3) pRangeLastReadR3;
434 R3PTRTYPE(PIOMIOPORTRANGER3) pRangeLastWriteR3;
435 R3PTRTYPE(PIOMIOPORTSTATS) pStatsLastReadR3;
436 R3PTRTYPE(PIOMIOPORTSTATS) pStatsLastWriteR3;
437 R3PTRTYPE(PIOMMMIORANGE) pMMIORangeLastR3;
438 R3PTRTYPE(PIOMMMIOSTATS) pMMIOStatsLastR3;
439
440 R0PTRTYPE(PIOMIOPORTRANGER0) pRangeLastReadR0;
441 R0PTRTYPE(PIOMIOPORTRANGER0) pRangeLastWriteR0;
442 R0PTRTYPE(PIOMIOPORTSTATS) pStatsLastReadR0;
443 R0PTRTYPE(PIOMIOPORTSTATS) pStatsLastWriteR0;
444 R0PTRTYPE(PIOMMMIORANGE) pMMIORangeLastR0;
445 R0PTRTYPE(PIOMMMIOSTATS) pMMIOStatsLastR0;
446
447 RCPTRTYPE(PIOMIOPORTRANGERC) pRangeLastReadRC;
448 RCPTRTYPE(PIOMIOPORTRANGERC) pRangeLastWriteRC;
449 RCPTRTYPE(PIOMIOPORTSTATS) pStatsLastReadRC;
450 RCPTRTYPE(PIOMIOPORTSTATS) pStatsLastWriteRC;
451 RCPTRTYPE(PIOMMMIORANGE) pMMIORangeLastRC;
452 RCPTRTYPE(PIOMMMIOSTATS) pMMIOStatsLastRC;
453 /** @} */
454} IOMCPU;
455/** Pointer to IOM per virtual CPU instance data. */
456typedef IOMCPU *PIOMCPU;
457
458
459RT_C_DECLS_BEGIN
460
461void iomMmioFreeRange(PVM pVM, PIOMMMIORANGE pRange);
462#ifdef IN_RING3
463PIOMMMIOSTATS iomR3MMIOStatsCreate(PVM pVM, RTGCPHYS GCPhys, const char *pszDesc);
464#endif /* IN_RING3 */
465
466#ifndef IN_RING3
467DECLEXPORT(FNPGMRZPHYSPFHANDLER) iomMmioPfHandler;
468#endif
469PGM_ALL_CB2_PROTO(FNPGMPHYSHANDLER) iomMmioHandler;
470
471/* IOM locking helpers. */
472#ifdef IOM_WITH_CRIT_SECT_RW
473# define IOM_LOCK_EXCL(a_pVM) PDMCritSectRwEnterExcl(&(a_pVM)->iom.s.CritSect, VERR_SEM_BUSY)
474# define IOM_UNLOCK_EXCL(a_pVM) do { PDMCritSectRwLeaveExcl(&(a_pVM)->iom.s.CritSect); } while (0)
475# if 0 /* (in case needed for debugging) */
476# define IOM_LOCK_SHARED_EX(a_pVM, a_rcBusy) PDMCritSectRwEnterExcl(&(a_pVM)->iom.s.CritSect, (a_rcBusy))
477# define IOM_UNLOCK_SHARED(a_pVM) do { PDMCritSectRwLeaveExcl(&(a_pVM)->iom.s.CritSect); } while (0)
478# define IOM_IS_SHARED_LOCK_OWNER(a_pVM) PDMCritSectRwIsWriteOwner(&(a_pVM)->iom.s.CritSect)
479# else
480# define IOM_LOCK_SHARED_EX(a_pVM, a_rcBusy) PDMCritSectRwEnterShared(&(a_pVM)->iom.s.CritSect, (a_rcBusy))
481# define IOM_UNLOCK_SHARED(a_pVM) do { PDMCritSectRwLeaveShared(&(a_pVM)->iom.s.CritSect); } while (0)
482# define IOM_IS_SHARED_LOCK_OWNER(a_pVM) PDMCritSectRwIsReadOwner(&(a_pVM)->iom.s.CritSect, true)
483# endif
484# define IOM_IS_EXCL_LOCK_OWNER(a_pVM) PDMCritSectRwIsWriteOwner(&(a_pVM)->iom.s.CritSect)
485#else
486# define IOM_LOCK_EXCL(a_pVM) PDMCritSectEnter(&(a_pVM)->iom.s.CritSect, VERR_SEM_BUSY)
487# define IOM_UNLOCK_EXCL(a_pVM) do { PDMCritSectLeave(&(a_pVM)->iom.s.CritSect); } while (0)
488# define IOM_LOCK_SHARED_EX(a_pVM, a_rcBusy) PDMCritSectEnter(&(a_pVM)->iom.s.CritSect, (a_rcBusy))
489# define IOM_UNLOCK_SHARED(a_pVM) do { PDMCritSectLeave(&(a_pVM)->iom.s.CritSect); } while (0)
490# define IOM_IS_SHARED_LOCK_OWNER(a_pVM) PDMCritSectIsOwner(&(a_pVM)->iom.s.CritSect)
491# define IOM_IS_EXCL_LOCK_OWNER(a_pVM) PDMCritSectIsOwner(&(a_pVM)->iom.s.CritSect)
492#endif
493#define IOM_LOCK_SHARED(a_pVM) IOM_LOCK_SHARED_EX(a_pVM, VERR_SEM_BUSY)
494
495
496RT_C_DECLS_END
497
498
499#ifdef IN_RING3
500
501#endif
502
503/** @} */
504
505#endif /* !___IOMInternal_h */
506
Note: See TracBrowser for help on using the repository browser.

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