VirtualBox

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

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

VMM: Kicking out raw-mode - IOM. bugref:9517

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