VirtualBox

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

Last change on this file since 77922 was 76585, checked in by vboxsync, 6 years ago

*: scm --fix-header-guard-endif

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