VirtualBox

source: vbox/trunk/src/VBox/VMM/PGMInternal.h@ 7753

Last change on this file since 7753 was 7753, checked in by vboxsync, 17 years ago

The PGM bits of the MMIO cleanup.
Moved the parts of PGMR3Reset that deals with RAM (zeroing it) and sketched out the new code there.
Fixed a bug in PGM_PAGE_INIT_ZERO* where the type and state was switched.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 144.5 KB
Line 
1/* $Id: PGMInternal.h 7753 2008-04-04 20:35:44Z vboxsync $ */
2/** @file
3 * PGM - Internal header file.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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 ___PGMInternal_h
19#define ___PGMInternal_h
20
21#include <VBox/cdefs.h>
22#include <VBox/types.h>
23#include <VBox/err.h>
24#include <VBox/stam.h>
25#include <VBox/param.h>
26#include <VBox/vmm.h>
27#include <VBox/mm.h>
28#include <VBox/pdmcritsect.h>
29#include <VBox/pdmapi.h>
30#include <VBox/dis.h>
31#include <VBox/dbgf.h>
32#include <VBox/log.h>
33#include <VBox/gmm.h>
34#include <iprt/avl.h>
35#include <iprt/assert.h>
36#include <iprt/critsect.h>
37
38#if !defined(IN_PGM_R3) && !defined(IN_PGM_R0) && !defined(IN_PGM_GC)
39# error "Not in PGM! This is an internal header!"
40#endif
41
42
43/** @defgroup grp_pgm_int Internals
44 * @ingroup grp_pgm
45 * @internal
46 * @{
47 */
48
49
50/** @name PGM Compile Time Config
51 * @{
52 */
53
54/**
55 * Solve page is out of sync issues inside Guest Context (in PGMGC.cpp).
56 * Comment it if it will break something.
57 */
58#define PGM_OUT_OF_SYNC_IN_GC
59
60/**
61 * Virtualize the dirty bit
62 * This also makes a half-hearted attempt at the accessed bit. For full
63 * accessed bit virtualization define PGM_SYNC_ACCESSED_BIT.
64 */
65#define PGM_SYNC_DIRTY_BIT
66
67/**
68 * Fully virtualize the accessed bit.
69 * @remark This requires SYNC_DIRTY_ACCESSED_BITS to be defined!
70 */
71#define PGM_SYNC_ACCESSED_BIT
72
73/**
74 * Check and skip global PDEs for non-global flushes
75 */
76#define PGM_SKIP_GLOBAL_PAGEDIRS_ON_NONGLOBAL_FLUSH
77
78/**
79 * Sync N pages instead of a whole page table
80 */
81#define PGM_SYNC_N_PAGES
82
83/**
84 * Number of pages to sync during a page fault
85 *
86 * When PGMPOOL_WITH_GCPHYS_TRACKING is enabled using high values here
87 * causes a lot of unnecessary extents and also is slower than taking more \#PFs.
88 */
89#define PGM_SYNC_NR_PAGES 8
90
91/**
92 * Number of PGMPhysRead/Write cache entries (must be <= sizeof(uint64_t))
93 */
94#define PGM_MAX_PHYSCACHE_ENTRIES 64
95#define PGM_MAX_PHYSCACHE_ENTRIES_MASK (PGM_MAX_PHYSCACHE_ENTRIES-1)
96
97/**
98 * Enable caching of PGMR3PhysRead/WriteByte/Word/Dword
99 */
100#define PGM_PHYSMEMACCESS_CACHING
101
102/*
103 * Assert Sanity.
104 */
105#if defined(PGM_SYNC_ACCESSED_BIT) && !defined(PGM_SYNC_DIRTY_BIT)
106# error "PGM_SYNC_ACCESSED_BIT requires PGM_SYNC_DIRTY_BIT!"
107#endif
108
109/** @def PGMPOOL_WITH_CACHE
110 * Enable agressive caching using the page pool.
111 *
112 * This requires PGMPOOL_WITH_USER_TRACKING and PGMPOOL_WITH_MONITORING.
113 */
114#define PGMPOOL_WITH_CACHE
115
116/** @def PGMPOOL_WITH_MIXED_PT_CR3
117 * When defined, we'll deal with 'uncachable' pages.
118 */
119#ifdef PGMPOOL_WITH_CACHE
120# define PGMPOOL_WITH_MIXED_PT_CR3
121#endif
122
123/** @def PGMPOOL_WITH_MONITORING
124 * Monitor the guest pages which are shadowed.
125 * When this is enabled, PGMPOOL_WITH_CACHE or PGMPOOL_WITH_GCPHYS_TRACKING must
126 * be enabled as well.
127 * @remark doesn't really work without caching now. (Mixed PT/CR3 change.)
128 */
129#ifdef PGMPOOL_WITH_CACHE
130# define PGMPOOL_WITH_MONITORING
131#endif
132
133/** @def PGMPOOL_WITH_GCPHYS_TRACKING
134 * Tracking the of shadow pages mapping guest physical pages.
135 *
136 * This is very expensive, the current cache prototype is trying to figure out
137 * whether it will be acceptable with an agressive caching policy.
138 */
139#if defined(PGMPOOL_WITH_CACHE) || defined(PGMPOOL_WITH_MONITORING)
140# define PGMPOOL_WITH_GCPHYS_TRACKING
141#endif
142
143/** @def PGMPOOL_WITH_USER_TRACKNG
144 * Tracking users of shadow pages. This is required for the linking of shadow page
145 * tables and physical guest addresses.
146 */
147#if defined(PGMPOOL_WITH_GCPHYS_TRACKING) || defined(PGMPOOL_WITH_CACHE) || defined(PGMPOOL_WITH_MONITORING)
148# define PGMPOOL_WITH_USER_TRACKING
149#endif
150
151/** @def PGMPOOL_CFG_MAX_GROW
152 * The maximum number of pages to add to the pool in one go.
153 */
154#define PGMPOOL_CFG_MAX_GROW (_256K >> PAGE_SHIFT)
155
156/** @def VBOX_STRICT_PGM_HANDLER_VIRTUAL
157 * Enables some extra assertions for virtual handlers (mainly phys2virt related).
158 */
159#ifdef VBOX_STRICT
160# define VBOX_STRICT_PGM_HANDLER_VIRTUAL
161#endif
162/** @} */
163
164
165/** @name PDPT and PML4 flags.
166 * These are placed in the three bits available for system programs in
167 * the PDPT and PML4 entries.
168 * @{ */
169/** The entry is a permanent one and it's must always be present.
170 * Never free such an entry. */
171#define PGM_PLXFLAGS_PERMANENT RT_BIT_64(10)
172/** @} */
173
174/** @name Page directory flags.
175 * These are placed in the three bits available for system programs in
176 * the page directory entries.
177 * @{ */
178/** Mapping (hypervisor allocated pagetable). */
179#define PGM_PDFLAGS_MAPPING RT_BIT_64(10)
180/** Made read-only to facilitate dirty bit tracking. */
181#define PGM_PDFLAGS_TRACK_DIRTY RT_BIT_64(11)
182/** @} */
183
184/** @name Page flags.
185 * These are placed in the three bits available for system programs in
186 * the page entries.
187 * @{ */
188/** Made read-only to facilitate dirty bit tracking. */
189#define PGM_PTFLAGS_TRACK_DIRTY RT_BIT_64(9)
190
191#ifndef PGM_PTFLAGS_CSAM_VALIDATED
192/** Scanned and approved by CSAM (tm).
193 * NOTE: Must be identical to the one defined in CSAMInternal.h!!
194 * @todo Move PGM_PTFLAGS_* and PGM_PDFLAGS_* to VBox/pgm.h. */
195#define PGM_PTFLAGS_CSAM_VALIDATED RT_BIT_64(11)
196#endif
197/** @} */
198
199/** @name Defines used to indicate the shadow and guest paging in the templates.
200 * @{ */
201#define PGM_TYPE_REAL 1
202#define PGM_TYPE_PROT 2
203#define PGM_TYPE_32BIT 3
204#define PGM_TYPE_PAE 4
205#define PGM_TYPE_AMD64 5
206/** @} */
207
208/** Macro for checking if the guest is using paging.
209 * @param uType PGM_TYPE_*
210 * @remark ASSUMES certain order of the PGM_TYPE_* values.
211 */
212#define PGM_WITH_PAGING(uType) ((uType) >= PGM_TYPE_32BIT)
213
214/** Macro for checking if the guest supports the NX bit.
215 * @param uType PGM_TYPE_*
216 * @remark ASSUMES certain order of the PGM_TYPE_* values.
217 */
218#define PGM_WITH_NX(uType) ((uType) >= PGM_TYPE_PAE)
219
220
221/** @def PGM_HCPHYS_2_PTR
222 * Maps a HC physical page pool address to a virtual address.
223 *
224 * @returns VBox status code.
225 * @param pVM The VM handle.
226 * @param HCPhys The HC physical address to map to a virtual one.
227 * @param ppv Where to store the virtual address. No need to cast this.
228 *
229 * @remark In GC this uses PGMGCDynMapHCPage(), so it will consume of the
230 * small page window employeed by that function. Be careful.
231 * @remark There is no need to assert on the result.
232 */
233#ifdef IN_GC
234# define PGM_HCPHYS_2_PTR(pVM, HCPhys, ppv) PGMGCDynMapHCPage(pVM, HCPhys, (void **)(ppv))
235#else
236# define PGM_HCPHYS_2_PTR(pVM, HCPhys, ppv) MMPagePhys2PageEx(pVM, HCPhys, (void **)(ppv))
237#endif
238
239/** @def PGM_GCPHYS_2_PTR
240 * Maps a GC physical page address to a virtual address.
241 *
242 * @returns VBox status code.
243 * @param pVM The VM handle.
244 * @param GCPhys The GC physical address to map to a virtual one.
245 * @param ppv Where to store the virtual address. No need to cast this.
246 *
247 * @remark In GC this uses PGMGCDynMapGCPage(), so it will consume of the
248 * small page window employeed by that function. Be careful.
249 * @remark There is no need to assert on the result.
250 */
251#ifdef IN_GC
252# define PGM_GCPHYS_2_PTR(pVM, GCPhys, ppv) PGMGCDynMapGCPage(pVM, GCPhys, (void **)(ppv))
253#else
254# define PGM_GCPHYS_2_PTR(pVM, GCPhys, ppv) PGMPhysGCPhys2HCPtr(pVM, GCPhys, 1 /* one page only */, (void **)(ppv)) /** @todo this isn't asserting, use PGMRamGCPhys2HCPtr! */
255#endif
256
257/** @def PGM_GCPHYS_2_PTR_EX
258 * Maps a unaligned GC physical page address to a virtual address.
259 *
260 * @returns VBox status code.
261 * @param pVM The VM handle.
262 * @param GCPhys The GC physical address to map to a virtual one.
263 * @param ppv Where to store the virtual address. No need to cast this.
264 *
265 * @remark In GC this uses PGMGCDynMapGCPage(), so it will consume of the
266 * small page window employeed by that function. Be careful.
267 * @remark There is no need to assert on the result.
268 */
269#ifdef IN_GC
270# define PGM_GCPHYS_2_PTR_EX(pVM, GCPhys, ppv) PGMGCDynMapGCPageEx(pVM, GCPhys, (void **)(ppv))
271#else
272# define PGM_GCPHYS_2_PTR_EX(pVM, GCPhys, ppv) PGMPhysGCPhys2HCPtr(pVM, GCPhys, 1 /* one page only */, (void **)(ppv)) /** @todo this isn't asserting, use PGMRamGCPhys2HCPtr! */
273#endif
274
275/** @def PGM_INVL_PG
276 * Invalidates a page when in GC does nothing in HC.
277 *
278 * @param GCVirt The virtual address of the page to invalidate.
279 */
280#ifdef IN_GC
281# define PGM_INVL_PG(GCVirt) ASMInvalidatePage((void *)(GCVirt))
282#else
283# define PGM_INVL_PG(GCVirt) ((void)0)
284#endif
285
286/** @def PGM_INVL_BIG_PG
287 * Invalidates a 4MB page directory entry when in GC does nothing in HC.
288 *
289 * @param GCVirt The virtual address within the page directory to invalidate.
290 */
291#ifdef IN_GC
292# define PGM_INVL_BIG_PG(GCVirt) ASMReloadCR3()
293#else
294# define PGM_INVL_BIG_PG(GCVirt) ((void)0)
295#endif
296
297/** @def PGM_INVL_GUEST_TLBS()
298 * Invalidates all guest TLBs.
299 */
300#ifdef IN_GC
301# define PGM_INVL_GUEST_TLBS() ASMReloadCR3()
302#else
303# define PGM_INVL_GUEST_TLBS() ((void)0)
304#endif
305
306
307/**
308 * Structure for tracking GC Mappings.
309 *
310 * This structure is used by linked list in both GC and HC.
311 */
312typedef struct PGMMAPPING
313{
314 /** Pointer to next entry. */
315 R3PTRTYPE(struct PGMMAPPING *) pNextR3;
316 /** Pointer to next entry. */
317 R0PTRTYPE(struct PGMMAPPING *) pNextR0;
318 /** Pointer to next entry. */
319 GCPTRTYPE(struct PGMMAPPING *) pNextGC;
320 /** Start Virtual address. */
321 RTGCUINTPTR GCPtr;
322 /** Last Virtual address (inclusive). */
323 RTGCUINTPTR GCPtrLast;
324 /** Range size (bytes). */
325 RTGCUINTPTR cb;
326 /** Pointer to relocation callback function. */
327 R3PTRTYPE(PFNPGMRELOCATE) pfnRelocate;
328 /** User argument to the callback. */
329 R3PTRTYPE(void *) pvUser;
330 /** Mapping description / name. For easing debugging. */
331 R3PTRTYPE(const char *) pszDesc;
332 /** Number of page tables. */
333 RTUINT cPTs;
334#if HC_ARCH_BITS != GC_ARCH_BITS
335 RTUINT uPadding0; /**< Alignment padding. */
336#endif
337 /** Array of page table mapping data. Each entry
338 * describes one page table. The array can be longer
339 * than the declared length.
340 */
341 struct
342 {
343 /** The HC physical address of the page table. */
344 RTHCPHYS HCPhysPT;
345 /** The HC physical address of the first PAE page table. */
346 RTHCPHYS HCPhysPaePT0;
347 /** The HC physical address of the second PAE page table. */
348 RTHCPHYS HCPhysPaePT1;
349 /** The HC virtual address of the 32-bit page table. */
350 R3PTRTYPE(PX86PT) pPTR3;
351 /** The HC virtual address of the two PAE page table. (i.e 1024 entries instead of 512) */
352 R3PTRTYPE(PX86PTPAE) paPaePTsR3;
353 /** The GC virtual address of the 32-bit page table. */
354 GCPTRTYPE(PX86PT) pPTGC;
355 /** The GC virtual address of the two PAE page table. */
356 GCPTRTYPE(PX86PTPAE) paPaePTsGC;
357 /** The GC virtual address of the 32-bit page table. */
358 R0PTRTYPE(PX86PT) pPTR0;
359 /** The GC virtual address of the two PAE page table. */
360 R0PTRTYPE(PX86PTPAE) paPaePTsR0;
361 } aPTs[1];
362} PGMMAPPING;
363/** Pointer to structure for tracking GC Mappings. */
364typedef struct PGMMAPPING *PPGMMAPPING;
365
366
367/**
368 * Physical page access handler structure.
369 *
370 * This is used to keep track of physical address ranges
371 * which are being monitored in some kind of way.
372 */
373typedef struct PGMPHYSHANDLER
374{
375 AVLROGCPHYSNODECORE Core;
376 /** Access type. */
377 PGMPHYSHANDLERTYPE enmType;
378 /** Number of pages to update. */
379 uint32_t cPages;
380 /** Pointer to R3 callback function. */
381 R3PTRTYPE(PFNPGMR3PHYSHANDLER) pfnHandlerR3;
382 /** User argument for R3 handlers. */
383 R3PTRTYPE(void *) pvUserR3;
384 /** Pointer to R0 callback function. */
385 R0PTRTYPE(PFNPGMR0PHYSHANDLER) pfnHandlerR0;
386 /** User argument for R0 handlers. */
387 R0PTRTYPE(void *) pvUserR0;
388 /** Pointer to GC callback function. */
389 GCPTRTYPE(PFNPGMGCPHYSHANDLER) pfnHandlerGC;
390 /** User argument for GC handlers. */
391 GCPTRTYPE(void *) pvUserGC;
392 /** Description / Name. For easing debugging. */
393 R3PTRTYPE(const char *) pszDesc;
394#ifdef VBOX_WITH_STATISTICS
395 /** Profiling of this handler. */
396 STAMPROFILE Stat;
397#endif
398} PGMPHYSHANDLER;
399/** Pointer to a physical page access handler structure. */
400typedef PGMPHYSHANDLER *PPGMPHYSHANDLER;
401
402
403/**
404 * Cache node for the physical addresses covered by a virtual handler.
405 */
406typedef struct PGMPHYS2VIRTHANDLER
407{
408 /** Core node for the tree based on physical ranges. */
409 AVLROGCPHYSNODECORE Core;
410 /** Offset from this struct to the PGMVIRTHANDLER structure. */
411 int32_t offVirtHandler;
412 /** Offset of the next alias relative to this one.
413 * Bit 0 is used for indicating whether we're in the tree.
414 * Bit 1 is used for indicating that we're the head node.
415 */
416 int32_t offNextAlias;
417} PGMPHYS2VIRTHANDLER;
418/** Pointer to a phys to virtual handler structure. */
419typedef PGMPHYS2VIRTHANDLER *PPGMPHYS2VIRTHANDLER;
420
421/** The bit in PGMPHYS2VIRTHANDLER::offNextAlias used to indicate that the
422 * node is in the tree. */
423#define PGMPHYS2VIRTHANDLER_IN_TREE RT_BIT(0)
424/** The bit in PGMPHYS2VIRTHANDLER::offNextAlias used to indicate that the
425 * node is in the head of an alias chain.
426 * The PGMPHYS2VIRTHANDLER_IN_TREE is always set if this bit is set. */
427#define PGMPHYS2VIRTHANDLER_IS_HEAD RT_BIT(1)
428/** The mask to apply to PGMPHYS2VIRTHANDLER::offNextAlias to get the offset. */
429#define PGMPHYS2VIRTHANDLER_OFF_MASK (~(int32_t)3)
430
431
432/**
433 * Virtual page access handler structure.
434 *
435 * This is used to keep track of virtual address ranges
436 * which are being monitored in some kind of way.
437 */
438typedef struct PGMVIRTHANDLER
439{
440 /** Core node for the tree based on virtual ranges. */
441 AVLROGCPTRNODECORE Core;
442 /** Number of cache pages. */
443 uint32_t u32Padding;
444 /** Access type. */
445 PGMVIRTHANDLERTYPE enmType;
446 /** Number of cache pages. */
447 uint32_t cPages;
448
449/** @todo The next two members are redundant. It adds some readability though. */
450 /** Start of the range. */
451 RTGCPTR GCPtr;
452 /** End of the range (exclusive). */
453 RTGCPTR GCPtrLast;
454 /** Size of the range (in bytes). */
455 RTGCUINTPTR cb;
456 /** Pointer to the GC callback function. */
457 GCPTRTYPE(PFNPGMGCVIRTHANDLER) pfnHandlerGC;
458 /** Pointer to the HC callback function for invalidation. */
459 R3PTRTYPE(PFNPGMHCVIRTINVALIDATE) pfnInvalidateHC;
460 /** Pointer to the HC callback function. */
461 R3PTRTYPE(PFNPGMHCVIRTHANDLER) pfnHandlerHC;
462 /** Description / Name. For easing debugging. */
463 R3PTRTYPE(const char *) pszDesc;
464#ifdef VBOX_WITH_STATISTICS
465 /** Profiling of this handler. */
466 STAMPROFILE Stat;
467#endif
468 /** Array of cached physical addresses for the monitored ranged. */
469 PGMPHYS2VIRTHANDLER aPhysToVirt[HC_ARCH_BITS == 32 ? 1 : 2];
470} PGMVIRTHANDLER;
471/** Pointer to a virtual page access handler structure. */
472typedef PGMVIRTHANDLER *PPGMVIRTHANDLER;
473
474
475/**
476 * Page type.
477 * @remarks This enum has to fit in a 3-bit field (see PGMPAGE::u3Type).
478 * @todo convert to \#defines.
479 */
480typedef enum PGMPAGETYPE
481{
482 /** The usual invalid zero entry. */
483 PGMPAGETYPE_INVALID = 0,
484 /** RAM page. (RWX) */
485 PGMPAGETYPE_RAM,
486 /** MMIO2 page. (RWX) */
487 PGMPAGETYPE_MMIO2,
488 /** Shadowed ROM. (RWX) */
489 PGMPAGETYPE_ROM_SHADOW,
490 /** ROM page. (R-X) */
491 PGMPAGETYPE_ROM,
492 /** MMIO page. (---) */
493 PGMPAGETYPE_MMIO,
494 /** End of valid entries. */
495 PGMPAGETYPE_END
496} PGMPAGETYPE;
497AssertCompile(PGMPAGETYPE_END < 7);
498
499/** @name Page type predicates.
500 * @{ */
501#define PGMPAGETYPE_IS_READABLE(type) ( (type) <= PGMPAGETYPE_ROM )
502#define PGMPAGETYPE_IS_WRITEABLE(type) ( (type) <= PGMPAGETYPE_ROM_SHADOW )
503#define PGMPAGETYPE_IS_RWX(type) ( (type) <= PGMPAGETYPE_ROM_SHADOW )
504#define PGMPAGETYPE_IS_ROX(type) ( (type) == PGMPAGETYPE_ROM )
505#define PGMPAGETYPE_IS_NP(type) ( (type) == PGMPAGETYPE_MMIO )
506/** @} */
507
508
509/**
510 * A Physical Guest Page tracking structure.
511 *
512 * The format of this structure is complicated because we have to fit a lot
513 * of information into as few bits as possible. The format is also subject
514 * to change (there is one comming up soon). Which means that for we'll be
515 * using PGM_PAGE_GET_*, PGM_PAGE_IS_ and PGM_PAGE_SET_* macros for *all*
516 * accessess to the structure.
517 */
518typedef struct PGMPAGE
519{
520 /** The physical address and a whole lot of other stuff. All bits are used! */
521 RTHCPHYS HCPhys;
522 /** The page state. */
523 uint32_t u2StateX : 2;
524 /** Flag indicating that a write monitored page was written to when set. */
525 uint32_t fWrittenToX : 1;
526 /** For later. */
527 uint32_t fSomethingElse : 1;
528 /** The Page ID.
529 * @todo Merge with HCPhys once we've liberated HCPhys of its stuff.
530 * The HCPhys will be 100% static. */
531 uint32_t idPageX : 28;
532 /** The page type (PGMPAGETYPE). */
533 uint32_t u3Type : 3;
534 /** The physical handler state (PGM_PAGE_HNDL_PHYS_STATE*) */
535 uint32_t u2HandlerPhysStateX : 2;
536 /** The virtual handler state (PGM_PAGE_HNDL_VIRT_STATE*) */
537 uint32_t u2HandlerVirtStateX : 2;
538 uint32_t u29B : 25;
539} PGMPAGE;
540AssertCompileSize(PGMPAGE, 16);
541/** Pointer to a physical guest page. */
542typedef PGMPAGE *PPGMPAGE;
543/** Pointer to a const physical guest page. */
544typedef const PGMPAGE *PCPGMPAGE;
545/** Pointer to a physical guest page pointer. */
546typedef PPGMPAGE *PPPGMPAGE;
547
548
549/**
550 * Clears the page structure.
551 * @param pPage Pointer to the physical guest page tracking structure.
552 */
553#define PGM_PAGE_CLEAR(pPage) \
554 do { \
555 (pPage)->HCPhys = 0; \
556 (pPage)->u2StateX = 0; \
557 (pPage)->fWrittenToX = 0; \
558 (pPage)->fSomethingElse = 0; \
559 (pPage)->idPageX = 0; \
560 (pPage)->u3Type = 0; \
561 (pPage)->u29B = 0; \
562 } while (0)
563
564/**
565 * Initializes the page structure.
566 * @param pPage Pointer to the physical guest page tracking structure.
567 */
568#define PGM_PAGE_INIT(pPage, _HCPhys, _idPage, _uType, _uState) \
569 do { \
570 (pPage)->HCPhys = (_HCPhys); \
571 (pPage)->u2StateX = (_uState); \
572 (pPage)->fWrittenToX = 0; \
573 (pPage)->fSomethingElse = 0; \
574 (pPage)->idPageX = (_idPage); \
575 /*(pPage)->u3Type = (_uType); - later */ \
576 PGM_PAGE_SET_TYPE(pPage, _uType); \
577 (pPage)->u29B = 0; \
578 } while (0)
579
580/**
581 * Initializes the page structure of a ZERO page.
582 * @param pPage Pointer to the physical guest page tracking structure.
583 */
584#ifdef VBOX_WITH_NEW_PHYS_CODE
585# define PGM_PAGE_INIT_ZERO(pPage, pVM, _uType) \
586 PGM_PAGE_INIT(pPage, (pVM)->pgm.s.HCPhysZeroPg, NIL_GMM_PAGEID, (_uType), PGM_PAGE_STATE_ZERO)
587#else
588# define PGM_PAGE_INIT_ZERO(pPage, pVM, _uType) \
589 PGM_PAGE_INIT(pPage, 0, NIL_GMM_PAGEID, (_uType), PGM_PAGE_STATE_ZERO)
590#endif
591/** Temporary hack. Replaced by PGM_PAGE_INIT_ZERO once the old code is kicked out. */
592# define PGM_PAGE_INIT_ZERO_REAL(pPage, pVM, _uType) \
593 PGM_PAGE_INIT(pPage, (pVM)->pgm.s.HCPhysZeroPg, NIL_GMM_PAGEID, (_uType), PGM_PAGE_STATE_ZERO)
594
595
596/** @name The Page state, PGMPAGE::u2StateX.
597 * @{ */
598/** The zero page.
599 * This is a per-VM page that's never ever mapped writable. */
600#define PGM_PAGE_STATE_ZERO 0
601/** A allocated page.
602 * This is a per-VM page allocated from the page pool (or wherever
603 * we get MMIO2 pages from if the type is MMIO2).
604 */
605#define PGM_PAGE_STATE_ALLOCATED 1
606/** A allocated page that's being monitored for writes.
607 * The shadow page table mappings are read-only. When a write occurs, the
608 * fWrittenTo member is set, the page remapped as read-write and the state
609 * moved back to allocated. */
610#define PGM_PAGE_STATE_WRITE_MONITORED 2
611/** The page is shared, aka. copy-on-write.
612 * This is a page that's shared with other VMs. */
613#define PGM_PAGE_STATE_SHARED 3
614/** @} */
615
616
617/**
618 * Gets the page state.
619 * @returns page state (PGM_PAGE_STATE_*).
620 * @param pPage Pointer to the physical guest page tracking structure.
621 */
622#define PGM_PAGE_GET_STATE(pPage) ( (pPage)->u2StateX )
623
624/**
625 * Sets the page state.
626 * @param pPage Pointer to the physical guest page tracking structure.
627 * @param _uState The new page state.
628 */
629#define PGM_PAGE_SET_STATE(pPage, _uState) \
630 do { (pPage)->u2StateX = (_uState); } while (0)
631
632
633/**
634 * Gets the host physical address of the guest page.
635 * @returns host physical address (RTHCPHYS).
636 * @param pPage Pointer to the physical guest page tracking structure.
637 */
638#define PGM_PAGE_GET_HCPHYS(pPage) ( (pPage)->HCPhys & UINT64_C(0x0000fffffffff000) )
639
640/**
641 * Sets the host physical address of the guest page.
642 * @param pPage Pointer to the physical guest page tracking structure.
643 * @param _HCPhys The new host physical address.
644 */
645#define PGM_PAGE_SET_HCPHYS(pPage, _HCPhys) \
646 do { (pPage)->HCPhys = (((pPage)->HCPhys) & UINT64_C(0xffff000000000fff)) \
647 | ((_HCPhys) & UINT64_C(0x0000fffffffff000)); } while (0)
648
649/**
650 * Get the Page ID.
651 * @returns The Page ID; NIL_GMM_PAGEID if it's a ZERO page.
652 * @param pPage Pointer to the physical guest page tracking structure.
653 */
654#define PGM_PAGE_GET_PAGEID(pPage) ( (pPage)->idPageX )
655/* later:
656#define PGM_PAGE_GET_PAGEID(pPage) ( ((uint32_t)(pPage)->HCPhys >> (48 - 12))
657 | ((uint32_t)(pPage)->HCPhys & 0xfff) )
658*/
659/**
660 * Sets the Page ID.
661 * @param pPage Pointer to the physical guest page tracking structure.
662 */
663#define PGM_PAGE_SET_PAGEID(pPage, _idPage) do { (pPage)->idPageX = (_idPage); } while (0)
664/* later:
665#define PGM_PAGE_SET_PAGEID(pPage, _idPage) do { (pPage)->HCPhys = (((pPage)->HCPhys) & UINT64_C(0x0000fffffffff000)) \
666 | ((_idPage) & 0xfff) \
667 | (((_idPage) & 0x0ffff000) << (48-12)); } while (0)
668*/
669
670/**
671 * Get the Chunk ID.
672 * @returns The Chunk ID; NIL_GMM_CHUNKID if it's a ZERO page.
673 * @param pPage Pointer to the physical guest page tracking structure.
674 */
675#define PGM_PAGE_GET_CHUNKID(pPage) ( (pPage)->idPageX >> GMM_CHUNKID_SHIFT )
676/* later:
677#if GMM_CHUNKID_SHIFT == 12
678# define PGM_PAGE_GET_CHUNKID(pPage) ( (uint32_t)((pPage)->HCPhys >> 48) )
679#elif GMM_CHUNKID_SHIFT > 12
680# define PGM_PAGE_GET_CHUNKID(pPage) ( (uint32_t)((pPage)->HCPhys >> (48 + (GMM_CHUNKID_SHIFT - 12)) )
681#elif GMM_CHUNKID_SHIFT < 12
682# define PGM_PAGE_GET_CHUNKID(pPage) ( ( (uint32_t)((pPage)->HCPhys >> 48) << (12 - GMM_CHUNKID_SHIFT) ) \
683 | ( (uint32_t)((pPage)->HCPhys & 0xfff) >> GMM_CHUNKID_SHIFT ) )
684#else
685# error "GMM_CHUNKID_SHIFT isn't defined or something."
686#endif
687*/
688
689/**
690 * Get the index of the page within the allocaiton chunk.
691 * @returns The page index.
692 * @param pPage Pointer to the physical guest page tracking structure.
693 */
694#define PGM_PAGE_GET_PAGE_IN_CHUNK(pPage) ( (pPage)->idPageX & GMM_PAGEID_IDX_MASK )
695/* later:
696#if GMM_CHUNKID_SHIFT <= 12
697# define PGM_PAGE_GET_PAGE_IN_CHUNK(pPage) ( (uint32_t)((pPage)->HCPhys & GMM_PAGEID_IDX_MASK) )
698#else
699# define PGM_PAGE_GET_PAGE_IN_CHUNK(pPage) ( (uint32_t)((pPage)->HCPhys & 0xfff) \
700 | ( (uint32_t)((pPage)->HCPhys >> 48) & (RT_BIT_32(GMM_CHUNKID_SHIFT - 12) - 1) ) )
701#endif
702*/
703
704
705/**
706 * Gets the page type.
707 * @returns The page type.
708 * @param pPage Pointer to the physical guest page tracking structure.
709 */
710#define PGM_PAGE_GET_TYPE(pPage) (pPage)->u3Type
711
712/**
713 * Sets the page type.
714 * @param pPage Pointer to the physical guest page tracking structure.
715 * @param _enmType The new page type (PGMPAGETYPE).
716 */
717#ifdef VBOX_WITH_NEW_PHYS_CODE
718#define PGM_PAGE_SET_TYPE(pPage, _enmType) \
719 do { (pPage)->u3Type = (_enmType); } while (0)
720#else
721#define PGM_PAGE_SET_TYPE(pPage, _enmType) \
722 do { \
723 (pPage)->u3Type = (_enmType); \
724 if ((_enmType) == PGMPAGETYPE_ROM) \
725 (pPage)->HCPhys |= MM_RAM_FLAGS_ROM; \
726 else if ((_enmType) == PGMPAGETYPE_ROM_SHADOW) \
727 (pPage)->HCPhys |= MM_RAM_FLAGS_ROM | MM_RAM_FLAGS_MMIO2; \
728 else if ((_enmType) == PGMPAGETYPE_MMIO2) \
729 (pPage)->HCPhys |= MM_RAM_FLAGS_MMIO2; \
730 } while (0)
731#endif
732
733
734/**
735 * Checks if the page is 'reserved'.
736 * @returns true/false.
737 * @param pPage Pointer to the physical guest page tracking structure.
738 */
739#define PGM_PAGE_IS_RESERVED(pPage) ( !!((pPage)->HCPhys & MM_RAM_FLAGS_RESERVED) )
740
741/**
742 * Checks if the page is marked for MMIO.
743 * @returns true/false.
744 * @param pPage Pointer to the physical guest page tracking structure.
745 */
746#define PGM_PAGE_IS_MMIO(pPage) ( !!((pPage)->HCPhys & MM_RAM_FLAGS_MMIO) )
747
748/**
749 * Checks if the page is backed by the ZERO page.
750 * @returns true/false.
751 * @param pPage Pointer to the physical guest page tracking structure.
752 */
753#define PGM_PAGE_IS_ZERO(pPage) ( (pPage)->u2StateX == PGM_PAGE_STATE_ZERO )
754
755/**
756 * Checks if the page is backed by a SHARED page.
757 * @returns true/false.
758 * @param pPage Pointer to the physical guest page tracking structure.
759 */
760#define PGM_PAGE_IS_SHARED(pPage) ( (pPage)->u2StateX == PGM_PAGE_STATE_SHARED )
761
762
763/**
764 * Marks the paget as written to (for GMM change monitoring).
765 * @param pPage Pointer to the physical guest page tracking structure.
766 */
767#define PGM_PAGE_SET_WRITTEN_TO(pPage) do { (pPage)->fWrittenToX = 1; } while (0)
768
769/**
770 * Clears the written-to indicator.
771 * @param pPage Pointer to the physical guest page tracking structure.
772 */
773#define PGM_PAGE_CLEAR_WRITTEN_TO(pPage) do { (pPage)->fWrittenToX = 0; } while (0)
774
775/**
776 * Checks if the page was marked as written-to.
777 * @returns true/false.
778 * @param pPage Pointer to the physical guest page tracking structure.
779 */
780#define PGM_PAGE_IS_WRITTEN_TO(pPage) ( (pPage)->fWrittenToX )
781
782
783/** @name Physical Access Handler State values (PGMPAGE::u2HandlerPhysStateX).
784 *
785 * @remarks The values are assigned in order of priority, so we can calculate
786 * the correct state for a page with different handlers installed.
787 * @{ */
788/** No handler installed. */
789#define PGM_PAGE_HNDL_PHYS_STATE_NONE 0
790/** Monitoring is temporarily disabled. */
791#define PGM_PAGE_HNDL_PHYS_STATE_DISABLED 1
792/** Write access is monitored. */
793#define PGM_PAGE_HNDL_PHYS_STATE_WRITE 2
794/** All access is monitored. */
795#define PGM_PAGE_HNDL_PHYS_STATE_ALL 3
796/** @} */
797
798/**
799 * Gets the physical access handler state of a page.
800 * @returns PGM_PAGE_HNDL_PHYS_STATE_* value.
801 * @param pPage Pointer to the physical guest page tracking structure.
802 */
803#define PGM_PAGE_GET_HNDL_PHYS_STATE(pPage) ( (pPage)->u2HandlerPhysStateX )
804
805/**
806 * Sets the physical access handler state of a page.
807 * @param pPage Pointer to the physical guest page tracking structure.
808 * @param _uState The new state value.
809 */
810#define PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, _uState) \
811 do { (pPage)->u2HandlerPhysStateX = (_uState); } while (0)
812
813/**
814 * Checks if the page has any physical access handlers, including temporariliy disabled ones.
815 * @returns true/false
816 * @param pPage Pointer to the physical guest page tracking structure.
817 */
818#define PGM_PAGE_HAS_ANY_PHYSICAL_HANDLERS(pPage) ( (pPage)->u2HandlerPhysStateX != PGM_PAGE_HNDL_PHYS_STATE_NONE )
819
820/**
821 * Checks if the page has any active physical access handlers.
822 * @returns true/false
823 * @param pPage Pointer to the physical guest page tracking structure.
824 */
825#define PGM_PAGE_HAS_ACTIVE_PHYSICAL_HANDLERS(pPage) ( (pPage)->u2HandlerPhysStateX >= PGM_PAGE_HNDL_PHYS_STATE_WRITE )
826
827
828/** @name Virtual Access Handler State values (PGMPAGE::u2HandlerVirtStateX).
829 *
830 * @remarks The values are assigned in order of priority, so we can calculate
831 * the correct state for a page with different handlers installed.
832 * @{ */
833/** No handler installed. */
834#define PGM_PAGE_HNDL_VIRT_STATE_NONE 0
835/* 1 is reserved so the lineup is identical with the physical ones. */
836/** Write access is monitored. */
837#define PGM_PAGE_HNDL_VIRT_STATE_WRITE 2
838/** All access is monitored. */
839#define PGM_PAGE_HNDL_VIRT_STATE_ALL 3
840/** @} */
841
842/**
843 * Gets the virtual access handler state of a page.
844 * @returns PGM_PAGE_HNDL_VIRT_STATE_* value.
845 * @param pPage Pointer to the physical guest page tracking structure.
846 */
847#define PGM_PAGE_GET_HNDL_VIRT_STATE(pPage) ( (pPage)->u2HandlerVirtStateX )
848
849/**
850 * Sets the virtual access handler state of a page.
851 * @param pPage Pointer to the physical guest page tracking structure.
852 * @param _uState The new state value.
853 */
854#define PGM_PAGE_SET_HNDL_VIRT_STATE(pPage, _uState) \
855 do { (pPage)->u2HandlerVirtStateX = (_uState); } while (0)
856
857/**
858 * Checks if the page has any virtual access handlers.
859 * @returns true/false
860 * @param pPage Pointer to the physical guest page tracking structure.
861 */
862#define PGM_PAGE_HAS_ANY_VIRTUAL_HANDLERS(pPage) ( (pPage)->u2HandlerVirtStateX != PGM_PAGE_HNDL_VIRT_STATE_NONE )
863
864/**
865 * Same as PGM_PAGE_HAS_ANY_VIRTUAL_HANDLERS - can't disable pages in
866 * virtual handlers.
867 * @returns true/false
868 * @param pPage Pointer to the physical guest page tracking structure.
869 */
870#define PGM_PAGE_HAS_ACTIVE_VIRTUAL_HANDLERS(pPage) PGM_PAGE_HAS_ANY_VIRTUAL_HANDLERS(pPage)
871
872
873
874/**
875 * Checks if the page has any access handlers, including temporarily disabled ones.
876 * @returns true/false
877 * @param pPage Pointer to the physical guest page tracking structure.
878 */
879#define PGM_PAGE_HAS_ANY_HANDLERS(pPage) \
880 ( (pPage)->u2HandlerPhysStateX != PGM_PAGE_HNDL_PHYS_STATE_NONE \
881 || (pPage)->u2HandlerVirtStateX != PGM_PAGE_HNDL_VIRT_STATE_NONE )
882
883/**
884 * Checks if the page has any active access handlers.
885 * @returns true/false
886 * @param pPage Pointer to the physical guest page tracking structure.
887 */
888#define PGM_PAGE_HAS_ACTIVE_HANDLERS(pPage) \
889 ( (pPage)->u2HandlerPhysStateX >= PGM_PAGE_HNDL_PHYS_STATE_WRITE \
890 || (pPage)->u2HandlerVirtStateX >= PGM_PAGE_HNDL_VIRT_STATE_WRITE )
891
892/**
893 * Checks if the page has any active access handlers catching all accesses.
894 * @returns true/false
895 * @param pPage Pointer to the physical guest page tracking structure.
896 */
897#define PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(pPage) \
898 ( (pPage)->u2HandlerPhysStateX == PGM_PAGE_HNDL_PHYS_STATE_ALL \
899 || (pPage)->u2HandlerVirtStateX == PGM_PAGE_HNDL_VIRT_STATE_ALL )
900
901
902/**
903 * Ram range for GC Phys to HC Phys conversion.
904 *
905 * Can be used for HC Virt to GC Phys and HC Virt to HC Phys
906 * conversions too, but we'll let MM handle that for now.
907 *
908 * This structure is used by linked lists in both GC and HC.
909 */
910typedef struct PGMRAMRANGE
911{
912 /** Pointer to the next RAM range - for R3. */
913 R3PTRTYPE(struct PGMRAMRANGE *) pNextR3;
914 /** Pointer to the next RAM range - for R0. */
915 R0PTRTYPE(struct PGMRAMRANGE *) pNextR0;
916 /** Pointer to the next RAM range - for GC. */
917 GCPTRTYPE(struct PGMRAMRANGE *) pNextGC;
918#if GC_ARCH_BITS == 32
919 /** Pointer alignment. */
920 RTGCPTR GCPtrAlignment;
921#endif
922 /** Start of the range. Page aligned. */
923 RTGCPHYS GCPhys;
924 /** Last address in the range (inclusive). Page aligned (-1). */
925 RTGCPHYS GCPhysLast;
926 /** Size of the range. (Page aligned of course). */
927 RTGCPHYS cb;
928 /** MM_RAM_* flags */
929 uint32_t fFlags;
930#ifdef VBOX_WITH_NEW_PHYS_CODE
931 uint32_t u32Alignment; /**< alignment. */
932#else
933 /** HC virtual lookup ranges for chunks. Currently only used with MM_RAM_FLAGS_DYNAMIC_ALLOC ranges. */
934 GCPTRTYPE(PRTHCPTR) pavHCChunkGC;
935 /** HC virtual lookup ranges for chunks. Currently only used with MM_RAM_FLAGS_DYNAMIC_ALLOC ranges. */
936 R3R0PTRTYPE(PRTHCPTR) pavHCChunkHC;
937#endif
938 /** Start of the HC mapping of the range. This is only used for MMIO2. */
939 R3PTRTYPE(void *) pvHC;
940 /** The range description. */
941 R3PTRTYPE(const char *) pszDesc;
942
943 /** Padding to make aPage aligned on sizeof(PGMPAGE). */
944#ifdef VBOX_WITH_NEW_PHYS_CODE
945 uint32_t au32Reserved[2];
946#elif HC_ARCH_BITS == 32
947 uint32_t au32Reserved[1];
948#endif
949
950 /** Array of physical guest page tracking structures. */
951 PGMPAGE aPages[1];
952} PGMRAMRANGE;
953/** Pointer to Ram range for GC Phys to HC Phys conversion. */
954typedef PGMRAMRANGE *PPGMRAMRANGE;
955
956/** Return hc ptr corresponding to the ram range and physical offset */
957#define PGMRAMRANGE_GETHCPTR(pRam, off) \
958 (pRam->fFlags & MM_RAM_FLAGS_DYNAMIC_ALLOC) ? (RTHCPTR)((RTHCUINTPTR)CTXSUFF(pRam->pavHCChunk)[(off >> PGM_DYNAMIC_CHUNK_SHIFT)] + (off & PGM_DYNAMIC_CHUNK_OFFSET_MASK)) \
959 : (RTHCPTR)((RTHCUINTPTR)pRam->pvHC + off);
960
961/**
962 * Per page tracking structure for ROM image.
963 *
964 * A ROM image may have a shadow page, in which case we may have
965 * two pages backing it. This structure contains the PGMPAGE for
966 * both while PGMRAMRANGE have a copy of the active one. It is
967 * important that these aren't out of sync in any regard other
968 * than page pool tracking data.
969 */
970typedef struct PGMROMPAGE
971{
972 /** The page structure for the virgin ROM page. */
973 PGMPAGE Virgin;
974 /** The page structure for the shadow RAM page. */
975 PGMPAGE Shadow;
976 /** The current protection setting. */
977 PGMROMPROT enmProt;
978 /** Pad the structure size to a multiple of 8. */
979 uint32_t u32Padding;
980} PGMROMPAGE;
981/** Pointer to a ROM page tracking structure. */
982typedef PGMROMPAGE *PPGMROMPAGE;
983
984
985/**
986 * A registered ROM image.
987 *
988 * This is needed to keep track of ROM image since they generally
989 * intrude into a PGMRAMRANGE. It also keeps track of additional
990 * info like the two page sets (read-only virgin and read-write shadow),
991 * the current state of each page.
992 *
993 * Because access handlers cannot easily be executed in a different
994 * context, the ROM ranges needs to be accessible and in all contexts.
995 */
996typedef struct PGMROMRANGE
997{
998 /** Pointer to the next range - R3. */
999 R3PTRTYPE(struct PGMROMRANGE *) pNextR3;
1000 /** Pointer to the next range - R0. */
1001 R0PTRTYPE(struct PGMROMRANGE *) pNextR0;
1002 /** Pointer to the next range - GC. */
1003 GCPTRTYPE(struct PGMROMRANGE *) pNextGC;
1004#if GC_ARCH_BITS == 32
1005 RTGCPTR GCPtrAlignment; /**< Pointer alignment. */
1006#endif
1007 /** Address of the range. */
1008 RTGCPHYS GCPhys;
1009 /** Address of the last byte in the range. */
1010 RTGCPHYS GCPhysLast;
1011 /** Size of the range. */
1012 RTGCPHYS cb;
1013 /** The flags (PGMPHYS_ROM_FLAG_*). */
1014 uint32_t fFlags;
1015 /**< Alignment padding ensuring that aPages is sizeof(PGMROMPAGE) aligned. */
1016 uint32_t au32Alignemnt[HC_ARCH_BITS == 32 ? 7 : 3];
1017 /** Pointer to the original bits when PGMPHYS_ROM_FLAG_PERMANENT_BINARY was specified.
1018 * This is used for strictness checks. */
1019 R3PTRTYPE(const void *) pvOriginal;
1020 /** The ROM description. */
1021 R3PTRTYPE(const char *) pszDesc;
1022 /** The per page tracking structures. */
1023 PGMROMPAGE aPages[1];
1024} PGMROMRANGE;
1025/** Pointer to a ROM range. */
1026typedef PGMROMRANGE *PPGMROMRANGE;
1027
1028
1029/**
1030 * A registered MMIO2 (= Device RAM) range.
1031 *
1032 * There are a few reason why we need to keep track of these
1033 * registrations. One of them is the deregistration & cleanup
1034 * stuff, while another is that the PGMRAMRANGE associated with
1035 * such a region may have to be removed from the ram range list.
1036 *
1037 * Overlapping with a RAM range has to be 100% or none at all. The
1038 * pages in the existing RAM range must not be ROM nor MMIO. A guru
1039 * meditation will be raised if a partial overlap or an overlap of
1040 * ROM pages is encountered. On an overlap we will free all the
1041 * existing RAM pages and put in the ram range pages instead.
1042 */
1043typedef struct PGMMMIO2RANGE
1044{
1045 /** The owner of the range. (a device) */
1046 PPDMDEVINSR3 pDevInsR3;
1047 /** Pointer to the ring-3 mapping of the allocation. */
1048 RTR3PTR pvR3;
1049 /** Pointer to the next range - R3. */
1050 R3PTRTYPE(struct PGMMMIO2RANGE *) pNextR3;
1051 /** Whether it's mapped or not. */
1052 bool fMapped;
1053 /** Whether it's overlapping or not. */
1054 bool fOverlapping;
1055 /** The PCI region number.
1056 * @remarks This ASSUMES that nobody will ever really need to have multiple
1057 * PCI devices with matching MMIO region numbers on a single device. */
1058 uint8_t iRegion;
1059 /**< Alignment padding for putting the ram range on a PGMPAGE alignment boundrary. */
1060 uint8_t abAlignemnt[HC_ARCH_BITS == 32 ? 1 : 5];
1061 /** The associated RAM range. */
1062 PGMRAMRANGE RamRange;
1063} PGMMMIO2RANGE;
1064/** Pointer to a MMIO2 range. */
1065typedef PGMMMIO2RANGE *PPGMMMIO2RANGE;
1066
1067
1068
1069
1070/** @todo r=bird: fix typename. */
1071/**
1072 * PGMPhysRead/Write cache entry
1073 */
1074typedef struct PGMPHYSCACHE_ENTRY
1075{
1076 /** HC pointer to physical page */
1077 R3PTRTYPE(uint8_t *) pbHC;
1078 /** GC Physical address for cache entry */
1079 RTGCPHYS GCPhys;
1080#if HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32
1081 RTGCPHYS u32Padding0; /**< alignment padding. */
1082#endif
1083} PGMPHYSCACHE_ENTRY;
1084
1085/**
1086 * PGMPhysRead/Write cache to reduce REM memory access overhead
1087 */
1088typedef struct PGMPHYSCACHE
1089{
1090 /** Bitmap of valid cache entries */
1091 uint64_t aEntries;
1092 /** Cache entries */
1093 PGMPHYSCACHE_ENTRY Entry[PGM_MAX_PHYSCACHE_ENTRIES];
1094} PGMPHYSCACHE;
1095
1096
1097/** Pointer to an allocation chunk ring-3 mapping. */
1098typedef struct PGMCHUNKR3MAP *PPGMCHUNKR3MAP;
1099/** Pointer to an allocation chunk ring-3 mapping pointer. */
1100typedef PPGMCHUNKR3MAP *PPPGMCHUNKR3MAP;
1101
1102/**
1103 * Ring-3 tracking structore for an allocation chunk ring-3 mapping.
1104 *
1105 * The primary tree (Core) uses the chunk id as key.
1106 * The secondary tree (AgeCore) is used for ageing and uses ageing sequence number as key.
1107 */
1108typedef struct PGMCHUNKR3MAP
1109{
1110 /** The key is the chunk id. */
1111 AVLU32NODECORE Core;
1112 /** The key is the ageing sequence number. */
1113 AVLLU32NODECORE AgeCore;
1114 /** The current age thingy. */
1115 uint32_t iAge;
1116 /** The current reference count. */
1117 uint32_t volatile cRefs;
1118 /** The current permanent reference count. */
1119 uint32_t volatile cPermRefs;
1120 /** The mapping address. */
1121 void *pv;
1122} PGMCHUNKR3MAP;
1123
1124/**
1125 * Allocation chunk ring-3 mapping TLB entry.
1126 */
1127typedef struct PGMCHUNKR3MAPTLBE
1128{
1129 /** The chunk id. */
1130 uint32_t volatile idChunk;
1131#if HC_ARCH_BITS == 64
1132 uint32_t u32Padding; /**< alignment padding. */
1133#endif
1134 /** The chunk map. */
1135 R3R0PTRTYPE(PPGMCHUNKR3MAP) volatile pChunk;
1136} PGMCHUNKR3MAPTLBE;
1137/** Pointer to the an allocation chunk ring-3 mapping TLB entry. */
1138typedef PGMCHUNKR3MAPTLBE *PPGMCHUNKR3MAPTLBE;
1139
1140/** The number of TLB entries in PGMCHUNKR3MAPTLB.
1141 * @remark Must be a power of two value. */
1142#define PGM_CHUNKR3MAPTLB_ENTRIES 32
1143
1144/**
1145 * Allocation chunk ring-3 mapping TLB.
1146 *
1147 * @remarks We use a TLB to speed up lookups by avoiding walking the AVL.
1148 * At first glance this might look kinda odd since AVL trees are
1149 * supposed to give the most optimial lookup times of all trees
1150 * due to their balancing. However, take a tree with 1023 nodes
1151 * in it, that's 10 levels, meaning that most searches has to go
1152 * down 9 levels before they find what they want. This isn't fast
1153 * compared to a TLB hit. There is the factor of cache misses,
1154 * and of course the problem with trees and branch prediction.
1155 * This is why we use TLBs in front of most of the trees.
1156 *
1157 * @todo Generalize this TLB + AVL stuff, shouldn't be all that
1158 * difficult when we switch to inlined AVL trees (from kStuff).
1159 */
1160typedef struct PGMCHUNKR3MAPTLB
1161{
1162 /** The TLB entries. */
1163 PGMCHUNKR3MAPTLBE aEntries[PGM_CHUNKR3MAPTLB_ENTRIES];
1164} PGMCHUNKR3MAPTLB;
1165
1166/**
1167 * Calculates the index of a guest page in the Ring-3 Chunk TLB.
1168 * @returns Chunk TLB index.
1169 * @param idChunk The Chunk ID.
1170 */
1171#define PGM_CHUNKR3MAPTLB_IDX(idChunk) ( (idChunk) & (PGM_CHUNKR3MAPTLB_ENTRIES - 1) )
1172
1173
1174/**
1175 * Ring-3 guest page mapping TLB entry.
1176 * @remarks used in ring-0 as well at the moment.
1177 */
1178typedef struct PGMPAGER3MAPTLBE
1179{
1180 /** Address of the page. */
1181 RTGCPHYS volatile GCPhys;
1182 /** The guest page. */
1183 R3R0PTRTYPE(PPGMPAGE) volatile pPage;
1184 /** Pointer to the page mapping tracking structure, PGMCHUNKR3MAP. */
1185 R3R0PTRTYPE(PPGMCHUNKR3MAP) volatile pMap;
1186 /** The address */
1187 R3R0PTRTYPE(void *) volatile pv;
1188#if HC_ARCH_BITS == 32
1189 uint32_t u32Padding; /**< alignment padding. */
1190#endif
1191} PGMPAGER3MAPTLBE;
1192/** Pointer to an entry in the HC physical TLB. */
1193typedef PGMPAGER3MAPTLBE *PPGMPAGER3MAPTLBE;
1194
1195
1196/** The number of entries in the ring-3 guest page mapping TLB.
1197 * @remarks The value must be a power of two. */
1198#define PGM_PAGER3MAPTLB_ENTRIES 64
1199
1200/**
1201 * Ring-3 guest page mapping TLB.
1202 * @remarks used in ring-0 as well at the moment.
1203 */
1204typedef struct PGMPAGER3MAPTLB
1205{
1206 /** The TLB entries. */
1207 PGMPAGER3MAPTLBE aEntries[PGM_PAGER3MAPTLB_ENTRIES];
1208} PGMPAGER3MAPTLB;
1209/** Pointer to the ring-3 guest page mapping TLB. */
1210typedef PGMPAGER3MAPTLB *PPGMPAGER3MAPTLB;
1211
1212/**
1213 * Calculates the index of the TLB entry for the specified guest page.
1214 * @returns Physical TLB index.
1215 * @param GCPhys The guest physical address.
1216 */
1217#define PGM_PAGER3MAPTLB_IDX(GCPhys) ( ((GCPhys) >> PAGE_SHIFT) & (PGM_PAGER3MAPTLB_ENTRIES - 1) )
1218
1219
1220/** @name Context neutrual page mapper TLB.
1221 *
1222 * Hoping to avoid some code and bug duplication parts of the GCxxx->CCPtr
1223 * code is writting in a kind of context neutrual way. Time will show whether
1224 * this actually makes sense or not...
1225 *
1226 * @{ */
1227/** @typedef PPGMPAGEMAPTLB
1228 * The page mapper TLB pointer type for the current context. */
1229/** @typedef PPGMPAGEMAPTLB
1230 * The page mapper TLB entry pointer type for the current context. */
1231/** @typedef PPGMPAGEMAPTLB
1232 * The page mapper TLB entry pointer pointer type for the current context. */
1233/** @def PGMPAGEMAPTLB_ENTRIES
1234 * The number of TLB entries in the page mapper TLB for the current context. */
1235/** @def PGM_PAGEMAPTLB_IDX
1236 * Calculate the TLB index for a guest physical address.
1237 * @returns The TLB index.
1238 * @param GCPhys The guest physical address. */
1239/** @typedef PPGMPAGEMAP
1240 * Pointer to a page mapper unit for current context. */
1241/** @typedef PPPGMPAGEMAP
1242 * Pointer to a page mapper unit pointer for current context. */
1243#ifdef IN_GC
1244// typedef PPGMPAGEGCMAPTLB PPGMPAGEMAPTLB;
1245// typedef PPGMPAGEGCMAPTLBE PPGMPAGEMAPTLBE;
1246// typedef PPGMPAGEGCMAPTLBE *PPPGMPAGEMAPTLBE;
1247# define PGM_PAGEMAPTLB_ENTRIES PGM_PAGEGCMAPTLB_ENTRIES
1248# define PGM_PAGEMAPTLB_IDX(GCPhys) PGM_PAGEGCMAPTLB_IDX(GCPhys)
1249 typedef void * PPGMPAGEMAP;
1250 typedef void ** PPPGMPAGEMAP;
1251//#elif IN_RING0
1252// typedef PPGMPAGER0MAPTLB PPGMPAGEMAPTLB;
1253// typedef PPGMPAGER0MAPTLBE PPGMPAGEMAPTLBE;
1254// typedef PPGMPAGER0MAPTLBE *PPPGMPAGEMAPTLBE;
1255//# define PGM_PAGEMAPTLB_ENTRIES PGM_PAGER0MAPTLB_ENTRIES
1256//# define PGM_PAGEMAPTLB_IDX(GCPhys) PGM_PAGER0MAPTLB_IDX(GCPhys)
1257// typedef PPGMCHUNKR0MAP PPGMPAGEMAP;
1258// typedef PPPGMCHUNKR0MAP PPPGMPAGEMAP;
1259#else
1260 typedef PPGMPAGER3MAPTLB PPGMPAGEMAPTLB;
1261 typedef PPGMPAGER3MAPTLBE PPGMPAGEMAPTLBE;
1262 typedef PPGMPAGER3MAPTLBE *PPPGMPAGEMAPTLBE;
1263# define PGM_PAGEMAPTLB_ENTRIES PGM_PAGER3MAPTLB_ENTRIES
1264# define PGM_PAGEMAPTLB_IDX(GCPhys) PGM_PAGER3MAPTLB_IDX(GCPhys)
1265 typedef PPGMCHUNKR3MAP PPGMPAGEMAP;
1266 typedef PPPGMCHUNKR3MAP PPPGMPAGEMAP;
1267#endif
1268/** @} */
1269
1270
1271/** @name PGM Pool Indexes.
1272 * Aka. the unique shadow page identifier.
1273 * @{ */
1274/** NIL page pool IDX. */
1275#define NIL_PGMPOOL_IDX 0
1276/** The first normal index. */
1277#define PGMPOOL_IDX_FIRST_SPECIAL 1
1278/** Page directory (32-bit root). */
1279#define PGMPOOL_IDX_PD 1
1280/** The extended PAE page directory (2048 entries, works as root currently). */
1281#define PGMPOOL_IDX_PAE_PD 2
1282/** Page Directory Pointer Table (PAE root, not currently used). */
1283#define PGMPOOL_IDX_PDPT 3
1284/** Page Map Level-4 (64-bit root). */
1285#define PGMPOOL_IDX_PML4 4
1286/** The first normal index. */
1287#define PGMPOOL_IDX_FIRST 5
1288/** The last valid index. (inclusive, 14 bits) */
1289#define PGMPOOL_IDX_LAST 0x3fff
1290/** @} */
1291
1292/** The NIL index for the parent chain. */
1293#define NIL_PGMPOOL_USER_INDEX ((uint16_t)0xffff)
1294
1295/**
1296 * Node in the chain linking a shadowed page to it's parent (user).
1297 */
1298#pragma pack(1)
1299typedef struct PGMPOOLUSER
1300{
1301 /** The index to the next item in the chain. NIL_PGMPOOL_USER_INDEX is no next. */
1302 uint16_t iNext;
1303 /** The user page index. */
1304 uint16_t iUser;
1305 /** Index into the user table. */
1306 uint16_t iUserTable;
1307} PGMPOOLUSER, *PPGMPOOLUSER;
1308typedef const PGMPOOLUSER *PCPGMPOOLUSER;
1309#pragma pack()
1310
1311
1312/** The NIL index for the phys ext chain. */
1313#define NIL_PGMPOOL_PHYSEXT_INDEX ((uint16_t)0xffff)
1314
1315/**
1316 * Node in the chain of physical cross reference extents.
1317 */
1318#pragma pack(1)
1319typedef struct PGMPOOLPHYSEXT
1320{
1321 /** The index to the next item in the chain. NIL_PGMPOOL_PHYSEXT_INDEX is no next. */
1322 uint16_t iNext;
1323 /** The user page index. */
1324 uint16_t aidx[3];
1325} PGMPOOLPHYSEXT, *PPGMPOOLPHYSEXT;
1326typedef const PGMPOOLPHYSEXT *PCPGMPOOLPHYSEXT;
1327#pragma pack()
1328
1329
1330/**
1331 * The kind of page that's being shadowed.
1332 */
1333typedef enum PGMPOOLKIND
1334{
1335 /** The virtual invalid 0 entry. */
1336 PGMPOOLKIND_INVALID = 0,
1337 /** The entry is free (=unused). */
1338 PGMPOOLKIND_FREE,
1339
1340 /** Shw: 32-bit page table; Gst: no paging */
1341 PGMPOOLKIND_32BIT_PT_FOR_PHYS,
1342 /** Shw: 32-bit page table; Gst: 32-bit page table. */
1343 PGMPOOLKIND_32BIT_PT_FOR_32BIT_PT,
1344 /** Shw: 32-bit page table; Gst: 4MB page. */
1345 PGMPOOLKIND_32BIT_PT_FOR_32BIT_4MB,
1346 /** Shw: PAE page table; Gst: no paging */
1347 PGMPOOLKIND_PAE_PT_FOR_PHYS,
1348 /** Shw: PAE page table; Gst: 32-bit page table. */
1349 PGMPOOLKIND_PAE_PT_FOR_32BIT_PT,
1350 /** Shw: PAE page table; Gst: Half of a 4MB page. */
1351 PGMPOOLKIND_PAE_PT_FOR_32BIT_4MB,
1352 /** Shw: PAE page table; Gst: PAE page table. */
1353 PGMPOOLKIND_PAE_PT_FOR_PAE_PT,
1354 /** Shw: PAE page table; Gst: 2MB page. */
1355 PGMPOOLKIND_PAE_PT_FOR_PAE_2MB,
1356
1357 /** Shw: PAE page directory; Gst: 32-bit page directory. */
1358 PGMPOOLKIND_PAE_PD_FOR_32BIT_PD,
1359 /** Shw: PAE page directory; Gst: PAE page directory. */
1360 PGMPOOLKIND_PAE_PD_FOR_PAE_PD,
1361
1362 /** Shw: 64-bit page directory pointer table; Gst: 64-bit page directory pointer table. */
1363 PGMPOOLKIND_64BIT_PDPT_FOR_64BIT_PDPT,
1364
1365 /** Shw: Root 32-bit page directory. */
1366 PGMPOOLKIND_ROOT_32BIT_PD,
1367 /** Shw: Root PAE page directory */
1368 PGMPOOLKIND_ROOT_PAE_PD,
1369 /** Shw: Root PAE page directory pointer table (legacy, 4 entries). */
1370 PGMPOOLKIND_ROOT_PDPT,
1371 /** Shw: Root page map level-4 table. */
1372 PGMPOOLKIND_ROOT_PML4,
1373
1374 /** The last valid entry. */
1375 PGMPOOLKIND_LAST = PGMPOOLKIND_ROOT_PML4
1376} PGMPOOLKIND;
1377
1378
1379/**
1380 * The tracking data for a page in the pool.
1381 */
1382typedef struct PGMPOOLPAGE
1383{
1384 /** AVL node code with the (HC) physical address of this page. */
1385 AVLOHCPHYSNODECORE Core;
1386 /** Pointer to the HC mapping of the page. */
1387 R3R0PTRTYPE(void *) pvPageHC;
1388 /** The guest physical address. */
1389 RTGCPHYS GCPhys;
1390 /** The kind of page we're shadowing. (This is really a PGMPOOLKIND enum.) */
1391 uint8_t enmKind;
1392 uint8_t bPadding;
1393 /** The index of this page. */
1394 uint16_t idx;
1395 /** The next entry in the list this page currently resides in.
1396 * It's either in the free list or in the GCPhys hash. */
1397 uint16_t iNext;
1398#ifdef PGMPOOL_WITH_USER_TRACKING
1399 /** Head of the user chain. NIL_PGMPOOL_USER_INDEX if not currently in use. */
1400 uint16_t iUserHead;
1401 /** The number of present entries. */
1402 uint16_t cPresent;
1403 /** The first entry in the table which is present. */
1404 uint16_t iFirstPresent;
1405#endif
1406#ifdef PGMPOOL_WITH_MONITORING
1407 /** The number of modifications to the monitored page. */
1408 uint16_t cModifications;
1409 /** The next modified page. NIL_PGMPOOL_IDX if tail. */
1410 uint16_t iModifiedNext;
1411 /** The previous modified page. NIL_PGMPOOL_IDX if head. */
1412 uint16_t iModifiedPrev;
1413 /** The next page sharing access handler. NIL_PGMPOOL_IDX if tail. */
1414 uint16_t iMonitoredNext;
1415 /** The previous page sharing access handler. NIL_PGMPOOL_IDX if head. */
1416 uint16_t iMonitoredPrev;
1417#endif
1418#ifdef PGMPOOL_WITH_CACHE
1419 /** The next page in the age list. */
1420 uint16_t iAgeNext;
1421 /** The previous page in the age list. */
1422 uint16_t iAgePrev;
1423#endif /* PGMPOOL_WITH_CACHE */
1424 /** Used to indicate that the page is zeroed. */
1425 bool fZeroed;
1426 /** Used to indicate that a PT has non-global entries. */
1427 bool fSeenNonGlobal;
1428 /** Used to indicate that we're monitoring writes to the guest page. */
1429 bool fMonitored;
1430 /** Used to indicate that the page is in the cache (e.g. in the GCPhys hash).
1431 * (All pages are in the age list.) */
1432 bool fCached;
1433 /** This is used by the R3 access handlers when invoked by an async thread.
1434 * It's a hack required because of REMR3NotifyHandlerPhysicalDeregister. */
1435 bool volatile fReusedFlushPending;
1436 /** Used to indicate that the guest is mapping the page is also used as a CR3.
1437 * In these cases the access handler acts differently and will check
1438 * for mapping conflicts like the normal CR3 handler.
1439 * @todo When we change the CR3 shadowing to use pool pages, this flag can be
1440 * replaced by a list of pages which share access handler.
1441 */
1442 bool fCR3Mix;
1443} PGMPOOLPAGE, *PPGMPOOLPAGE, **PPPGMPOOLPAGE;
1444
1445
1446#ifdef PGMPOOL_WITH_CACHE
1447/** The hash table size. */
1448# define PGMPOOL_HASH_SIZE 0x40
1449/** The hash function. */
1450# define PGMPOOL_HASH(GCPhys) ( ((GCPhys) >> PAGE_SHIFT) & (PGMPOOL_HASH_SIZE - 1) )
1451#endif
1452
1453
1454/**
1455 * The shadow page pool instance data.
1456 *
1457 * It's all one big allocation made at init time, except for the
1458 * pages that is. The user nodes follows immediatly after the
1459 * page structures.
1460 */
1461typedef struct PGMPOOL
1462{
1463 /** The VM handle - HC Ptr. */
1464 R3R0PTRTYPE(PVM) pVMHC;
1465 /** The VM handle - GC Ptr. */
1466 GCPTRTYPE(PVM) pVMGC;
1467 /** The max pool size. This includes the special IDs. */
1468 uint16_t cMaxPages;
1469 /** The current pool size. */
1470 uint16_t cCurPages;
1471 /** The head of the free page list. */
1472 uint16_t iFreeHead;
1473 /* Padding. */
1474 uint16_t u16Padding;
1475#ifdef PGMPOOL_WITH_USER_TRACKING
1476 /** Head of the chain of free user nodes. */
1477 uint16_t iUserFreeHead;
1478 /** The number of user nodes we've allocated. */
1479 uint16_t cMaxUsers;
1480 /** The number of present page table entries in the entire pool. */
1481 uint32_t cPresent;
1482 /** Pointer to the array of user nodes - GC pointer. */
1483 GCPTRTYPE(PPGMPOOLUSER) paUsersGC;
1484 /** Pointer to the array of user nodes - HC pointer. */
1485 R3R0PTRTYPE(PPGMPOOLUSER) paUsersHC;
1486#endif /* PGMPOOL_WITH_USER_TRACKING */
1487#ifdef PGMPOOL_WITH_GCPHYS_TRACKING
1488 /** Head of the chain of free phys ext nodes. */
1489 uint16_t iPhysExtFreeHead;
1490 /** The number of user nodes we've allocated. */
1491 uint16_t cMaxPhysExts;
1492 /** Pointer to the array of physical xref extent - GC pointer. */
1493 GCPTRTYPE(PPGMPOOLPHYSEXT) paPhysExtsGC;
1494 /** Pointer to the array of physical xref extent nodes - HC pointer. */
1495 R3R0PTRTYPE(PPGMPOOLPHYSEXT) paPhysExtsHC;
1496#endif /* PGMPOOL_WITH_GCPHYS_TRACKING */
1497#ifdef PGMPOOL_WITH_CACHE
1498 /** Hash table for GCPhys addresses. */
1499 uint16_t aiHash[PGMPOOL_HASH_SIZE];
1500 /** The head of the age list. */
1501 uint16_t iAgeHead;
1502 /** The tail of the age list. */
1503 uint16_t iAgeTail;
1504 /** Set if the cache is enabled. */
1505 bool fCacheEnabled;
1506#endif /* PGMPOOL_WITH_CACHE */
1507#ifdef PGMPOOL_WITH_MONITORING
1508 /** Head of the list of modified pages. */
1509 uint16_t iModifiedHead;
1510 /** The current number of modified pages. */
1511 uint16_t cModifiedPages;
1512 /** Access handler, GC. */
1513 GCPTRTYPE(PFNPGMGCPHYSHANDLER) pfnAccessHandlerGC;
1514 /** Access handler, R0. */
1515 R0PTRTYPE(PFNPGMR0PHYSHANDLER) pfnAccessHandlerR0;
1516 /** Access handler, R3. */
1517 R3PTRTYPE(PFNPGMR3PHYSHANDLER) pfnAccessHandlerR3;
1518 /** The access handler description (HC ptr). */
1519 R3PTRTYPE(const char *) pszAccessHandler;
1520#endif /* PGMPOOL_WITH_MONITORING */
1521 /** The number of pages currently in use. */
1522 uint16_t cUsedPages;
1523#ifdef VBOX_WITH_STATISTICS
1524 /** The high wather mark for cUsedPages. */
1525 uint16_t cUsedPagesHigh;
1526 uint32_t Alignment1; /**< Align the next member on a 64-bit boundrary. */
1527 /** Profiling pgmPoolAlloc(). */
1528 STAMPROFILEADV StatAlloc;
1529 /** Profiling pgmPoolClearAll(). */
1530 STAMPROFILE StatClearAll;
1531 /** Profiling pgmPoolFlushAllInt(). */
1532 STAMPROFILE StatFlushAllInt;
1533 /** Profiling pgmPoolFlushPage(). */
1534 STAMPROFILE StatFlushPage;
1535 /** Profiling pgmPoolFree(). */
1536 STAMPROFILE StatFree;
1537 /** Profiling time spent zeroing pages. */
1538 STAMPROFILE StatZeroPage;
1539# ifdef PGMPOOL_WITH_USER_TRACKING
1540 /** Profiling of pgmPoolTrackDeref. */
1541 STAMPROFILE StatTrackDeref;
1542 /** Profiling pgmTrackFlushGCPhysPT. */
1543 STAMPROFILE StatTrackFlushGCPhysPT;
1544 /** Profiling pgmTrackFlushGCPhysPTs. */
1545 STAMPROFILE StatTrackFlushGCPhysPTs;
1546 /** Profiling pgmTrackFlushGCPhysPTsSlow. */
1547 STAMPROFILE StatTrackFlushGCPhysPTsSlow;
1548 /** Number of times we've been out of user records. */
1549 STAMCOUNTER StatTrackFreeUpOneUser;
1550# endif
1551# ifdef PGMPOOL_WITH_GCPHYS_TRACKING
1552 /** Profiling deref activity related tracking GC physical pages. */
1553 STAMPROFILE StatTrackDerefGCPhys;
1554 /** Number of linear searches for a HCPhys in the ram ranges. */
1555 STAMCOUNTER StatTrackLinearRamSearches;
1556 /** The number of failing pgmPoolTrackPhysExtAlloc calls. */
1557 STAMCOUNTER StamTrackPhysExtAllocFailures;
1558# endif
1559# ifdef PGMPOOL_WITH_MONITORING
1560 /** Profiling the GC PT access handler. */
1561 STAMPROFILE StatMonitorGC;
1562 /** Times we've failed interpreting the instruction. */
1563 STAMCOUNTER StatMonitorGCEmulateInstr;
1564 /** Profiling the pgmPoolFlushPage calls made from the GC PT access handler. */
1565 STAMPROFILE StatMonitorGCFlushPage;
1566 /** Times we've detected fork(). */
1567 STAMCOUNTER StatMonitorGCFork;
1568 /** Profiling the GC access we've handled (except REP STOSD). */
1569 STAMPROFILE StatMonitorGCHandled;
1570 /** Times we've failed interpreting a patch code instruction. */
1571 STAMCOUNTER StatMonitorGCIntrFailPatch1;
1572 /** Times we've failed interpreting a patch code instruction during flushing. */
1573 STAMCOUNTER StatMonitorGCIntrFailPatch2;
1574 /** The number of times we've seen rep prefixes we can't handle. */
1575 STAMCOUNTER StatMonitorGCRepPrefix;
1576 /** Profiling the REP STOSD cases we've handled. */
1577 STAMPROFILE StatMonitorGCRepStosd;
1578
1579 /** Profiling the HC PT access handler. */
1580 STAMPROFILE StatMonitorHC;
1581 /** Times we've failed interpreting the instruction. */
1582 STAMCOUNTER StatMonitorHCEmulateInstr;
1583 /** Profiling the pgmPoolFlushPage calls made from the HC PT access handler. */
1584 STAMPROFILE StatMonitorHCFlushPage;
1585 /** Times we've detected fork(). */
1586 STAMCOUNTER StatMonitorHCFork;
1587 /** Profiling the HC access we've handled (except REP STOSD). */
1588 STAMPROFILE StatMonitorHCHandled;
1589 /** The number of times we've seen rep prefixes we can't handle. */
1590 STAMCOUNTER StatMonitorHCRepPrefix;
1591 /** Profiling the REP STOSD cases we've handled. */
1592 STAMPROFILE StatMonitorHCRepStosd;
1593 /** The number of times we're called in an async thread an need to flush. */
1594 STAMCOUNTER StatMonitorHCAsync;
1595 /** The high wather mark for cModifiedPages. */
1596 uint16_t cModifiedPagesHigh;
1597 uint16_t Alignment2[3]; /**< Align the next member on a 64-bit boundrary. */
1598# endif
1599# ifdef PGMPOOL_WITH_CACHE
1600 /** The number of cache hits. */
1601 STAMCOUNTER StatCacheHits;
1602 /** The number of cache misses. */
1603 STAMCOUNTER StatCacheMisses;
1604 /** The number of times we've got a conflict of 'kind' in the cache. */
1605 STAMCOUNTER StatCacheKindMismatches;
1606 /** Number of times we've been out of pages. */
1607 STAMCOUNTER StatCacheFreeUpOne;
1608 /** The number of cacheable allocations. */
1609 STAMCOUNTER StatCacheCacheable;
1610 /** The number of uncacheable allocations. */
1611 STAMCOUNTER StatCacheUncacheable;
1612# endif
1613#elif HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32
1614 uint32_t Alignment1; /**< Align the next member on a 64-bit boundrary. */
1615#endif
1616 /** The AVL tree for looking up a page by its HC physical address. */
1617 AVLOHCPHYSTREE HCPhysTree;
1618 uint32_t Alignment3; /**< Align the next member on a 64-bit boundrary. */
1619 /** Array of pages. (cMaxPages in length)
1620 * The Id is the index into thist array.
1621 */
1622 PGMPOOLPAGE aPages[PGMPOOL_IDX_FIRST];
1623} PGMPOOL, *PPGMPOOL, **PPPGMPOOL;
1624
1625
1626/** @def PGMPOOL_PAGE_2_PTR
1627 * Maps a pool page pool into the current context.
1628 *
1629 * @returns VBox status code.
1630 * @param pVM The VM handle.
1631 * @param pPage The pool page.
1632 *
1633 * @remark In HC this uses PGMGCDynMapHCPage(), so it will consume of the
1634 * small page window employeed by that function. Be careful.
1635 * @remark There is no need to assert on the result.
1636 */
1637#ifdef IN_GC
1638# define PGMPOOL_PAGE_2_PTR(pVM, pPage) pgmGCPoolMapPage((pVM), (pPage))
1639#else
1640# define PGMPOOL_PAGE_2_PTR(pVM, pPage) ((pPage)->pvPageHC)
1641#endif
1642
1643
1644/**
1645 * Trees are using self relative offsets as pointers.
1646 * So, all its data, including the root pointer, must be in the heap for HC and GC
1647 * to have the same layout.
1648 */
1649typedef struct PGMTREES
1650{
1651 /** Physical access handlers (AVL range+offsetptr tree). */
1652 AVLROGCPHYSTREE PhysHandlers;
1653 /** Virtual access handlers (AVL range + GC ptr tree). */
1654 AVLROGCPTRTREE VirtHandlers;
1655 /** Virtual access handlers (Phys range AVL range + offsetptr tree). */
1656 AVLROGCPHYSTREE PhysToVirtHandlers;
1657 /** Virtual access handlers for the hypervisor (AVL range + GC ptr tree). */
1658 AVLROGCPTRTREE HyperVirtHandlers;
1659} PGMTREES;
1660/** Pointer to PGM trees. */
1661typedef PGMTREES *PPGMTREES;
1662
1663
1664/** @name Paging mode macros
1665 * @{ */
1666#ifdef IN_GC
1667# define PGM_CTX(a,b) a##GC##b
1668# define PGM_CTX_STR(a,b) a "GC" b
1669# define PGM_CTX_DECL(type) PGMGCDECL(type)
1670#else
1671# ifdef IN_RING3
1672# define PGM_CTX(a,b) a##R3##b
1673# define PGM_CTX_STR(a,b) a "R3" b
1674# define PGM_CTX_DECL(type) DECLCALLBACK(type)
1675# else
1676# define PGM_CTX(a,b) a##R0##b
1677# define PGM_CTX_STR(a,b) a "R0" b
1678# define PGM_CTX_DECL(type) PGMDECL(type)
1679# endif
1680#endif
1681
1682#define PGM_GST_NAME_REAL(name) PGM_CTX(pgm,GstReal##name)
1683#define PGM_GST_NAME_GC_REAL_STR(name) "pgmGCGstReal" #name
1684#define PGM_GST_NAME_R0_REAL_STR(name) "pgmR0GstReal" #name
1685#define PGM_GST_NAME_PROT(name) PGM_CTX(pgm,GstProt##name)
1686#define PGM_GST_NAME_GC_PROT_STR(name) "pgmGCGstProt" #name
1687#define PGM_GST_NAME_R0_PROT_STR(name) "pgmR0GstProt" #name
1688#define PGM_GST_NAME_32BIT(name) PGM_CTX(pgm,Gst32Bit##name)
1689#define PGM_GST_NAME_GC_32BIT_STR(name) "pgmGCGst32Bit" #name
1690#define PGM_GST_NAME_R0_32BIT_STR(name) "pgmR0Gst32Bit" #name
1691#define PGM_GST_NAME_PAE(name) PGM_CTX(pgm,GstPAE##name)
1692#define PGM_GST_NAME_GC_PAE_STR(name) "pgmGCGstPAE" #name
1693#define PGM_GST_NAME_R0_PAE_STR(name) "pgmR0GstPAE" #name
1694#define PGM_GST_NAME_AMD64(name) PGM_CTX(pgm,GstAMD64##name)
1695#define PGM_GST_NAME_GC_AMD64_STR(name) "pgmGCGstAMD64" #name
1696#define PGM_GST_NAME_R0_AMD64_STR(name) "pgmR0GstAMD64" #name
1697#define PGM_GST_PFN(name, pVM) ((pVM)->pgm.s.PGM_CTX(pfn,Gst##name))
1698#define PGM_GST_DECL(type, name) PGM_CTX_DECL(type) PGM_GST_NAME(name)
1699
1700#define PGM_SHW_NAME_32BIT(name) PGM_CTX(pgm,Shw32Bit##name)
1701#define PGM_SHW_NAME_GC_32BIT_STR(name) "pgmGCShw32Bit" #name
1702#define PGM_SHW_NAME_R0_32BIT_STR(name) "pgmR0Shw32Bit" #name
1703#define PGM_SHW_NAME_PAE(name) PGM_CTX(pgm,ShwPAE##name)
1704#define PGM_SHW_NAME_GC_PAE_STR(name) "pgmGCShwPAE" #name
1705#define PGM_SHW_NAME_R0_PAE_STR(name) "pgmR0ShwPAE" #name
1706#define PGM_SHW_NAME_AMD64(name) PGM_CTX(pgm,ShwAMD64##name)
1707#define PGM_SHW_NAME_GC_AMD64_STR(name) "pgmGCShwAMD64" #name
1708#define PGM_SHW_NAME_R0_AMD64_STR(name) "pgmR0ShwAMD64" #name
1709#define PGM_SHW_DECL(type, name) PGM_CTX_DECL(type) PGM_SHW_NAME(name)
1710#define PGM_SHW_PFN(name, pVM) ((pVM)->pgm.s.PGM_CTX(pfn,Shw##name))
1711
1712/* Shw_Gst */
1713#define PGM_BTH_NAME_32BIT_REAL(name) PGM_CTX(pgm,Bth32BitReal##name)
1714#define PGM_BTH_NAME_32BIT_PROT(name) PGM_CTX(pgm,Bth32BitProt##name)
1715#define PGM_BTH_NAME_32BIT_32BIT(name) PGM_CTX(pgm,Bth32Bit32Bit##name)
1716#define PGM_BTH_NAME_PAE_REAL(name) PGM_CTX(pgm,BthPAEReal##name)
1717#define PGM_BTH_NAME_PAE_PROT(name) PGM_CTX(pgm,BthPAEProt##name)
1718#define PGM_BTH_NAME_PAE_32BIT(name) PGM_CTX(pgm,BthPAE32Bit##name)
1719#define PGM_BTH_NAME_PAE_PAE(name) PGM_CTX(pgm,BthPAEPAE##name)
1720#define PGM_BTH_NAME_AMD64_AMD64(name) PGM_CTX(pgm,BthAMD64AMD64##name)
1721#define PGM_BTH_NAME_GC_32BIT_REAL_STR(name) "pgmGCBth32BitReal" #name
1722#define PGM_BTH_NAME_GC_32BIT_PROT_STR(name) "pgmGCBth32BitProt" #name
1723#define PGM_BTH_NAME_GC_32BIT_32BIT_STR(name) "pgmGCBth32Bit32Bit" #name
1724#define PGM_BTH_NAME_GC_PAE_REAL_STR(name) "pgmGCBthPAEReal" #name
1725#define PGM_BTH_NAME_GC_PAE_PROT_STR(name) "pgmGCBthPAEProt" #name
1726#define PGM_BTH_NAME_GC_PAE_32BIT_STR(name) "pgmGCBthPAE32Bit" #name
1727#define PGM_BTH_NAME_GC_PAE_PAE_STR(name) "pgmGCBthPAEPAE" #name
1728#define PGM_BTH_NAME_GC_AMD64_AMD64_STR(name) "pgmGCBthAMD64AMD64" #name
1729#define PGM_BTH_NAME_R0_32BIT_REAL_STR(name) "pgmR0Bth32BitReal" #name
1730#define PGM_BTH_NAME_R0_32BIT_PROT_STR(name) "pgmR0Bth32BitProt" #name
1731#define PGM_BTH_NAME_R0_32BIT_32BIT_STR(name) "pgmR0Bth32Bit32Bit" #name
1732#define PGM_BTH_NAME_R0_PAE_REAL_STR(name) "pgmR0BthPAEReal" #name
1733#define PGM_BTH_NAME_R0_PAE_PROT_STR(name) "pgmR0BthPAEProt" #name
1734#define PGM_BTH_NAME_R0_PAE_32BIT_STR(name) "pgmR0BthPAE32Bit" #name
1735#define PGM_BTH_NAME_R0_PAE_PAE_STR(name) "pgmR0BthPAEPAE" #name
1736#define PGM_BTH_NAME_R0_AMD64_AMD64_STR(name) "pgmR0BthAMD64AMD64" #name
1737#define PGM_BTH_DECL(type, name) PGM_CTX_DECL(type) PGM_BTH_NAME(name)
1738#define PGM_BTH_PFN(name, pVM) ((pVM)->pgm.s.PGM_CTX(pfn,Bth##name))
1739/** @} */
1740
1741/**
1742 * Data for each paging mode.
1743 */
1744typedef struct PGMMODEDATA
1745{
1746 /** The guest mode type. */
1747 uint32_t uGstType;
1748 /** The shadow mode type. */
1749 uint32_t uShwType;
1750
1751 /** @name Function pointers for Shadow paging.
1752 * @{
1753 */
1754 DECLR3CALLBACKMEMBER(int, pfnR3ShwRelocate,(PVM pVM, RTGCUINTPTR offDelta));
1755 DECLR3CALLBACKMEMBER(int, pfnR3ShwExit,(PVM pVM));
1756 DECLR3CALLBACKMEMBER(int, pfnR3ShwGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
1757 DECLR3CALLBACKMEMBER(int, pfnR3ShwModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1758 DECLR3CALLBACKMEMBER(int, pfnR3ShwGetPDEByIndex,(PVM pVM, uint32_t iPD, PX86PDEPAE pPde));
1759 DECLR3CALLBACKMEMBER(int, pfnR3ShwSetPDEByIndex,(PVM pVM, uint32_t iPD, X86PDEPAE Pde));
1760 DECLR3CALLBACKMEMBER(int, pfnR3ShwModifyPDEByIndex,(PVM pVM, uint32_t iPD, uint64_t fFlags, uint64_t fMask));
1761
1762 DECLGCCALLBACKMEMBER(int, pfnGCShwGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
1763 DECLGCCALLBACKMEMBER(int, pfnGCShwModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1764 DECLGCCALLBACKMEMBER(int, pfnGCShwGetPDEByIndex,(PVM pVM, uint32_t iPD, PX86PDEPAE pPde));
1765 DECLGCCALLBACKMEMBER(int, pfnGCShwSetPDEByIndex,(PVM pVM, uint32_t iPD, X86PDEPAE Pde));
1766 DECLGCCALLBACKMEMBER(int, pfnGCShwModifyPDEByIndex,(PVM pVM, uint32_t iPD, uint64_t fFlags, uint64_t fMask));
1767
1768 DECLR0CALLBACKMEMBER(int, pfnR0ShwGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
1769 DECLR0CALLBACKMEMBER(int, pfnR0ShwModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1770 DECLR0CALLBACKMEMBER(int, pfnR0ShwGetPDEByIndex,(PVM pVM, uint32_t iPD, PX86PDEPAE pPde));
1771 DECLR0CALLBACKMEMBER(int, pfnR0ShwSetPDEByIndex,(PVM pVM, uint32_t iPD, X86PDEPAE Pde));
1772 DECLR0CALLBACKMEMBER(int, pfnR0ShwModifyPDEByIndex,(PVM pVM, uint32_t iPD, uint64_t fFlags, uint64_t fMask));
1773 /** @} */
1774
1775 /** @name Function pointers for Guest paging.
1776 * @{
1777 */
1778 DECLR3CALLBACKMEMBER(int, pfnR3GstRelocate,(PVM pVM, RTGCUINTPTR offDelta));
1779 DECLR3CALLBACKMEMBER(int, pfnR3GstExit,(PVM pVM));
1780 DECLR3CALLBACKMEMBER(int, pfnR3GstGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys));
1781 DECLR3CALLBACKMEMBER(int, pfnR3GstModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1782 DECLR3CALLBACKMEMBER(int, pfnR3GstGetPDE,(PVM pVM, RTGCUINTPTR GCPtr, PX86PDEPAE pPde));
1783 DECLR3CALLBACKMEMBER(int, pfnR3GstMonitorCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
1784 DECLR3CALLBACKMEMBER(int, pfnR3GstUnmonitorCR3,(PVM pVM));
1785 DECLR3CALLBACKMEMBER(int, pfnR3GstMapCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
1786 DECLR3CALLBACKMEMBER(int, pfnR3GstUnmapCR3,(PVM pVM));
1787 R3PTRTYPE(PFNPGMR3PHYSHANDLER) pfnR3GstWriteHandlerCR3;
1788 R3PTRTYPE(const char *) pszR3GstWriteHandlerCR3;
1789 R3PTRTYPE(PFNPGMR3PHYSHANDLER) pfnR3GstPAEWriteHandlerCR3;
1790 R3PTRTYPE(const char *) pszR3GstPAEWriteHandlerCR3;
1791
1792 DECLGCCALLBACKMEMBER(int, pfnGCGstGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys));
1793 DECLGCCALLBACKMEMBER(int, pfnGCGstModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1794 DECLGCCALLBACKMEMBER(int, pfnGCGstGetPDE,(PVM pVM, RTGCUINTPTR GCPtr, PX86PDEPAE pPde));
1795 DECLGCCALLBACKMEMBER(int, pfnGCGstMonitorCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
1796 DECLGCCALLBACKMEMBER(int, pfnGCGstUnmonitorCR3,(PVM pVM));
1797 DECLGCCALLBACKMEMBER(int, pfnGCGstMapCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
1798 DECLGCCALLBACKMEMBER(int, pfnGCGstUnmapCR3,(PVM pVM));
1799 GCPTRTYPE(PFNPGMGCPHYSHANDLER) pfnGCGstWriteHandlerCR3;
1800 GCPTRTYPE(PFNPGMGCPHYSHANDLER) pfnGCGstPAEWriteHandlerCR3;
1801
1802 DECLR0CALLBACKMEMBER(int, pfnR0GstGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys));
1803 DECLR0CALLBACKMEMBER(int, pfnR0GstModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1804 DECLR0CALLBACKMEMBER(int, pfnR0GstGetPDE,(PVM pVM, RTGCUINTPTR GCPtr, PX86PDEPAE pPde));
1805 DECLR0CALLBACKMEMBER(int, pfnR0GstMonitorCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
1806 DECLR0CALLBACKMEMBER(int, pfnR0GstUnmonitorCR3,(PVM pVM));
1807 DECLR0CALLBACKMEMBER(int, pfnR0GstMapCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
1808 DECLR0CALLBACKMEMBER(int, pfnR0GstUnmapCR3,(PVM pVM));
1809 R0PTRTYPE(PFNPGMGCPHYSHANDLER) pfnR0GstWriteHandlerCR3;
1810 R0PTRTYPE(PFNPGMGCPHYSHANDLER) pfnR0GstPAEWriteHandlerCR3;
1811 /** @} */
1812
1813 /** @name Function pointers for Both Shadow and Guest paging.
1814 * @{
1815 */
1816 DECLR3CALLBACKMEMBER(int, pfnR3BthRelocate,(PVM pVM, RTGCUINTPTR offDelta));
1817 DECLR3CALLBACKMEMBER(int, pfnR3BthTrap0eHandler,(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault));
1818 DECLR3CALLBACKMEMBER(int, pfnR3BthInvalidatePage,(PVM pVM, RTGCPTR GCPtrPage));
1819 DECLR3CALLBACKMEMBER(int, pfnR3BthSyncCR3,(PVM pVM, uint32_t cr0, uint32_t cr3, uint32_t cr4, bool fGlobal));
1820 DECLR3CALLBACKMEMBER(int, pfnR3BthSyncPage,(PVM pVM, X86PDE PdeSrc, RTGCUINTPTR GCPtrPage, unsigned cPages, unsigned uError));
1821 DECLR3CALLBACKMEMBER(int, pfnR3BthPrefetchPage,(PVM pVM, RTGCUINTPTR GCPtrPage));
1822 DECLR3CALLBACKMEMBER(int, pfnR3BthVerifyAccessSyncPage,(PVM pVM, RTGCUINTPTR GCPtrPage, unsigned fFlags, unsigned uError));
1823#ifdef VBOX_STRICT
1824 DECLR3CALLBACKMEMBER(unsigned, pfnR3BthAssertCR3,(PVM pVM, uint32_t cr3, uint32_t cr4, RTGCUINTPTR GCPtr, RTGCUINTPTR cb));
1825#endif
1826
1827 DECLGCCALLBACKMEMBER(int, pfnGCBthTrap0eHandler,(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault));
1828 DECLGCCALLBACKMEMBER(int, pfnGCBthInvalidatePage,(PVM pVM, RTGCPTR GCPtrPage));
1829 DECLGCCALLBACKMEMBER(int, pfnGCBthSyncCR3,(PVM pVM, uint32_t cr0, uint32_t cr3, uint32_t cr4, bool fGlobal));
1830 DECLGCCALLBACKMEMBER(int, pfnGCBthSyncPage,(PVM pVM, X86PDE PdeSrc, RTGCUINTPTR GCPtrPage, unsigned cPages, unsigned uError));
1831 DECLGCCALLBACKMEMBER(int, pfnGCBthPrefetchPage,(PVM pVM, RTGCUINTPTR GCPtrPage));
1832 DECLGCCALLBACKMEMBER(int, pfnGCBthVerifyAccessSyncPage,(PVM pVM, RTGCUINTPTR GCPtrPage, unsigned fFlags, unsigned uError));
1833#ifdef VBOX_STRICT
1834 DECLGCCALLBACKMEMBER(unsigned, pfnGCBthAssertCR3,(PVM pVM, uint32_t cr3, uint32_t cr4, RTGCUINTPTR GCPtr, RTGCUINTPTR cb));
1835#endif
1836
1837 DECLR0CALLBACKMEMBER(int, pfnR0BthTrap0eHandler,(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault));
1838 DECLR0CALLBACKMEMBER(int, pfnR0BthInvalidatePage,(PVM pVM, RTGCPTR GCPtrPage));
1839 DECLR0CALLBACKMEMBER(int, pfnR0BthSyncCR3,(PVM pVM, uint32_t cr0, uint32_t cr3, uint32_t cr4, bool fGlobal));
1840 DECLR0CALLBACKMEMBER(int, pfnR0BthSyncPage,(PVM pVM, X86PDE PdeSrc, RTGCUINTPTR GCPtrPage, unsigned cPages, unsigned uError));
1841 DECLR0CALLBACKMEMBER(int, pfnR0BthPrefetchPage,(PVM pVM, RTGCUINTPTR GCPtrPage));
1842 DECLR0CALLBACKMEMBER(int, pfnR0BthVerifyAccessSyncPage,(PVM pVM, RTGCUINTPTR GCPtrPage, unsigned fFlags, unsigned uError));
1843#ifdef VBOX_STRICT
1844 DECLR0CALLBACKMEMBER(unsigned, pfnR0BthAssertCR3,(PVM pVM, uint32_t cr3, uint32_t cr4, RTGCUINTPTR GCPtr, RTGCUINTPTR cb));
1845#endif
1846 /** @} */
1847} PGMMODEDATA, *PPGMMODEDATA;
1848
1849
1850
1851/**
1852 * Converts a PGM pointer into a VM pointer.
1853 * @returns Pointer to the VM structure the PGM is part of.
1854 * @param pPGM Pointer to PGM instance data.
1855 */
1856#define PGM2VM(pPGM) ( (PVM)((char*)pPGM - pPGM->offVM) )
1857
1858/**
1859 * PGM Data (part of VM)
1860 */
1861typedef struct PGM
1862{
1863 /** Offset to the VM structure. */
1864 RTINT offVM;
1865
1866 /*
1867 * This will be redefined at least two more times before we're done, I'm sure.
1868 * The current code is only to get on with the coding.
1869 * - 2004-06-10: initial version, bird.
1870 * - 2004-07-02: 1st time, bird.
1871 * - 2004-10-18: 2nd time, bird.
1872 * - 2005-07-xx: 3rd time, bird.
1873 */
1874
1875 /** Pointer to the page table entries for the dynamic page mapping area - GCPtr. */
1876 GCPTRTYPE(PX86PTE) paDynPageMap32BitPTEsGC;
1877 /** Pointer to the page table entries for the dynamic page mapping area - GCPtr. */
1878 GCPTRTYPE(PX86PTEPAE) paDynPageMapPaePTEsGC;
1879
1880 /** The host paging mode. (This is what SUPLib reports.) */
1881 SUPPAGINGMODE enmHostMode;
1882 /** The shadow paging mode. */
1883 PGMMODE enmShadowMode;
1884 /** The guest paging mode. */
1885 PGMMODE enmGuestMode;
1886
1887 /** The current physical address representing in the guest CR3 register. */
1888 RTGCPHYS GCPhysCR3;
1889 /** Pointer to the 5 page CR3 content mapping.
1890 * The first page is always the CR3 (in some form) while the 4 other pages
1891 * are used of the PDs in PAE mode. */
1892 RTGCPTR GCPtrCR3Mapping;
1893#if HC_ARCH_BITS == 64
1894 uint32_t u32Alignment;
1895#endif
1896 /** The physical address of the currently monitored guest CR3 page.
1897 * When this value is NIL_RTGCPHYS no page is being monitored. */
1898 RTGCPHYS GCPhysGstCR3Monitored;
1899
1900 /** @name 32-bit Guest Paging.
1901 * @{ */
1902 /** The guest's page directory, HC pointer. */
1903 R3R0PTRTYPE(PX86PD) pGuestPDHC;
1904 /** The guest's page directory, static GC mapping. */
1905 GCPTRTYPE(PX86PD) pGuestPDGC;
1906 /** @} */
1907
1908 /** @name PAE Guest Paging.
1909 * @{ */
1910 /** The guest's page directory pointer table, static GC mapping. */
1911 GCPTRTYPE(PX86PDPT) pGstPaePDPTGC;
1912 /** The guest's page directory pointer table, HC pointer. */
1913 R3R0PTRTYPE(PX86PDPT) pGstPaePDPTHC;
1914 /** The guest's page directories, HC pointers.
1915 * These are individual pointers and don't have to be adjecent.
1916 * These don't have to be up-to-date - use pgmGstGetPaePD() to access them. */
1917 R3R0PTRTYPE(PX86PDPAE) apGstPaePDsHC[4];
1918 /** The guest's page directories, static GC mapping.
1919 * Unlike the HC array the first entry can be accessed as a 2048 entry PD.
1920 * These don't have to be up-to-date - use pgmGstGetPaePD() to access them. */
1921 GCPTRTYPE(PX86PDPAE) apGstPaePDsGC[4];
1922 /** The physical addresses of the guest page directories (PAE) pointed to by apGstPagePDsHC/GC. */
1923 RTGCPHYS aGCPhysGstPaePDs[4];
1924 /** The physical addresses of the monitored guest page directories (PAE). */
1925 RTGCPHYS aGCPhysGstPaePDsMonitored[4];
1926 /** @} */
1927
1928
1929 /** @name 32-bit Shadow Paging
1930 * @{ */
1931 /** The 32-Bit PD - HC Ptr. */
1932 R3R0PTRTYPE(PX86PD) pHC32BitPD;
1933 /** The 32-Bit PD - GC Ptr. */
1934 GCPTRTYPE(PX86PD) pGC32BitPD;
1935#if HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32
1936 uint32_t u32Padding1; /**< alignment padding. */
1937#endif
1938 /** The Physical Address (HC) of the 32-Bit PD. */
1939 RTHCPHYS HCPhys32BitPD;
1940 /** @} */
1941
1942 /** @name PAE Shadow Paging
1943 * @{ */
1944 /** The four PDs for the low 4GB - HC Ptr.
1945 * Even though these are 4 pointers, what they point at is a single table.
1946 * Thus, it's possible to walk the 2048 entries starting where apHCPaePDs[0] points. */
1947 R3R0PTRTYPE(PX86PDPAE) apHCPaePDs[4];
1948 /** The four PDs for the low 4GB - GC Ptr.
1949 * Same kind of mapping as apHCPaePDs. */
1950 GCPTRTYPE(PX86PDPAE) apGCPaePDs[4];
1951 /** The Physical Address (HC) of the four PDs for the low 4GB.
1952 * These are *NOT* 4 contiguous pages. */
1953 RTHCPHYS aHCPhysPaePDs[4];
1954 /** The PAE PDP - HC Ptr. */
1955 R3R0PTRTYPE(PX86PDPT) pHCPaePDPT;
1956 /** The Physical Address (HC) of the PAE PDPT. */
1957 RTHCPHYS HCPhysPaePDPT;
1958 /** The PAE PDPT - GC Ptr. */
1959 GCPTRTYPE(PX86PDPT) pGCPaePDPT;
1960 /** @} */
1961
1962 /** @name AMD64 Shadow Paging
1963 * Extends PAE Paging.
1964 * @{ */
1965 /** The Page Map Level 4 table - HC Ptr. */
1966 GCPTRTYPE(PX86PML4) pGCPaePML4;
1967 /** The Page Map Level 4 table - GC Ptr. */
1968 R3R0PTRTYPE(PX86PML4) pHCPaePML4;
1969 /** The Physical Address (HC) of the Page Map Level 4 table. */
1970 RTHCPHYS HCPhysPaePML4;
1971 /** @}*/
1972
1973 /** @name Function pointers for Shadow paging.
1974 * @{
1975 */
1976 DECLR3CALLBACKMEMBER(int, pfnR3ShwRelocate,(PVM pVM, RTGCUINTPTR offDelta));
1977 DECLR3CALLBACKMEMBER(int, pfnR3ShwExit,(PVM pVM));
1978 DECLR3CALLBACKMEMBER(int, pfnR3ShwGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
1979 DECLR3CALLBACKMEMBER(int, pfnR3ShwModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1980 DECLR3CALLBACKMEMBER(int, pfnR3ShwGetPDEByIndex,(PVM pVM, uint32_t iPD, PX86PDEPAE pPde));
1981 DECLR3CALLBACKMEMBER(int, pfnR3ShwSetPDEByIndex,(PVM pVM, uint32_t iPD, X86PDEPAE Pde));
1982 DECLR3CALLBACKMEMBER(int, pfnR3ShwModifyPDEByIndex,(PVM pVM, uint32_t iPD, uint64_t fFlags, uint64_t fMask));
1983
1984 DECLGCCALLBACKMEMBER(int, pfnGCShwGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
1985 DECLGCCALLBACKMEMBER(int, pfnGCShwModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1986 DECLGCCALLBACKMEMBER(int, pfnGCShwGetPDEByIndex,(PVM pVM, uint32_t iPD, PX86PDEPAE pPde));
1987 DECLGCCALLBACKMEMBER(int, pfnGCShwSetPDEByIndex,(PVM pVM, uint32_t iPD, X86PDEPAE Pde));
1988 DECLGCCALLBACKMEMBER(int, pfnGCShwModifyPDEByIndex,(PVM pVM, uint32_t iPD, uint64_t fFlags, uint64_t fMask));
1989#if GC_ARCH_BITS == 32 && HC_ARCH_BITS == 64
1990 RTGCPTR alignment0; /**< structure size alignment. */
1991#endif
1992
1993 DECLR0CALLBACKMEMBER(int, pfnR0ShwGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
1994 DECLR0CALLBACKMEMBER(int, pfnR0ShwModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1995 DECLR0CALLBACKMEMBER(int, pfnR0ShwGetPDEByIndex,(PVM pVM, uint32_t iPD, PX86PDEPAE pPde));
1996 DECLR0CALLBACKMEMBER(int, pfnR0ShwSetPDEByIndex,(PVM pVM, uint32_t iPD, X86PDEPAE Pde));
1997 DECLR0CALLBACKMEMBER(int, pfnR0ShwModifyPDEByIndex,(PVM pVM, uint32_t iPD, uint64_t fFlags, uint64_t fMask));
1998
1999 /** @} */
2000
2001 /** @name Function pointers for Guest paging.
2002 * @{
2003 */
2004 DECLR3CALLBACKMEMBER(int, pfnR3GstRelocate,(PVM pVM, RTGCUINTPTR offDelta));
2005 DECLR3CALLBACKMEMBER(int, pfnR3GstExit,(PVM pVM));
2006 DECLR3CALLBACKMEMBER(int, pfnR3GstGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys));
2007 DECLR3CALLBACKMEMBER(int, pfnR3GstModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
2008 DECLR3CALLBACKMEMBER(int, pfnR3GstGetPDE,(PVM pVM, RTGCUINTPTR GCPtr, PX86PDEPAE pPde));
2009 DECLR3CALLBACKMEMBER(int, pfnR3GstMonitorCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
2010 DECLR3CALLBACKMEMBER(int, pfnR3GstUnmonitorCR3,(PVM pVM));
2011 DECLR3CALLBACKMEMBER(int, pfnR3GstMapCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
2012 DECLR3CALLBACKMEMBER(int, pfnR3GstUnmapCR3,(PVM pVM));
2013 R3PTRTYPE(PFNPGMR3PHYSHANDLER) pfnR3GstWriteHandlerCR3;
2014 R3PTRTYPE(const char *) pszR3GstWriteHandlerCR3;
2015 R3PTRTYPE(PFNPGMR3PHYSHANDLER) pfnR3GstPAEWriteHandlerCR3;
2016 R3PTRTYPE(const char *) pszR3GstPAEWriteHandlerCR3;
2017
2018 DECLGCCALLBACKMEMBER(int, pfnGCGstGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys));
2019 DECLGCCALLBACKMEMBER(int, pfnGCGstModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
2020 DECLGCCALLBACKMEMBER(int, pfnGCGstGetPDE,(PVM pVM, RTGCUINTPTR GCPtr, PX86PDEPAE pPde));
2021 DECLGCCALLBACKMEMBER(int, pfnGCGstMonitorCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
2022 DECLGCCALLBACKMEMBER(int, pfnGCGstUnmonitorCR3,(PVM pVM));
2023 DECLGCCALLBACKMEMBER(int, pfnGCGstMapCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
2024 DECLGCCALLBACKMEMBER(int, pfnGCGstUnmapCR3,(PVM pVM));
2025 GCPTRTYPE(PFNPGMGCPHYSHANDLER) pfnGCGstWriteHandlerCR3;
2026 GCPTRTYPE(PFNPGMGCPHYSHANDLER) pfnGCGstPAEWriteHandlerCR3;
2027#if GC_ARCH_BITS == 32 && HC_ARCH_BITS == 64
2028 RTGCPTR alignment3; /**< structure size alignment. */
2029#endif
2030
2031 DECLR0CALLBACKMEMBER(int, pfnR0GstGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys));
2032 DECLR0CALLBACKMEMBER(int, pfnR0GstModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
2033 DECLR0CALLBACKMEMBER(int, pfnR0GstGetPDE,(PVM pVM, RTGCUINTPTR GCPtr, PX86PDEPAE pPde));
2034 DECLR0CALLBACKMEMBER(int, pfnR0GstMonitorCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
2035 DECLR0CALLBACKMEMBER(int, pfnR0GstUnmonitorCR3,(PVM pVM));
2036 DECLR0CALLBACKMEMBER(int, pfnR0GstMapCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
2037 DECLR0CALLBACKMEMBER(int, pfnR0GstUnmapCR3,(PVM pVM));
2038 R0PTRTYPE(PFNPGMGCPHYSHANDLER) pfnR0GstWriteHandlerCR3;
2039 R0PTRTYPE(PFNPGMGCPHYSHANDLER) pfnR0GstPAEWriteHandlerCR3;
2040 /** @} */
2041
2042 /** @name Function pointers for Both Shadow and Guest paging.
2043 * @{
2044 */
2045 DECLR3CALLBACKMEMBER(int, pfnR3BthRelocate,(PVM pVM, RTGCUINTPTR offDelta));
2046 DECLR3CALLBACKMEMBER(int, pfnR3BthTrap0eHandler,(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault));
2047 DECLR3CALLBACKMEMBER(int, pfnR3BthInvalidatePage,(PVM pVM, RTGCPTR GCPtrPage));
2048 DECLR3CALLBACKMEMBER(int, pfnR3BthSyncCR3,(PVM pVM, uint32_t cr0, uint32_t cr3, uint32_t cr4, bool fGlobal));
2049 DECLR3CALLBACKMEMBER(int, pfnR3BthSyncPage,(PVM pVM, X86PDE PdeSrc, RTGCUINTPTR GCPtrPage, unsigned cPages, unsigned uError));
2050 DECLR3CALLBACKMEMBER(int, pfnR3BthPrefetchPage,(PVM pVM, RTGCUINTPTR GCPtrPage));
2051 DECLR3CALLBACKMEMBER(int, pfnR3BthVerifyAccessSyncPage,(PVM pVM, RTGCUINTPTR GCPtrPage, unsigned fFlags, unsigned uError));
2052 DECLR3CALLBACKMEMBER(unsigned, pfnR3BthAssertCR3,(PVM pVM, uint32_t cr3, uint32_t cr4, RTGCUINTPTR GCPtr, RTGCUINTPTR cb));
2053
2054 DECLR0CALLBACKMEMBER(int, pfnR0BthTrap0eHandler,(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault));
2055 DECLR0CALLBACKMEMBER(int, pfnR0BthInvalidatePage,(PVM pVM, RTGCPTR GCPtrPage));
2056 DECLR0CALLBACKMEMBER(int, pfnR0BthSyncCR3,(PVM pVM, uint32_t cr0, uint32_t cr3, uint32_t cr4, bool fGlobal));
2057 DECLR0CALLBACKMEMBER(int, pfnR0BthSyncPage,(PVM pVM, X86PDE PdeSrc, RTGCUINTPTR GCPtrPage, unsigned cPages, unsigned uError));
2058 DECLR0CALLBACKMEMBER(int, pfnR0BthPrefetchPage,(PVM pVM, RTGCUINTPTR GCPtrPage));
2059 DECLR0CALLBACKMEMBER(int, pfnR0BthVerifyAccessSyncPage,(PVM pVM, RTGCUINTPTR GCPtrPage, unsigned fFlags, unsigned uError));
2060 DECLR0CALLBACKMEMBER(unsigned, pfnR0BthAssertCR3,(PVM pVM, uint32_t cr3, uint32_t cr4, RTGCUINTPTR GCPtr, RTGCUINTPTR cb));
2061
2062 DECLGCCALLBACKMEMBER(int, pfnGCBthTrap0eHandler,(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault));
2063 DECLGCCALLBACKMEMBER(int, pfnGCBthInvalidatePage,(PVM pVM, RTGCPTR GCPtrPage));
2064 DECLGCCALLBACKMEMBER(int, pfnGCBthSyncCR3,(PVM pVM, uint32_t cr0, uint32_t cr3, uint32_t cr4, bool fGlobal));
2065 DECLGCCALLBACKMEMBER(int, pfnGCBthSyncPage,(PVM pVM, X86PDE PdeSrc, RTGCUINTPTR GCPtrPage, unsigned cPages, unsigned uError));
2066 DECLGCCALLBACKMEMBER(int, pfnGCBthPrefetchPage,(PVM pVM, RTGCUINTPTR GCPtrPage));
2067 DECLGCCALLBACKMEMBER(int, pfnGCBthVerifyAccessSyncPage,(PVM pVM, RTGCUINTPTR GCPtrPage, unsigned fFlags, unsigned uError));
2068 DECLGCCALLBACKMEMBER(unsigned, pfnGCBthAssertCR3,(PVM pVM, uint32_t cr3, uint32_t cr4, RTGCUINTPTR GCPtr, RTGCUINTPTR cb));
2069#if GC_ARCH_BITS == 32 && HC_ARCH_BITS == 64
2070 RTGCPTR alignment2; /**< structure size alignment. */
2071#endif
2072 /** @} */
2073
2074 /** Pointer to SHW+GST mode data (function pointers).
2075 * The index into this table is made up from */
2076 R3PTRTYPE(PPGMMODEDATA) paModeData;
2077
2078 /** Pointer to the list of RAM ranges (Phys GC -> Phys HC conversion) - for R3.
2079 * This is sorted by physical address and contains no overlapping ranges. */
2080 R3PTRTYPE(PPGMRAMRANGE) pRamRangesR3;
2081 /** R0 pointer corresponding to PGM::pRamRangesR3. */
2082 R0PTRTYPE(PPGMRAMRANGE) pRamRangesR0;
2083 /** GC pointer corresponding to PGM::pRamRangesR3. */
2084 GCPTRTYPE(PPGMRAMRANGE) pRamRangesGC;
2085 /** The configured RAM size. */
2086 RTUINT cbRamSize;
2087
2088 /** Pointer to the list of ROM ranges - for R3.
2089 * This is sorted by physical address and contains no overlapping ranges. */
2090 R3PTRTYPE(PPGMROMRANGE) pRomRangesR3;
2091 /** R0 pointer corresponding to PGM::pRomRangesR3. */
2092 R0PTRTYPE(PPGMRAMRANGE) pRomRangesR0;
2093 /** GC pointer corresponding to PGM::pRomRangesR3. */
2094 GCPTRTYPE(PPGMRAMRANGE) pRomRangesGC;
2095 /** Alignment padding. */
2096 RTGCPTR GCPtrPadding2;
2097
2098 /** Pointer to the list of MMIO2 ranges - for R3.
2099 * Registration order. */
2100 R3PTRTYPE(PPGMMMIO2RANGE) pMmio2RangesR3;
2101
2102 /** PGM offset based trees - HC Ptr. */
2103 R3R0PTRTYPE(PPGMTREES) pTreesHC;
2104 /** PGM offset based trees - GC Ptr. */
2105 GCPTRTYPE(PPGMTREES) pTreesGC;
2106
2107 /** Linked list of GC mappings - for GC.
2108 * The list is sorted ascending on address.
2109 */
2110 GCPTRTYPE(PPGMMAPPING) pMappingsGC;
2111 /** Linked list of GC mappings - for HC.
2112 * The list is sorted ascending on address.
2113 */
2114 R3PTRTYPE(PPGMMAPPING) pMappingsR3;
2115 /** Linked list of GC mappings - for R0.
2116 * The list is sorted ascending on address.
2117 */
2118 R0PTRTYPE(PPGMMAPPING) pMappingsR0;
2119
2120 /** If set no conflict checks are required. (boolean) */
2121 bool fMappingsFixed;
2122 /** If set, then no mappings are put into the shadow page table. (boolean) */
2123 bool fDisableMappings;
2124 /** Size of fixed mapping */
2125 uint32_t cbMappingFixed;
2126 /** Base address (GC) of fixed mapping */
2127 RTGCPTR GCPtrMappingFixed;
2128#if HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32
2129 uint32_t u32Padding0; /**< alignment padding. */
2130#endif
2131
2132
2133 /** @name Intermediate Context
2134 * @{ */
2135 /** Pointer to the intermediate page directory - Normal. */
2136 R3PTRTYPE(PX86PD) pInterPD;
2137 /** Pointer to the intermedate page tables - Normal.
2138 * There are two page tables, one for the identity mapping and one for
2139 * the host context mapping (of the core code). */
2140 R3PTRTYPE(PX86PT) apInterPTs[2];
2141 /** Pointer to the intermedate page tables - PAE. */
2142 R3PTRTYPE(PX86PTPAE) apInterPaePTs[2];
2143 /** Pointer to the intermedate page directory - PAE. */
2144 R3PTRTYPE(PX86PDPAE) apInterPaePDs[4];
2145 /** Pointer to the intermedate page directory - PAE. */
2146 R3PTRTYPE(PX86PDPT) pInterPaePDPT;
2147 /** Pointer to the intermedate page-map level 4 - AMD64. */
2148 R3PTRTYPE(PX86PML4) pInterPaePML4;
2149 /** Pointer to the intermedate page directory - AMD64. */
2150 R3PTRTYPE(PX86PDPT) pInterPaePDPT64;
2151 /** The Physical Address (HC) of the intermediate Page Directory - Normal. */
2152 RTHCPHYS HCPhysInterPD;
2153 /** The Physical Address (HC) of the intermediate Page Directory Pointer Table - PAE. */
2154 RTHCPHYS HCPhysInterPaePDPT;
2155 /** The Physical Address (HC) of the intermediate Page Map Level 4 table - AMD64. */
2156 RTHCPHYS HCPhysInterPaePML4;
2157 /** @} */
2158
2159 /** Base address of the dynamic page mapping area.
2160 * The array is MM_HYPER_DYNAMIC_SIZE bytes big.
2161 */
2162 GCPTRTYPE(uint8_t *) pbDynPageMapBaseGC;
2163 /** The index of the last entry used in the dynamic page mapping area. */
2164 RTUINT iDynPageMapLast;
2165 /** Cache containing the last entries in the dynamic page mapping area.
2166 * The cache size is covering half of the mapping area. */
2167 RTHCPHYS aHCPhysDynPageMapCache[MM_HYPER_DYNAMIC_SIZE >> (PAGE_SHIFT + 1)];
2168
2169 /** A20 gate mask.
2170 * Our current approach to A20 emulation is to let REM do it and don't bother
2171 * anywhere else. The interesting Guests will be operating with it enabled anyway.
2172 * But whould need arrise, we'll subject physical addresses to this mask. */
2173 RTGCPHYS GCPhysA20Mask;
2174 /** A20 gate state - boolean! */
2175 RTUINT fA20Enabled;
2176
2177 /** What needs syncing (PGM_SYNC_*).
2178 * This is used to queue operations for PGMSyncCR3, PGMInvalidatePage,
2179 * PGMFlushTLB, and PGMR3Load. */
2180 RTUINT fSyncFlags;
2181
2182 /** PGM critical section.
2183 * This protects the physical & virtual access handlers, ram ranges,
2184 * and the page flag updating (some of it anyway).
2185 */
2186 PDMCRITSECT CritSect;
2187
2188 /** Shadow Page Pool - HC Ptr. */
2189 R3R0PTRTYPE(PPGMPOOL) pPoolHC;
2190 /** Shadow Page Pool - GC Ptr. */
2191 GCPTRTYPE(PPGMPOOL) pPoolGC;
2192
2193 /** We're not in a state which permits writes to guest memory.
2194 * (Only used in strict builds.) */
2195 bool fNoMorePhysWrites;
2196
2197 /** Flush the cache on the next access. */
2198 bool fPhysCacheFlushPending;
2199/** @todo r=bird: Fix member names!*/
2200 /** PGMPhysRead cache */
2201 PGMPHYSCACHE pgmphysreadcache;
2202 /** PGMPhysWrite cache */
2203 PGMPHYSCACHE pgmphyswritecache;
2204
2205 /**
2206 * Data associated with managing the ring-3 mappings of the allocation chunks.
2207 */
2208 struct
2209 {
2210 /** The chunk tree, ordered by chunk id. */
2211 R3R0PTRTYPE(PAVLU32NODECORE) pTree;
2212 /** The chunk mapping TLB. */
2213 PGMCHUNKR3MAPTLB Tlb;
2214 /** The number of mapped chunks. */
2215 uint32_t c;
2216 /** The maximum number of mapped chunks.
2217 * @cfgm PGM/MaxRing3Chunks */
2218 uint32_t cMax;
2219 /** The chunk age tree, ordered by ageing sequence number. */
2220 R3PTRTYPE(PAVLLU32NODECORE) pAgeTree;
2221 /** The current time. */
2222 uint32_t iNow;
2223 /** Number of pgmR3PhysChunkFindUnmapCandidate calls left to the next ageing. */
2224 uint32_t AgeingCountdown;
2225 } ChunkR3Map;
2226
2227 /**
2228 * The page mapping TLB for ring-3 and (for the time being) ring-0.
2229 */
2230 PGMPAGER3MAPTLB PhysTlbHC;
2231
2232 /** @name The zero page.
2233 * @{ */
2234 /** The host physical address of the zero page. */
2235 RTHCPHYS HCPhysZeroPg;
2236 /** The ring-3 mapping of the zero page. */
2237 RTR3PTR pvZeroPgR3;
2238 /** The ring-0 mapping of the zero page. */
2239 RTR0PTR pvZeroPgR0;
2240 /** The GC mapping of the zero page. */
2241 RTGCPTR pvZeroPgGC;
2242#if GC_ARCH_BITS != 32
2243 uint32_t u32ZeroAlignment; /**< Alignment padding. */
2244#endif
2245 /** @}*/
2246
2247 /** The number of handy pages. */
2248 uint32_t cHandyPages;
2249 /**
2250 * Array of handy pages.
2251 *
2252 * This array is used in a two way communication between pgmPhysAllocPage
2253 * and GMMR0AllocateHandyPages, with PGMR3PhysAllocateHandyPages serving as
2254 * an intermediary.
2255 *
2256 * The size of this array is important, see pgmPhysEnsureHandyPage for details.
2257 * (The current size of 32 pages, means 128 KB of handy memory.)
2258 */
2259 GMMPAGEDESC aHandyPages[32];
2260
2261 /** @name Release Statistics
2262 * @{ */
2263 uint32_t cAllPages; /**< The total number of pages. (Should be Private + Shared + Zero.) */
2264 uint32_t cPrivatePages; /**< The number of private pages. */
2265 uint32_t cSharedPages; /**< The number of shared pages. */
2266 uint32_t cZeroPages; /**< The number of zero backed pages. */
2267 /** The number of times the guest has switched mode since last reset or statistics reset. */
2268 STAMCOUNTER cGuestModeChanges;
2269 /** @} */
2270
2271#ifdef VBOX_WITH_STATISTICS
2272 /** GC: Which statistic this \#PF should be attributed to. */
2273 GCPTRTYPE(PSTAMPROFILE) pStatTrap0eAttributionGC;
2274 RTGCPTR padding0;
2275 /** HC: Which statistic this \#PF should be attributed to. */
2276 R3R0PTRTYPE(PSTAMPROFILE) pStatTrap0eAttributionHC;
2277 RTHCPTR padding1;
2278 STAMPROFILE StatGCTrap0e; /**< GC: PGMGCTrap0eHandler() profiling. */
2279 STAMPROFILE StatTrap0eCSAM; /**< Profiling of the Trap0eHandler body when the cause is CSAM. */
2280 STAMPROFILE StatTrap0eDirtyAndAccessedBits; /**< Profiling of the Trap0eHandler body when the cause is dirty and/or accessed bit emulation. */
2281 STAMPROFILE StatTrap0eGuestTrap; /**< Profiling of the Trap0eHandler body when the cause is a guest trap. */
2282 STAMPROFILE StatTrap0eHndPhys; /**< Profiling of the Trap0eHandler body when the cause is a physical handler. */
2283 STAMPROFILE StatTrap0eHndVirt; /**< Profiling of the Trap0eHandler body when the cause is a virtual handler. */
2284 STAMPROFILE StatTrap0eHndUnhandled; /**< Profiling of the Trap0eHandler body when the cause is access outside the monitored areas of a monitored page. */
2285 STAMPROFILE StatTrap0eMisc; /**< Profiling of the Trap0eHandler body when the cause is not known. */
2286 STAMPROFILE StatTrap0eOutOfSync; /**< Profiling of the Trap0eHandler body when the cause is an out-of-sync page. */
2287 STAMPROFILE StatTrap0eOutOfSyncHndPhys; /**< Profiling of the Trap0eHandler body when the cause is an out-of-sync physical handler page. */
2288 STAMPROFILE StatTrap0eOutOfSyncHndVirt; /**< Profiling of the Trap0eHandler body when the cause is an out-of-sync virtual handler page. */
2289 STAMPROFILE StatTrap0eOutOfSyncObsHnd; /**< Profiling of the Trap0eHandler body when the cause is an obsolete handler page. */
2290 STAMPROFILE StatTrap0eSyncPT; /**< Profiling of the Trap0eHandler body when the cause is lazy syncing of a PT. */
2291
2292 STAMCOUNTER StatTrap0eMapHandler; /**< Number of traps due to access handlers in mappings. */
2293 STAMCOUNTER StatGCTrap0eConflicts; /**< GC: The number of times \#PF was caused by an undetected conflict. */
2294
2295 STAMCOUNTER StatGCTrap0eUSNotPresentRead;
2296 STAMCOUNTER StatGCTrap0eUSNotPresentWrite;
2297 STAMCOUNTER StatGCTrap0eUSWrite;
2298 STAMCOUNTER StatGCTrap0eUSReserved;
2299 STAMCOUNTER StatGCTrap0eUSNXE;
2300 STAMCOUNTER StatGCTrap0eUSRead;
2301
2302 STAMCOUNTER StatGCTrap0eSVNotPresentRead;
2303 STAMCOUNTER StatGCTrap0eSVNotPresentWrite;
2304 STAMCOUNTER StatGCTrap0eSVWrite;
2305 STAMCOUNTER StatGCTrap0eSVReserved;
2306 STAMCOUNTER StatGCTrap0eSNXE;
2307
2308 STAMCOUNTER StatTrap0eWPEmulGC;
2309 STAMCOUNTER StatTrap0eWPEmulR3;
2310
2311 STAMCOUNTER StatGCTrap0eUnhandled;
2312 STAMCOUNTER StatGCTrap0eMap;
2313
2314 /** GC: PGMSyncPT() profiling. */
2315 STAMPROFILE StatGCSyncPT;
2316 /** GC: The number of times PGMSyncPT() needed to allocate page tables. */
2317 STAMCOUNTER StatGCSyncPTAlloc;
2318 /** GC: The number of times PGMSyncPT() detected conflicts. */
2319 STAMCOUNTER StatGCSyncPTConflict;
2320 /** GC: The number of times PGMSyncPT() failed. */
2321 STAMCOUNTER StatGCSyncPTFailed;
2322 /** GC: PGMGCInvalidatePage() profiling. */
2323 STAMPROFILE StatGCInvalidatePage;
2324 /** GC: The number of times PGMGCInvalidatePage() was called for a 4KB page. */
2325 STAMCOUNTER StatGCInvalidatePage4KBPages;
2326 /** GC: The number of times PGMGCInvalidatePage() was called for a 4MB page. */
2327 STAMCOUNTER StatGCInvalidatePage4MBPages;
2328 /** GC: The number of times PGMGCInvalidatePage() skipped a 4MB page. */
2329 STAMCOUNTER StatGCInvalidatePage4MBPagesSkip;
2330 /** GC: The number of times PGMGCInvalidatePage() was called for a not accessed page directory. */
2331 STAMCOUNTER StatGCInvalidatePagePDNAs;
2332 /** GC: The number of times PGMGCInvalidatePage() was called for a not present page directory. */
2333 STAMCOUNTER StatGCInvalidatePagePDNPs;
2334 /** GC: The number of times PGMGCInvalidatePage() was called for a page directory containing mappings (no conflict). */
2335 STAMCOUNTER StatGCInvalidatePagePDMappings;
2336 /** GC: The number of times PGMGCInvalidatePage() was called for an out of sync page directory. */
2337 STAMCOUNTER StatGCInvalidatePagePDOutOfSync;
2338 /** HC: The number of times PGMGCInvalidatePage() was skipped due to not present shw or pending pending SyncCR3. */
2339 STAMCOUNTER StatGCInvalidatePageSkipped;
2340 /** GC: The number of times user page is out of sync was detected in GC. */
2341 STAMCOUNTER StatGCPageOutOfSyncUser;
2342 /** GC: The number of times supervisor page is out of sync was detected in GC. */
2343 STAMCOUNTER StatGCPageOutOfSyncSupervisor;
2344 /** GC: The number of dynamic page mapping cache hits */
2345 STAMCOUNTER StatDynMapCacheMisses;
2346 /** GC: The number of dynamic page mapping cache misses */
2347 STAMCOUNTER StatDynMapCacheHits;
2348 /** GC: The number of times pgmGCGuestPDWriteHandler() was successfully called. */
2349 STAMCOUNTER StatGCGuestCR3WriteHandled;
2350 /** GC: The number of times pgmGCGuestPDWriteHandler() was called and we had to fall back to the recompiler. */
2351 STAMCOUNTER StatGCGuestCR3WriteUnhandled;
2352 /** GC: The number of times pgmGCGuestPDWriteHandler() was called and a conflict was detected. */
2353 STAMCOUNTER StatGCGuestCR3WriteConflict;
2354 /** GC: Number of out-of-sync handled pages. */
2355 STAMCOUNTER StatHandlersOutOfSync;
2356 /** GC: Number of traps due to physical access handlers. */
2357 STAMCOUNTER StatHandlersPhysical;
2358 /** GC: Number of traps due to virtual access handlers. */
2359 STAMCOUNTER StatHandlersVirtual;
2360 /** GC: Number of traps due to virtual access handlers found by physical address. */
2361 STAMCOUNTER StatHandlersVirtualByPhys;
2362 /** GC: Number of traps due to virtual access handlers found by virtual address (without proper physical flags). */
2363 STAMCOUNTER StatHandlersVirtualUnmarked;
2364 /** GC: Number of traps due to access outside range of monitored page(s). */
2365 STAMCOUNTER StatHandlersUnhandled;
2366
2367 /** GC: The number of times pgmGCGuestROMWriteHandler() was successfully called. */
2368 STAMCOUNTER StatGCGuestROMWriteHandled;
2369 /** GC: The number of times pgmGCGuestROMWriteHandler() was called and we had to fall back to the recompiler */
2370 STAMCOUNTER StatGCGuestROMWriteUnhandled;
2371
2372 /** HC: PGMR3InvalidatePage() profiling. */
2373 STAMPROFILE StatHCInvalidatePage;
2374 /** HC: The number of times PGMR3InvalidatePage() was called for a 4KB page. */
2375 STAMCOUNTER StatHCInvalidatePage4KBPages;
2376 /** HC: The number of times PGMR3InvalidatePage() was called for a 4MB page. */
2377 STAMCOUNTER StatHCInvalidatePage4MBPages;
2378 /** HC: The number of times PGMR3InvalidatePage() skipped a 4MB page. */
2379 STAMCOUNTER StatHCInvalidatePage4MBPagesSkip;
2380 /** HC: The number of times PGMR3InvalidatePage() was called for a not accessed page directory. */
2381 STAMCOUNTER StatHCInvalidatePagePDNAs;
2382 /** HC: The number of times PGMR3InvalidatePage() was called for a not present page directory. */
2383 STAMCOUNTER StatHCInvalidatePagePDNPs;
2384 /** HC: The number of times PGMR3InvalidatePage() was called for a page directory containing mappings (no conflict). */
2385 STAMCOUNTER StatHCInvalidatePagePDMappings;
2386 /** HC: The number of times PGMGCInvalidatePage() was called for an out of sync page directory. */
2387 STAMCOUNTER StatHCInvalidatePagePDOutOfSync;
2388 /** HC: The number of times PGMR3InvalidatePage() was skipped due to not present shw or pending pending SyncCR3. */
2389 STAMCOUNTER StatHCInvalidatePageSkipped;
2390 /** HC: PGMR3SyncPT() profiling. */
2391 STAMPROFILE StatHCSyncPT;
2392 /** HC: pgmr3SyncPTResolveConflict() profiling (includes the entire relocation). */
2393 STAMPROFILE StatHCResolveConflict;
2394 /** HC: Number of times PGMR3CheckMappingConflicts() detected a conflict. */
2395 STAMCOUNTER StatHCDetectedConflicts;
2396 /** HC: The total number of times pgmHCGuestPDWriteHandler() was called. */
2397 STAMCOUNTER StatHCGuestPDWrite;
2398 /** HC: The number of times pgmHCGuestPDWriteHandler() detected a conflict */
2399 STAMCOUNTER StatHCGuestPDWriteConflict;
2400
2401 /** HC: The number of pages marked not present for accessed bit emulation. */
2402 STAMCOUNTER StatHCAccessedPage;
2403 /** HC: The number of pages marked read-only for dirty bit tracking. */
2404 STAMCOUNTER StatHCDirtyPage;
2405 /** HC: The number of pages marked read-only for dirty bit tracking. */
2406 STAMCOUNTER StatHCDirtyPageBig;
2407 /** HC: The number of traps generated for dirty bit tracking. */
2408 STAMCOUNTER StatHCDirtyPageTrap;
2409 /** HC: The number of pages already dirty or readonly. */
2410 STAMCOUNTER StatHCDirtyPageSkipped;
2411
2412 /** GC: The number of pages marked not present for accessed bit emulation. */
2413 STAMCOUNTER StatGCAccessedPage;
2414 /** GC: The number of pages marked read-only for dirty bit tracking. */
2415 STAMCOUNTER StatGCDirtyPage;
2416 /** GC: The number of pages marked read-only for dirty bit tracking. */
2417 STAMCOUNTER StatGCDirtyPageBig;
2418 /** GC: The number of traps generated for dirty bit tracking. */
2419 STAMCOUNTER StatGCDirtyPageTrap;
2420 /** GC: The number of pages already dirty or readonly. */
2421 STAMCOUNTER StatGCDirtyPageSkipped;
2422 /** GC: The number of pages marked dirty because of write accesses. */
2423 STAMCOUNTER StatGCDirtiedPage;
2424 /** GC: The number of pages already marked dirty because of write accesses. */
2425 STAMCOUNTER StatGCPageAlreadyDirty;
2426 /** GC: The number of real pages faults during dirty bit tracking. */
2427 STAMCOUNTER StatGCDirtyTrackRealPF;
2428
2429 /** GC: Profiling of the PGMTrackDirtyBit() body */
2430 STAMPROFILE StatGCDirtyBitTracking;
2431 /** HC: Profiling of the PGMTrackDirtyBit() body */
2432 STAMPROFILE StatHCDirtyBitTracking;
2433
2434 /** GC: Profiling of the PGMGstModifyPage() body */
2435 STAMPROFILE StatGCGstModifyPage;
2436 /** HC: Profiling of the PGMGstModifyPage() body */
2437 STAMPROFILE StatHCGstModifyPage;
2438
2439 /** GC: The number of time we've marked a PD not present from SyncPage to virtualize the accessed bit. */
2440 STAMCOUNTER StatGCSyncPagePDNAs;
2441 /** GC: The number of time we've encountered an out-of-sync PD in SyncPage. */
2442 STAMCOUNTER StatGCSyncPagePDOutOfSync;
2443 /** HC: The number of time we've marked a PD not present from SyncPage to virtualize the accessed bit. */
2444 STAMCOUNTER StatHCSyncPagePDNAs;
2445 /** HC: The number of time we've encountered an out-of-sync PD in SyncPage. */
2446 STAMCOUNTER StatHCSyncPagePDOutOfSync;
2447
2448 STAMCOUNTER StatSynPT4kGC;
2449 STAMCOUNTER StatSynPT4kHC;
2450 STAMCOUNTER StatSynPT4MGC;
2451 STAMCOUNTER StatSynPT4MHC;
2452
2453 /** Profiling of the PGMFlushTLB() body. */
2454 STAMPROFILE StatFlushTLB;
2455 /** The number of times PGMFlushTLB was called with a new CR3, non-global. (switch) */
2456 STAMCOUNTER StatFlushTLBNewCR3;
2457 /** The number of times PGMFlushTLB was called with a new CR3, global. (switch) */
2458 STAMCOUNTER StatFlushTLBNewCR3Global;
2459 /** The number of times PGMFlushTLB was called with the same CR3, non-global. (flush) */
2460 STAMCOUNTER StatFlushTLBSameCR3;
2461 /** The number of times PGMFlushTLB was called with the same CR3, global. (flush) */
2462 STAMCOUNTER StatFlushTLBSameCR3Global;
2463
2464 STAMPROFILE StatGCSyncCR3; /**< GC: PGMSyncCR3() profiling. */
2465 STAMPROFILE StatGCSyncCR3Handlers; /**< GC: Profiling of the PGMSyncCR3() update handler section. */
2466 STAMPROFILE StatGCSyncCR3HandlerVirtualReset; /**< GC: Profiling of the virtual handler resets. */
2467 STAMPROFILE StatGCSyncCR3HandlerVirtualUpdate; /**< GC: Profiling of the virtual handler updates. */
2468 STAMCOUNTER StatGCSyncCR3Global; /**< GC: The number of global CR3 syncs. */
2469 STAMCOUNTER StatGCSyncCR3NotGlobal; /**< GC: The number of non-global CR3 syncs. */
2470 STAMCOUNTER StatGCSyncCR3DstFreed; /**< GC: The number of times we've had to free a shadow entry. */
2471 STAMCOUNTER StatGCSyncCR3DstFreedSrcNP; /**< GC: The number of times we've had to free a shadow entry for which the source entry was not present. */
2472 STAMCOUNTER StatGCSyncCR3DstNotPresent; /**< GC: The number of times we've encountered a not present shadow entry for a present guest entry. */
2473 STAMCOUNTER StatGCSyncCR3DstSkippedGlobalPD; /**< GC: The number of times a global page directory wasn't flushed. */
2474 STAMCOUNTER StatGCSyncCR3DstSkippedGlobalPT; /**< GC: The number of times a page table with only global entries wasn't flushed. */
2475 STAMCOUNTER StatGCSyncCR3DstCacheHit; /**< GC: The number of times we got some kind of cache hit on a page table. */
2476
2477 STAMPROFILE StatHCSyncCR3; /**< HC: PGMSyncCR3() profiling. */
2478 STAMPROFILE StatHCSyncCR3Handlers; /**< HC: Profiling of the PGMSyncCR3() update handler section. */
2479 STAMPROFILE StatHCSyncCR3HandlerVirtualReset; /**< HC: Profiling of the virtual handler resets. */
2480 STAMPROFILE StatHCSyncCR3HandlerVirtualUpdate; /**< HC: Profiling of the virtual handler updates. */
2481 STAMCOUNTER StatHCSyncCR3Global; /**< HC: The number of global CR3 syncs. */
2482 STAMCOUNTER StatHCSyncCR3NotGlobal; /**< HC: The number of non-global CR3 syncs. */
2483 STAMCOUNTER StatHCSyncCR3DstFreed; /**< HC: The number of times we've had to free a shadow entry. */
2484 STAMCOUNTER StatHCSyncCR3DstFreedSrcNP; /**< HC: The number of times we've had to free a shadow entry for which the source entry was not present. */
2485 STAMCOUNTER StatHCSyncCR3DstNotPresent; /**< HC: The number of times we've encountered a not present shadow entry for a present guest entry. */
2486 STAMCOUNTER StatHCSyncCR3DstSkippedGlobalPD; /**< HC: The number of times a global page directory wasn't flushed. */
2487 STAMCOUNTER StatHCSyncCR3DstSkippedGlobalPT; /**< HC: The number of times a page table with only global entries wasn't flushed. */
2488 STAMCOUNTER StatHCSyncCR3DstCacheHit; /**< HC: The number of times we got some kind of cache hit on a page table. */
2489
2490 /** GC: Profiling of pgmHandlerVirtualFindByPhysAddr. */
2491 STAMPROFILE StatVirtHandleSearchByPhysGC;
2492 /** HC: Profiling of pgmHandlerVirtualFindByPhysAddr. */
2493 STAMPROFILE StatVirtHandleSearchByPhysHC;
2494 /** HC: The number of times PGMR3HandlerPhysicalReset is called. */
2495 STAMCOUNTER StatHandlePhysicalReset;
2496
2497 STAMPROFILE StatCheckPageFault;
2498 STAMPROFILE StatLazySyncPT;
2499 STAMPROFILE StatMapping;
2500 STAMPROFILE StatOutOfSync;
2501 STAMPROFILE StatHandlers;
2502 STAMPROFILE StatEIPHandlers;
2503 STAMPROFILE StatHCPrefetch;
2504
2505# ifdef PGMPOOL_WITH_GCPHYS_TRACKING
2506 /** The number of first time shadowings. */
2507 STAMCOUNTER StatTrackVirgin;
2508 /** The number of times switching to cRef2, i.e. the page is being shadowed by two PTs. */
2509 STAMCOUNTER StatTrackAliased;
2510 /** The number of times we're tracking using cRef2. */
2511 STAMCOUNTER StatTrackAliasedMany;
2512 /** The number of times we're hitting pages which has overflowed cRef2. */
2513 STAMCOUNTER StatTrackAliasedLots;
2514 /** The number of times the extent list grows to long. */
2515 STAMCOUNTER StatTrackOverflows;
2516 /** Profiling of SyncPageWorkerTrackDeref (expensive). */
2517 STAMPROFILE StatTrackDeref;
2518# endif
2519
2520 /** Ring-3/0 page mapper TLB hits. */
2521 STAMCOUNTER StatPageHCMapTlbHits;
2522 /** Ring-3/0 page mapper TLB misses. */
2523 STAMCOUNTER StatPageHCMapTlbMisses;
2524 /** Ring-3/0 chunk mapper TLB hits. */
2525 STAMCOUNTER StatChunkR3MapTlbHits;
2526 /** Ring-3/0 chunk mapper TLB misses. */
2527 STAMCOUNTER StatChunkR3MapTlbMisses;
2528 /** Times a shared page has been replaced by a private one. */
2529 STAMCOUNTER StatPageReplaceShared;
2530 /** Times the zero page has been replaced by a private one. */
2531 STAMCOUNTER StatPageReplaceZero;
2532 /** The number of times we've executed GMMR3AllocateHandyPages. */
2533 STAMCOUNTER StatPageHandyAllocs;
2534
2535 /** Allocated mbs of guest ram */
2536 STAMCOUNTER StatDynRamTotal;
2537 /** Nr of pgmr3PhysGrowRange calls. */
2538 STAMCOUNTER StatDynRamGrow;
2539
2540 STAMCOUNTER StatGCTrap0ePD[X86_PG_ENTRIES];
2541 STAMCOUNTER StatGCSyncPtPD[X86_PG_ENTRIES];
2542 STAMCOUNTER StatGCSyncPagePD[X86_PG_ENTRIES];
2543#endif
2544} PGM, *PPGM;
2545
2546
2547/** @name PGM::fSyncFlags Flags
2548 * @{
2549 */
2550/** Updates the virtual access handler state bit in PGMPAGE. */
2551#define PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL RT_BIT(0)
2552/** Always sync CR3. */
2553#define PGM_SYNC_ALWAYS RT_BIT(1)
2554/** Check monitoring on next CR3 (re)load and invalidate page. */
2555#define PGM_SYNC_MONITOR_CR3 RT_BIT(2)
2556/** Clear the page pool (a light weight flush). */
2557#define PGM_SYNC_CLEAR_PGM_POOL RT_BIT(8)
2558/** @} */
2559
2560
2561__BEGIN_DECLS
2562
2563int pgmLock(PVM pVM);
2564void pgmUnlock(PVM pVM);
2565
2566PGMGCDECL(int) pgmGCGuestPDWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser);
2567PGMDECL(int) pgmPhysRomWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser);
2568int pgmR3ChangeMode(PVM pVM, PGMMODE enmGuestMode);
2569
2570int pgmR3SyncPTResolveConflict(PVM pVM, PPGMMAPPING pMapping, PX86PD pPDSrc, int iPDOld);
2571PPGMMAPPING pgmGetMapping(PVM pVM, RTGCPTR GCPtr);
2572void pgmR3MapRelocate(PVM pVM, PPGMMAPPING pMapping, int iPDOld, int iPDNew);
2573DECLCALLBACK(void) pgmR3MapInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
2574
2575void pgmR3HandlerPhysicalUpdateAll(PVM pVM);
2576int pgmHandlerVirtualFindByPhysAddr(PVM pVM, RTGCPHYS GCPhys, PPGMVIRTHANDLER *ppVirt, unsigned *piPage);
2577DECLCALLBACK(int) pgmHandlerVirtualResetOne(PAVLROGCPTRNODECORE pNode, void *pvUser);
2578#if defined(VBOX_STRICT) || defined(LOG_ENABLED)
2579void pgmHandlerVirtualDumpPhysPages(PVM pVM);
2580#else
2581# define pgmHandlerVirtualDumpPhysPages(a) do { } while (0)
2582#endif
2583DECLCALLBACK(void) pgmR3InfoHandlers(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
2584
2585
2586void pgmPhysFreePage(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys);
2587int pgmPhysPageLoadIntoTlb(PPGM pPGM, RTGCPHYS GCPhys);
2588int pgmPhysPageMakeWritable(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys);
2589int pgmPhysPageMap(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys, PPPGMPAGEMAP ppMap, void **ppv);
2590#ifdef IN_RING3
2591int pgmR3PhysChunkMap(PVM pVM, uint32_t idChunk, PPPGMCHUNKR3MAP ppChunk);
2592int pgmR3PhysRamReset(PVM pVM);
2593int pgmR3PhysRomReset(PVM pVM);
2594#ifndef VBOX_WITH_NEW_PHYS_CODE
2595int pgmr3PhysGrowRange(PVM pVM, RTGCPHYS GCPhys);
2596#endif
2597
2598int pgmR3PoolInit(PVM pVM);
2599void pgmR3PoolRelocate(PVM pVM);
2600void pgmR3PoolReset(PVM pVM);
2601
2602#endif /* IN_RING3 */
2603#ifdef IN_GC
2604void *pgmGCPoolMapPage(PVM pVM, PPGMPOOLPAGE pPage);
2605#endif
2606int pgmPoolAlloc(PVM pVM, RTGCPHYS GCPhys, PGMPOOLKIND enmKind, uint16_t iUser, uint16_t iUserTable, PPPGMPOOLPAGE ppPage);
2607PPGMPOOLPAGE pgmPoolGetPageByHCPhys(PVM pVM, RTHCPHYS HCPhys);
2608void pgmPoolFree(PVM pVM, RTHCPHYS HCPhys, uint16_t iUser, uint16_t iUserTable);
2609void pgmPoolFreeByPage(PPGMPOOL pPool, PPGMPOOLPAGE pPage, uint16_t iUser, uint16_t iUserTable);
2610int pgmPoolFlushPage(PPGMPOOL pPool, PPGMPOOLPAGE pPage);
2611void pgmPoolFlushAll(PVM pVM);
2612void pgmPoolClearAll(PVM pVM);
2613void pgmPoolTrackFlushGCPhysPT(PVM pVM, PPGMPAGE pPhysPage, uint16_t iShw, uint16_t cRefs);
2614void pgmPoolTrackFlushGCPhysPTs(PVM pVM, PPGMPAGE pPhysPage, uint16_t iPhysExt);
2615int pgmPoolTrackFlushGCPhysPTsSlow(PVM pVM, PPGMPAGE pPhysPage);
2616PPGMPOOLPHYSEXT pgmPoolTrackPhysExtAlloc(PVM pVM, uint16_t *piPhysExt);
2617void pgmPoolTrackPhysExtFree(PVM pVM, uint16_t iPhysExt);
2618void pgmPoolTrackPhysExtFreeList(PVM pVM, uint16_t iPhysExt);
2619uint16_t pgmPoolTrackPhysExtAddref(PVM pVM, uint16_t u16, uint16_t iShwPT);
2620void pgmPoolTrackPhysExtDerefGCPhys(PPGMPOOL pPool, PPGMPOOLPAGE pPoolPage, PPGMPAGE pPhysPage);
2621#ifdef PGMPOOL_WITH_MONITORING
2622# ifdef IN_RING3
2623void pgmPoolMonitorChainChanging(PPGMPOOL pPool, PPGMPOOLPAGE pPage, RTGCPHYS GCPhysFault, RTHCPTR pvAddress, PDISCPUSTATE pCpu);
2624# else
2625void pgmPoolMonitorChainChanging(PPGMPOOL pPool, PPGMPOOLPAGE pPage, RTGCPHYS GCPhysFault, RTGCPTR pvAddress, PDISCPUSTATE pCpu);
2626# endif
2627int pgmPoolMonitorChainFlush(PPGMPOOL pPool, PPGMPOOLPAGE pPage);
2628void pgmPoolMonitorModifiedInsert(PPGMPOOL pPool, PPGMPOOLPAGE pPage);
2629void pgmPoolMonitorModifiedClearAll(PVM pVM);
2630int pgmPoolMonitorMonitorCR3(PPGMPOOL pPool, uint16_t idxRoot, RTGCPHYS GCPhysCR3);
2631int pgmPoolMonitorUnmonitorCR3(PPGMPOOL pPool, uint16_t idxRoot);
2632#endif
2633
2634__END_DECLS
2635
2636
2637/**
2638 * Gets the PGMRAMRANGE structure for a guest page.
2639 *
2640 * @returns Pointer to the RAM range on success.
2641 * @returns NULL on a VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS condition.
2642 *
2643 * @param pPGM PGM handle.
2644 * @param GCPhys The GC physical address.
2645 */
2646DECLINLINE(PPGMRAMRANGE) pgmPhysGetRange(PPGM pPGM, RTGCPHYS GCPhys)
2647{
2648 /*
2649 * Optimize for the first range.
2650 */
2651 PPGMRAMRANGE pRam = CTXALLSUFF(pPGM->pRamRanges);
2652 RTGCPHYS off = GCPhys - pRam->GCPhys;
2653 if (RT_UNLIKELY(off >= pRam->cb))
2654 {
2655 do
2656 {
2657 pRam = CTXALLSUFF(pRam->pNext);
2658 if (RT_UNLIKELY(!pRam))
2659 break;
2660 off = GCPhys - pRam->GCPhys;
2661 } while (off >= pRam->cb);
2662 }
2663 return pRam;
2664}
2665
2666
2667/**
2668 * Gets the PGMPAGE structure for a guest page.
2669 *
2670 * @returns Pointer to the page on success.
2671 * @returns NULL on a VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS condition.
2672 *
2673 * @param pPGM PGM handle.
2674 * @param GCPhys The GC physical address.
2675 */
2676DECLINLINE(PPGMPAGE) pgmPhysGetPage(PPGM pPGM, RTGCPHYS GCPhys)
2677{
2678 /*
2679 * Optimize for the first range.
2680 */
2681 PPGMRAMRANGE pRam = CTXALLSUFF(pPGM->pRamRanges);
2682 RTGCPHYS off = GCPhys - pRam->GCPhys;
2683 if (RT_UNLIKELY(off >= pRam->cb))
2684 {
2685 do
2686 {
2687 pRam = CTXALLSUFF(pRam->pNext);
2688 if (RT_UNLIKELY(!pRam))
2689 return NULL;
2690 off = GCPhys - pRam->GCPhys;
2691 } while (off >= pRam->cb);
2692 }
2693 return &pRam->aPages[off >> PAGE_SHIFT];
2694}
2695
2696
2697/**
2698 * Gets the PGMPAGE structure for a guest page.
2699 *
2700 * Old Phys code: Will make sure the page is present.
2701 *
2702 * @returns VBox status code.
2703 * @retval VINF_SUCCESS and a valid *ppPage on success.
2704 * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if the address isn't valid.
2705 *
2706 * @param pPGM PGM handle.
2707 * @param GCPhys The GC physical address.
2708 * @param ppPage Where to store the page poitner on success.
2709 */
2710DECLINLINE(int) pgmPhysGetPageEx(PPGM pPGM, RTGCPHYS GCPhys, PPPGMPAGE ppPage)
2711{
2712 /*
2713 * Optimize for the first range.
2714 */
2715 PPGMRAMRANGE pRam = CTXALLSUFF(pPGM->pRamRanges);
2716 RTGCPHYS off = GCPhys - pRam->GCPhys;
2717 if (RT_UNLIKELY(off >= pRam->cb))
2718 {
2719 do
2720 {
2721 pRam = CTXALLSUFF(pRam->pNext);
2722 if (RT_UNLIKELY(!pRam))
2723 {
2724 *ppPage = NULL; /* avoid incorrect and very annoying GCC warnings */
2725 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
2726 }
2727 off = GCPhys - pRam->GCPhys;
2728 } while (off >= pRam->cb);
2729 }
2730 *ppPage = &pRam->aPages[off >> PAGE_SHIFT];
2731#ifndef VBOX_WITH_NEW_PHYS_CODE
2732
2733 /*
2734 * Make sure it's present.
2735 */
2736 if (RT_UNLIKELY( !PGM_PAGE_GET_HCPHYS(*ppPage)
2737 && (pRam->fFlags & MM_RAM_FLAGS_DYNAMIC_ALLOC)))
2738 {
2739#ifdef IN_RING3
2740 int rc = pgmr3PhysGrowRange(PGM2VM(pPGM), GCPhys);
2741#else
2742 int rc = CTXALLMID(VMM, CallHost)(PGM2VM(pPGM), VMMCALLHOST_PGM_RAM_GROW_RANGE, GCPhys);
2743#endif
2744 if (VBOX_FAILURE(rc))
2745 {
2746 *ppPage = NULL; /* avoid incorrect and very annoying GCC warnings */
2747 return rc;
2748 }
2749 Assert(rc == VINF_SUCCESS);
2750 }
2751#endif
2752 return VINF_SUCCESS;
2753}
2754
2755
2756
2757
2758/**
2759 * Gets the PGMPAGE structure for a guest page.
2760 *
2761 * Old Phys code: Will make sure the page is present.
2762 *
2763 * @returns VBox status code.
2764 * @retval VINF_SUCCESS and a valid *ppPage on success.
2765 * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if the address isn't valid.
2766 *
2767 * @param pPGM PGM handle.
2768 * @param GCPhys The GC physical address.
2769 * @param ppPage Where to store the page poitner on success.
2770 * @param ppRamHint Where to read and store the ram list hint.
2771 * The caller initializes this to NULL before the call.
2772 */
2773DECLINLINE(int) pgmPhysGetPageWithHintEx(PPGM pPGM, RTGCPHYS GCPhys, PPPGMPAGE ppPage, PPGMRAMRANGE *ppRamHint)
2774{
2775 RTGCPHYS off;
2776 PPGMRAMRANGE pRam = *ppRamHint;
2777 if ( !pRam
2778 || RT_UNLIKELY((off = GCPhys - pRam->GCPhys) >= pRam->cb))
2779 {
2780 pRam = CTXALLSUFF(pPGM->pRamRanges);
2781 off = GCPhys - pRam->GCPhys;
2782 if (RT_UNLIKELY(off >= pRam->cb))
2783 {
2784 do
2785 {
2786 pRam = CTXALLSUFF(pRam->pNext);
2787 if (RT_UNLIKELY(!pRam))
2788 {
2789 *ppPage = NULL; /* Kill the incorrect and extremely annoying GCC warnings. */
2790 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
2791 }
2792 off = GCPhys - pRam->GCPhys;
2793 } while (off >= pRam->cb);
2794 }
2795 *ppRamHint = pRam;
2796 }
2797 *ppPage = &pRam->aPages[off >> PAGE_SHIFT];
2798#ifndef VBOX_WITH_NEW_PHYS_CODE
2799
2800 /*
2801 * Make sure it's present.
2802 */
2803 if (RT_UNLIKELY( !PGM_PAGE_GET_HCPHYS(*ppPage)
2804 && (pRam->fFlags & MM_RAM_FLAGS_DYNAMIC_ALLOC)))
2805 {
2806#ifdef IN_RING3
2807 int rc = pgmr3PhysGrowRange(PGM2VM(pPGM), GCPhys);
2808#else
2809 int rc = CTXALLMID(VMM, CallHost)(PGM2VM(pPGM), VMMCALLHOST_PGM_RAM_GROW_RANGE, GCPhys);
2810#endif
2811 if (VBOX_FAILURE(rc))
2812 {
2813 *ppPage = NULL; /* Shut up annoying smart ass. */
2814 return rc;
2815 }
2816 Assert(rc == VINF_SUCCESS);
2817 }
2818#endif
2819 return VINF_SUCCESS;
2820}
2821
2822
2823/**
2824 * Gets the PGMPAGE structure for a guest page together with the PGMRAMRANGE.
2825 *
2826 * @returns Pointer to the page on success.
2827 * @returns NULL on a VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS condition.
2828 *
2829 * @param pPGM PGM handle.
2830 * @param GCPhys The GC physical address.
2831 * @param ppRam Where to store the pointer to the PGMRAMRANGE.
2832 */
2833DECLINLINE(PPGMPAGE) pgmPhysGetPageAndRange(PPGM pPGM, RTGCPHYS GCPhys, PPGMRAMRANGE *ppRam)
2834{
2835 /*
2836 * Optimize for the first range.
2837 */
2838 PPGMRAMRANGE pRam = CTXALLSUFF(pPGM->pRamRanges);
2839 RTGCPHYS off = GCPhys - pRam->GCPhys;
2840 if (RT_UNLIKELY(off >= pRam->cb))
2841 {
2842 do
2843 {
2844 pRam = CTXALLSUFF(pRam->pNext);
2845 if (RT_UNLIKELY(!pRam))
2846 return NULL;
2847 off = GCPhys - pRam->GCPhys;
2848 } while (off >= pRam->cb);
2849 }
2850 *ppRam = pRam;
2851 return &pRam->aPages[off >> PAGE_SHIFT];
2852}
2853
2854
2855
2856
2857/**
2858 * Gets the PGMPAGE structure for a guest page together with the PGMRAMRANGE.
2859 *
2860 * @returns Pointer to the page on success.
2861 * @returns NULL on a VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS condition.
2862 *
2863 * @param pPGM PGM handle.
2864 * @param GCPhys The GC physical address.
2865 * @param ppPage Where to store the pointer to the PGMPAGE structure.
2866 * @param ppRam Where to store the pointer to the PGMRAMRANGE structure.
2867 */
2868DECLINLINE(int) pgmPhysGetPageAndRangeEx(PPGM pPGM, RTGCPHYS GCPhys, PPPGMPAGE ppPage, PPGMRAMRANGE *ppRam)
2869{
2870 /*
2871 * Optimize for the first range.
2872 */
2873 PPGMRAMRANGE pRam = CTXALLSUFF(pPGM->pRamRanges);
2874 RTGCPHYS off = GCPhys - pRam->GCPhys;
2875 if (RT_UNLIKELY(off >= pRam->cb))
2876 {
2877 do
2878 {
2879 pRam = CTXALLSUFF(pRam->pNext);
2880 if (RT_UNLIKELY(!pRam))
2881 {
2882 *ppRam = NULL; /* Shut up silly GCC warnings. */
2883 *ppPage = NULL; /* ditto */
2884 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
2885 }
2886 off = GCPhys - pRam->GCPhys;
2887 } while (off >= pRam->cb);
2888 }
2889 *ppRam = pRam;
2890 *ppPage = &pRam->aPages[off >> PAGE_SHIFT];
2891#ifndef VBOX_WITH_NEW_PHYS_CODE
2892
2893 /*
2894 * Make sure it's present.
2895 */
2896 if (RT_UNLIKELY( !PGM_PAGE_GET_HCPHYS(*ppPage)
2897 && (pRam->fFlags & MM_RAM_FLAGS_DYNAMIC_ALLOC)))
2898 {
2899#ifdef IN_RING3
2900 int rc = pgmr3PhysGrowRange(PGM2VM(pPGM), GCPhys);
2901#else
2902 int rc = CTXALLMID(VMM, CallHost)(PGM2VM(pPGM), VMMCALLHOST_PGM_RAM_GROW_RANGE, GCPhys);
2903#endif
2904 if (VBOX_FAILURE(rc))
2905 {
2906 *ppPage = NULL; /* Shut up silly GCC warnings. */
2907 *ppPage = NULL; /* ditto */
2908 return rc;
2909 }
2910 Assert(rc == VINF_SUCCESS);
2911
2912 }
2913#endif
2914 return VINF_SUCCESS;
2915}
2916
2917
2918/**
2919 * Convert GC Phys to HC Phys.
2920 *
2921 * @returns VBox status.
2922 * @param pPGM PGM handle.
2923 * @param GCPhys The GC physical address.
2924 * @param pHCPhys Where to store the corresponding HC physical address.
2925 *
2926 * @deprecated Doesn't deal with zero, shared or write monitored pages.
2927 * Avoid when writing new code!
2928 */
2929DECLINLINE(int) pgmRamGCPhys2HCPhys(PPGM pPGM, RTGCPHYS GCPhys, PRTHCPHYS pHCPhys)
2930{
2931 PPGMPAGE pPage;
2932 int rc = pgmPhysGetPageEx(pPGM, GCPhys, &pPage);
2933 if (VBOX_FAILURE(rc))
2934 return rc;
2935 *pHCPhys = PGM_PAGE_GET_HCPHYS(pPage) | (GCPhys & PAGE_OFFSET_MASK);
2936 return VINF_SUCCESS;
2937}
2938
2939
2940#ifndef IN_GC
2941/**
2942 * Queries the Physical TLB entry for a physical guest page,
2943 * attemting to load the TLB entry if necessary.
2944 *
2945 * @returns VBox status code.
2946 * @retval VINF_SUCCESS on success
2947 * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if it's not a valid physical address.
2948 * @param pPGM The PGM instance handle.
2949 * @param GCPhys The address of the guest page.
2950 * @param ppTlbe Where to store the pointer to the TLB entry.
2951 */
2952
2953DECLINLINE(int) pgmPhysPageQueryTlbe(PPGM pPGM, RTGCPHYS GCPhys, PPPGMPAGEMAPTLBE ppTlbe)
2954{
2955 int rc;
2956 PPGMPAGEMAPTLBE pTlbe = &pPGM->CTXSUFF(PhysTlb).aEntries[PGM_PAGEMAPTLB_IDX(GCPhys)];
2957 if (pTlbe->GCPhys == (GCPhys & X86_PTE_PAE_PG_MASK))
2958 {
2959 STAM_COUNTER_INC(&pPGM->CTXMID(StatPage,MapTlbHits));
2960 rc = VINF_SUCCESS;
2961 }
2962 else
2963 rc = pgmPhysPageLoadIntoTlb(pPGM, GCPhys);
2964 *ppTlbe = pTlbe;
2965 return rc;
2966}
2967#endif /* !IN_GC */
2968
2969
2970#ifndef VBOX_WITH_NEW_PHYS_CODE
2971/**
2972 * Convert GC Phys to HC Virt.
2973 *
2974 * @returns VBox status.
2975 * @param pPGM PGM handle.
2976 * @param GCPhys The GC physical address.
2977 * @param pHCPtr Where to store the corresponding HC virtual address.
2978 *
2979 * @deprecated This will be eliminated by PGMPhysGCPhys2CCPtr.
2980 */
2981DECLINLINE(int) pgmRamGCPhys2HCPtr(PPGM pPGM, RTGCPHYS GCPhys, PRTHCPTR pHCPtr)
2982{
2983 PPGMRAMRANGE pRam;
2984 PPGMPAGE pPage;
2985 int rc = pgmPhysGetPageAndRangeEx(pPGM, GCPhys, &pPage, &pRam);
2986 if (VBOX_FAILURE(rc))
2987 {
2988 *pHCPtr = 0; /* Shut up silly GCC warnings. */
2989 return rc;
2990 }
2991 RTGCPHYS off = GCPhys - pRam->GCPhys;
2992
2993 if (pRam->fFlags & MM_RAM_FLAGS_DYNAMIC_ALLOC)
2994 {
2995 unsigned iChunk = off >> PGM_DYNAMIC_CHUNK_SHIFT;
2996 *pHCPtr = (RTHCPTR)((RTHCUINTPTR)CTXSUFF(pRam->pavHCChunk)[iChunk] + (off & PGM_DYNAMIC_CHUNK_OFFSET_MASK));
2997 return VINF_SUCCESS;
2998 }
2999 if (pRam->pvHC)
3000 {
3001 *pHCPtr = (RTHCPTR)((RTHCUINTPTR)pRam->pvHC + off);
3002 return VINF_SUCCESS;
3003 }
3004 *pHCPtr = 0; /* Shut up silly GCC warnings. */
3005 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
3006}
3007#endif /* !VBOX_WITH_NEW_PHYS_CODE */
3008
3009
3010/**
3011 * Convert GC Phys to HC Virt.
3012 *
3013 * @returns VBox status.
3014 * @param PVM VM handle.
3015 * @param pRam Ram range
3016 * @param GCPhys The GC physical address.
3017 * @param pHCPtr Where to store the corresponding HC virtual address.
3018 *
3019 * @deprecated This will be eliminated. Don't use it.
3020 */
3021DECLINLINE(int) pgmRamGCPhys2HCPtrWithRange(PVM pVM, PPGMRAMRANGE pRam, RTGCPHYS GCPhys, PRTHCPTR pHCPtr)
3022{
3023 RTGCPHYS off = GCPhys - pRam->GCPhys;
3024 Assert(off < pRam->cb);
3025
3026 if (pRam->fFlags & MM_RAM_FLAGS_DYNAMIC_ALLOC)
3027 {
3028 unsigned idx = (off >> PGM_DYNAMIC_CHUNK_SHIFT);
3029 /* Physical chunk in dynamically allocated range not present? */
3030 if (RT_UNLIKELY(!CTXSUFF(pRam->pavHCChunk)[idx]))
3031 {
3032#ifdef IN_RING3
3033 int rc = pgmr3PhysGrowRange(pVM, GCPhys);
3034#else
3035 int rc = CTXALLMID(VMM, CallHost)(pVM, VMMCALLHOST_PGM_RAM_GROW_RANGE, GCPhys);
3036#endif
3037 if (rc != VINF_SUCCESS)
3038 {
3039 *pHCPtr = 0; /* GCC crap */
3040 return rc;
3041 }
3042 }
3043 *pHCPtr = (RTHCPTR)((RTHCUINTPTR)CTXSUFF(pRam->pavHCChunk)[idx] + (off & PGM_DYNAMIC_CHUNK_OFFSET_MASK));
3044 return VINF_SUCCESS;
3045 }
3046 if (pRam->pvHC)
3047 {
3048 *pHCPtr = (RTHCPTR)((RTHCUINTPTR)pRam->pvHC + off);
3049 return VINF_SUCCESS;
3050 }
3051 *pHCPtr = 0; /* GCC crap */
3052 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
3053}
3054
3055
3056/**
3057 * Convert GC Phys to HC Virt and HC Phys.
3058 *
3059 * @returns VBox status.
3060 * @param pPGM PGM handle.
3061 * @param GCPhys The GC physical address.
3062 * @param pHCPtr Where to store the corresponding HC virtual address.
3063 * @param pHCPhys Where to store the HC Physical address and its flags.
3064 *
3065 * @deprecated Will go away or be changed. Only user is MapCR3. MapCR3 will have to do ring-3
3066 * and ring-0 locking of the CR3 in a lazy fashion I'm fear... or perhaps not. we'll see.
3067 */
3068DECLINLINE(int) pgmRamGCPhys2HCPtrAndHCPhysWithFlags(PPGM pPGM, RTGCPHYS GCPhys, PRTHCPTR pHCPtr, PRTHCPHYS pHCPhys)
3069{
3070 PPGMRAMRANGE pRam;
3071 PPGMPAGE pPage;
3072 int rc = pgmPhysGetPageAndRangeEx(pPGM, GCPhys, &pPage, &pRam);
3073 if (VBOX_FAILURE(rc))
3074 {
3075 *pHCPtr = 0; /* Shut up crappy GCC warnings */
3076 *pHCPhys = 0; /* ditto */
3077 return rc;
3078 }
3079 RTGCPHYS off = GCPhys - pRam->GCPhys;
3080
3081 *pHCPhys = pPage->HCPhys; /** @todo PAGE FLAGS */
3082 if (pRam->fFlags & MM_RAM_FLAGS_DYNAMIC_ALLOC)
3083 {
3084 unsigned idx = (off >> PGM_DYNAMIC_CHUNK_SHIFT);
3085 *pHCPtr = (RTHCPTR)((RTHCUINTPTR)CTXSUFF(pRam->pavHCChunk)[idx] + (off & PGM_DYNAMIC_CHUNK_OFFSET_MASK));
3086 return VINF_SUCCESS;
3087 }
3088 if (pRam->pvHC)
3089 {
3090 *pHCPtr = (RTHCPTR)((RTHCUINTPTR)pRam->pvHC + off);
3091 return VINF_SUCCESS;
3092 }
3093 *pHCPtr = 0;
3094 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
3095}
3096
3097
3098/**
3099 * Clears flags associated with a RAM address.
3100 *
3101 * @returns VBox status code.
3102 * @param pPGM PGM handle.
3103 * @param GCPhys Guest context physical address.
3104 * @param fFlags fFlags to clear. (Bits 0-11.)
3105 */
3106DECLINLINE(int) pgmRamFlagsClearByGCPhys(PPGM pPGM, RTGCPHYS GCPhys, unsigned fFlags)
3107{
3108 PPGMPAGE pPage;
3109 int rc = pgmPhysGetPageEx(pPGM, GCPhys, &pPage);
3110 if (VBOX_FAILURE(rc))
3111 return rc;
3112
3113 fFlags &= ~X86_PTE_PAE_PG_MASK;
3114 pPage->HCPhys &= ~(RTHCPHYS)fFlags; /** @todo PAGE FLAGS */
3115 return VINF_SUCCESS;
3116}
3117
3118
3119/**
3120 * Clears flags associated with a RAM address.
3121 *
3122 * @returns VBox status code.
3123 * @param pPGM PGM handle.
3124 * @param GCPhys Guest context physical address.
3125 * @param fFlags fFlags to clear. (Bits 0-11.)
3126 * @param ppRamHint Where to read and store the ram list hint.
3127 * The caller initializes this to NULL before the call.
3128 */
3129DECLINLINE(int) pgmRamFlagsClearByGCPhysWithHint(PPGM pPGM, RTGCPHYS GCPhys, unsigned fFlags, PPGMRAMRANGE *ppRamHint)
3130{
3131 PPGMPAGE pPage;
3132 int rc = pgmPhysGetPageWithHintEx(pPGM, GCPhys, &pPage, ppRamHint);
3133 if (VBOX_FAILURE(rc))
3134 return rc;
3135
3136 fFlags &= ~X86_PTE_PAE_PG_MASK;
3137 pPage->HCPhys &= ~(RTHCPHYS)fFlags; /** @todo PAGE FLAGS */
3138 return VINF_SUCCESS;
3139}
3140
3141/**
3142 * Sets (bitwise OR) flags associated with a RAM address.
3143 *
3144 * @returns VBox status code.
3145 * @param pPGM PGM handle.
3146 * @param GCPhys Guest context physical address.
3147 * @param fFlags fFlags to set clear. (Bits 0-11.)
3148 */
3149DECLINLINE(int) pgmRamFlagsSetByGCPhys(PPGM pPGM, RTGCPHYS GCPhys, unsigned fFlags)
3150{
3151 PPGMPAGE pPage;
3152 int rc = pgmPhysGetPageEx(pPGM, GCPhys, &pPage);
3153 if (VBOX_FAILURE(rc))
3154 return rc;
3155
3156 fFlags &= ~X86_PTE_PAE_PG_MASK;
3157 pPage->HCPhys |= fFlags; /** @todo PAGE FLAGS */
3158 return VINF_SUCCESS;
3159}
3160
3161
3162/**
3163 * Sets (bitwise OR) flags associated with a RAM address.
3164 *
3165 * @returns VBox status code.
3166 * @param pPGM PGM handle.
3167 * @param GCPhys Guest context physical address.
3168 * @param fFlags fFlags to set clear. (Bits 0-11.)
3169 * @param ppRamHint Where to read and store the ram list hint.
3170 * The caller initializes this to NULL before the call.
3171 */
3172DECLINLINE(int) pgmRamFlagsSetByGCPhysWithHint(PPGM pPGM, RTGCPHYS GCPhys, unsigned fFlags, PPGMRAMRANGE *ppRamHint)
3173{
3174 PPGMPAGE pPage;
3175 int rc = pgmPhysGetPageWithHintEx(pPGM, GCPhys, &pPage, ppRamHint);
3176 if (VBOX_FAILURE(rc))
3177 return rc;
3178
3179 fFlags &= ~X86_PTE_PAE_PG_MASK;
3180 pPage->HCPhys |= fFlags; /** @todo PAGE FLAGS */
3181 return VINF_SUCCESS;
3182}
3183
3184
3185/**
3186 * Gets the page directory for the specified address.
3187 *
3188 * @returns Pointer to the page directory in question.
3189 * @returns NULL if the page directory is not present or on an invalid page.
3190 * @param pPGM Pointer to the PGM instance data.
3191 * @param GCPtr The address.
3192 */
3193DECLINLINE(PX86PDPAE) pgmGstGetPaePD(PPGM pPGM, RTGCUINTPTR GCPtr)
3194{
3195 const unsigned iPdPt = GCPtr >> X86_PDPT_SHIFT;
3196 if (CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].n.u1Present)
3197 {
3198 if ((CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u & X86_PDPE_PG_MASK) == pPGM->aGCPhysGstPaePDs[iPdPt])
3199 return CTXSUFF(pPGM->apGstPaePDs)[iPdPt];
3200
3201 /* cache is out-of-sync. */
3202 PX86PDPAE pPD;
3203 int rc = PGM_GCPHYS_2_PTR(PGM2VM(pPGM), CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u & X86_PDPE_PG_MASK, &pPD);
3204 if (VBOX_SUCCESS(rc))
3205 return pPD;
3206 AssertMsgFailed(("Impossible! rc=%d PDPE=%#llx\n", rc, CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u));
3207 /* returning NIL_RTGCPHYS is ok if we assume it's just an invalid page of some kind emulated as all 0s. */
3208 }
3209 return NULL;
3210}
3211
3212
3213/**
3214 * Gets the page directory entry for the specified address.
3215 *
3216 * @returns Pointer to the page directory entry in question.
3217 * @returns NULL if the page directory is not present or on an invalid page.
3218 * @param pPGM Pointer to the PGM instance data.
3219 * @param GCPtr The address.
3220 */
3221DECLINLINE(PX86PDEPAE) pgmGstGetPaePDEPtr(PPGM pPGM, RTGCUINTPTR GCPtr)
3222{
3223 const unsigned iPdPt = GCPtr >> X86_PDPT_SHIFT;
3224 if (CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].n.u1Present)
3225 {
3226 const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
3227 if ((CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u & X86_PDPE_PG_MASK) == pPGM->aGCPhysGstPaePDs[iPdPt])
3228 return &CTXSUFF(pPGM->apGstPaePDs)[iPdPt]->a[iPD];
3229
3230 /* The cache is out-of-sync. */
3231 PX86PDPAE pPD;
3232 int rc = PGM_GCPHYS_2_PTR(PGM2VM(pPGM), CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u & X86_PDPE_PG_MASK, &pPD);
3233 if (VBOX_SUCCESS(rc))
3234 return &pPD->a[iPD];
3235 AssertMsgFailed(("Impossible! rc=%Vrc PDPE=%RX64\n", rc, CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u));
3236 /* returning NIL_RTGCPHYS is ok if we assume it's just an invalid page or something which we'll emulate as all 0s. */
3237 }
3238 return NULL;
3239}
3240
3241
3242/**
3243 * Gets the page directory entry for the specified address.
3244 *
3245 * @returns The page directory entry in question.
3246 * @returns A non-present entry if the page directory is not present or on an invalid page.
3247 * @param pPGM Pointer to the PGM instance data.
3248 * @param GCPtr The address.
3249 */
3250DECLINLINE(uint64_t) pgmGstGetPaePDE(PPGM pPGM, RTGCUINTPTR GCPtr)
3251{
3252 const unsigned iPdPt = GCPtr >> X86_PDPT_SHIFT;
3253 if (CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].n.u1Present)
3254 {
3255 const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
3256 if ((CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u & X86_PDPE_PG_MASK) == pPGM->aGCPhysGstPaePDs[iPdPt])
3257 return CTXSUFF(pPGM->apGstPaePDs)[iPdPt]->a[iPD].u;
3258
3259 /* cache is out-of-sync. */
3260 PX86PDPAE pPD;
3261 int rc = PGM_GCPHYS_2_PTR(PGM2VM(pPGM), CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u & X86_PDPE_PG_MASK, &pPD);
3262 if (VBOX_SUCCESS(rc))
3263 return pPD->a[iPD].u;
3264 AssertMsgFailed(("Impossible! rc=%d PDPE=%#llx\n", rc, CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u));
3265 }
3266 return 0ULL;
3267}
3268
3269
3270/**
3271 * Gets the page directory pointer table entry for the specified address
3272 * and returns the index into the page directory
3273 *
3274 * @returns Pointer to the page directory in question.
3275 * @returns NULL if the page directory is not present or on an invalid page.
3276 * @param pPGM Pointer to the PGM instance data.
3277 * @param GCPtr The address.
3278 * @param piPD Receives the index into the returned page directory
3279 */
3280DECLINLINE(PX86PDPAE) pgmGstGetPaePDPtr(PPGM pPGM, RTGCUINTPTR GCPtr, unsigned *piPD)
3281{
3282 const unsigned iPdPt = GCPtr >> X86_PDPT_SHIFT;
3283 if (CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].n.u1Present)
3284 {
3285 const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
3286 if ((CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u & X86_PDPE_PG_MASK) == pPGM->aGCPhysGstPaePDs[iPdPt])
3287 {
3288 *piPD = iPD;
3289 return CTXSUFF(pPGM->apGstPaePDs)[iPdPt];
3290 }
3291
3292 /* cache is out-of-sync. */
3293 PX86PDPAE pPD;
3294 int rc = PGM_GCPHYS_2_PTR(PGM2VM(pPGM), CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u & X86_PDPE_PG_MASK, &pPD);
3295 if (VBOX_SUCCESS(rc))
3296 {
3297 *piPD = iPD;
3298 return pPD;
3299 }
3300 AssertMsgFailed(("Impossible! rc=%d PDPE=%#llx\n", rc, CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u));
3301 /* returning NIL_RTGCPHYS is ok if we assume it's just an invalid page of some kind emulated as all 0s. */
3302 }
3303 return NULL;
3304}
3305
3306
3307/**
3308 * Checks if any of the specified page flags are set for the given page.
3309 *
3310 * @returns true if any of the flags are set.
3311 * @returns false if all the flags are clear.
3312 * @param pPGM PGM handle.
3313 * @param GCPhys The GC physical address.
3314 * @param fFlags The flags to check for.
3315 */
3316DECLINLINE(bool) pgmRamTestFlags(PPGM pPGM, RTGCPHYS GCPhys, uint64_t fFlags)
3317{
3318 PPGMPAGE pPage = pgmPhysGetPage(pPGM, GCPhys);
3319 return pPage
3320 && (pPage->HCPhys & fFlags) != 0; /** @todo PAGE FLAGS */
3321}
3322
3323
3324/**
3325 * Gets the page state for a physical handler.
3326 *
3327 * @returns The physical handler page state.
3328 * @param pCur The physical handler in question.
3329 */
3330DECLINLINE(unsigned) pgmHandlerPhysicalCalcState(PPGMPHYSHANDLER pCur)
3331{
3332 switch (pCur->enmType)
3333 {
3334 case PGMPHYSHANDLERTYPE_PHYSICAL_WRITE:
3335 return PGM_PAGE_HNDL_PHYS_STATE_WRITE;
3336
3337 case PGMPHYSHANDLERTYPE_MMIO:
3338 case PGMPHYSHANDLERTYPE_PHYSICAL_ALL:
3339 return PGM_PAGE_HNDL_PHYS_STATE_ALL;
3340
3341 default:
3342 AssertFatalMsgFailed(("Invalid type %d\n", pCur->enmType));
3343 }
3344}
3345
3346
3347/**
3348 * Gets the page state for a virtual handler.
3349 *
3350 * @returns The virtual handler page state.
3351 * @param pCur The virtual handler in question.
3352 * @remarks This should never be used on a hypervisor access handler.
3353 */
3354DECLINLINE(unsigned) pgmHandlerVirtualCalcState(PPGMVIRTHANDLER pCur)
3355{
3356 switch (pCur->enmType)
3357 {
3358 case PGMVIRTHANDLERTYPE_WRITE:
3359 return PGM_PAGE_HNDL_VIRT_STATE_WRITE;
3360 case PGMVIRTHANDLERTYPE_ALL:
3361 return PGM_PAGE_HNDL_VIRT_STATE_ALL;
3362 default:
3363 AssertFatalMsgFailed(("Invalid type %d\n", pCur->enmType));
3364 }
3365}
3366
3367
3368/**
3369 * Clears one physical page of a virtual handler
3370 *
3371 * @param pPGM Pointer to the PGM instance.
3372 * @param pCur Virtual handler structure
3373 * @param iPage Physical page index
3374 *
3375 * @remark Only used when PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL is being set, so no
3376 * need to care about other handlers in the same page.
3377 */
3378DECLINLINE(void) pgmHandlerVirtualClearPage(PPGM pPGM, PPGMVIRTHANDLER pCur, unsigned iPage)
3379{
3380 const PPGMPHYS2VIRTHANDLER pPhys2Virt = &pCur->aPhysToVirt[iPage];
3381
3382 /*
3383 * Remove the node from the tree (it's supposed to be in the tree if we get here!).
3384 */
3385#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
3386 AssertReleaseMsg(pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_IN_TREE,
3387 ("pPhys2Virt=%p:{.Core.Key=%VGp, .Core.KeyLast=%VGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
3388 pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias));
3389#endif
3390 if (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_IS_HEAD)
3391 {
3392 /* We're the head of the alias chain. */
3393 PPGMPHYS2VIRTHANDLER pRemove = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysRemove(&pPGM->CTXSUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key); NOREF(pRemove);
3394#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
3395 AssertReleaseMsg(pRemove != NULL,
3396 ("pPhys2Virt=%p:{.Core.Key=%VGp, .Core.KeyLast=%VGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
3397 pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias));
3398 AssertReleaseMsg(pRemove == pPhys2Virt,
3399 ("wanted: pPhys2Virt=%p:{.Core.Key=%VGp, .Core.KeyLast=%VGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n"
3400 " got: pRemove=%p:{.Core.Key=%VGp, .Core.KeyLast=%VGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
3401 pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias,
3402 pRemove, pRemove->Core.Key, pRemove->Core.KeyLast, pRemove->offVirtHandler, pRemove->offNextAlias));
3403#endif
3404 if (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK)
3405 {
3406 /* Insert the next list in the alias chain into the tree. */
3407 PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
3408#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
3409 AssertReleaseMsg(pNext->offNextAlias & PGMPHYS2VIRTHANDLER_IN_TREE,
3410 ("pNext=%p:{.Core.Key=%VGp, .Core.KeyLast=%VGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
3411 pNext, pNext->Core.Key, pNext->Core.KeyLast, pNext->offVirtHandler, pNext->offNextAlias));
3412#endif
3413 pNext->offNextAlias |= PGMPHYS2VIRTHANDLER_IS_HEAD;
3414 bool fRc = RTAvlroGCPhysInsert(&pPGM->CTXSUFF(pTrees)->PhysToVirtHandlers, &pNext->Core);
3415 AssertRelease(fRc);
3416 }
3417 }
3418 else
3419 {
3420 /* Locate the previous node in the alias chain. */
3421 PPGMPHYS2VIRTHANDLER pPrev = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGet(&pPGM->CTXSUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key);
3422#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
3423 AssertReleaseMsg(pPrev != pPhys2Virt,
3424 ("pPhys2Virt=%p:{.Core.Key=%VGp, .Core.KeyLast=%VGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} pPrev=%p\n",
3425 pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias, pPrev));
3426#endif
3427 for (;;)
3428 {
3429 PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPrev + (pPrev->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
3430 if (pNext == pPhys2Virt)
3431 {
3432 /* unlink. */
3433 LogFlow(("pgmHandlerVirtualClearPage: removed %p:{.offNextAlias=%#RX32} from alias chain. prev %p:{.offNextAlias=%#RX32} [%VGp-%VGp]\n",
3434 pPhys2Virt, pPhys2Virt->offNextAlias, pPrev, pPrev->offNextAlias, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast));
3435 if (!(pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK))
3436 pPrev->offNextAlias &= ~PGMPHYS2VIRTHANDLER_OFF_MASK;
3437 else
3438 {
3439 PPGMPHYS2VIRTHANDLER pNewNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
3440 pPrev->offNextAlias = ((intptr_t)pNewNext - (intptr_t)pPrev)
3441 | (pPrev->offNextAlias & ~PGMPHYS2VIRTHANDLER_OFF_MASK);
3442 }
3443 break;
3444 }
3445
3446 /* next */
3447 if (pNext == pPrev)
3448 {
3449#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
3450 AssertReleaseMsg(pNext != pPrev,
3451 ("pPhys2Virt=%p:{.Core.Key=%VGp, .Core.KeyLast=%VGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} pPrev=%p\n",
3452 pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias, pPrev));
3453#endif
3454 break;
3455 }
3456 pPrev = pNext;
3457 }
3458 }
3459 Log2(("PHYS2VIRT: Removing %VGp-%VGp %#RX32 %s\n",
3460 pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offNextAlias, HCSTRING(pCur->pszDesc)));
3461 pPhys2Virt->offNextAlias = 0;
3462 pPhys2Virt->Core.KeyLast = NIL_RTGCPHYS; /* require reinsert */
3463
3464 /*
3465 * Clear the ram flags for this page.
3466 */
3467 PPGMPAGE pPage = pgmPhysGetPage(pPGM, pPhys2Virt->Core.Key);
3468 AssertReturnVoid(pPage);
3469 PGM_PAGE_SET_HNDL_VIRT_STATE(pPage, PGM_PAGE_HNDL_VIRT_STATE_NONE);
3470}
3471
3472
3473/**
3474 * Internal worker for finding a 'in-use' shadow page give by it's physical address.
3475 *
3476 * @returns Pointer to the shadow page structure.
3477 * @param pPool The pool.
3478 * @param HCPhys The HC physical address of the shadow page.
3479 */
3480DECLINLINE(PPGMPOOLPAGE) pgmPoolGetPage(PPGMPOOL pPool, RTHCPHYS HCPhys)
3481{
3482 /*
3483 * Look up the page.
3484 */
3485 PPGMPOOLPAGE pPage = (PPGMPOOLPAGE)RTAvloHCPhysGet(&pPool->HCPhysTree, HCPhys & X86_PTE_PAE_PG_MASK);
3486 AssertFatalMsg(pPage && pPage->enmKind != PGMPOOLKIND_FREE, ("HCPhys=%VHp pPage=%p type=%d\n", HCPhys, pPage, (pPage) ? pPage->enmKind : 0));
3487 return pPage;
3488}
3489
3490
3491/**
3492 * Internal worker for finding a 'in-use' shadow page give by it's physical address.
3493 *
3494 * @returns Pointer to the shadow page structure.
3495 * @param pPool The pool.
3496 * @param idx The pool page index.
3497 */
3498DECLINLINE(PPGMPOOLPAGE) pgmPoolGetPageByIdx(PPGMPOOL pPool, unsigned idx)
3499{
3500 AssertFatalMsg(idx >= PGMPOOL_IDX_FIRST && idx < pPool->cCurPages, ("idx=%d\n", idx));
3501 return &pPool->aPages[idx];
3502}
3503
3504
3505#ifdef PGMPOOL_WITH_GCPHYS_TRACKING
3506/**
3507 * Clear references to guest physical memory.
3508 *
3509 * @param pPool The pool.
3510 * @param pPoolPage The pool page.
3511 * @param pPhysPage The physical guest page tracking structure.
3512 */
3513DECLINLINE(void) pgmTrackDerefGCPhys(PPGMPOOL pPool, PPGMPOOLPAGE pPoolPage, PPGMPAGE pPhysPage)
3514{
3515 /*
3516 * Just deal with the simple case here.
3517 */
3518#ifdef LOG_ENABLED
3519 const RTHCPHYS HCPhysOrg = pPhysPage->HCPhys; /** @todo PAGE FLAGS */
3520#endif
3521 const unsigned cRefs = pPhysPage->HCPhys >> MM_RAM_FLAGS_CREFS_SHIFT; /** @todo PAGE FLAGS */
3522 if (cRefs == 1)
3523 {
3524 Assert(pPoolPage->idx == ((pPhysPage->HCPhys >> MM_RAM_FLAGS_IDX_SHIFT) & MM_RAM_FLAGS_IDX_MASK));
3525 pPhysPage->HCPhys = pPhysPage->HCPhys & MM_RAM_FLAGS_NO_REFS_MASK;
3526 }
3527 else
3528 pgmPoolTrackPhysExtDerefGCPhys(pPool, pPoolPage, pPhysPage);
3529 LogFlow(("pgmTrackDerefGCPhys: HCPhys=%RHp -> %RHp\n", HCPhysOrg, pPhysPage->HCPhys));
3530}
3531#endif
3532
3533
3534#ifdef PGMPOOL_WITH_CACHE
3535/**
3536 * Moves the page to the head of the age list.
3537 *
3538 * This is done when the cached page is used in one way or another.
3539 *
3540 * @param pPool The pool.
3541 * @param pPage The cached page.
3542 * @todo inline in PGMInternal.h!
3543 */
3544DECLINLINE(void) pgmPoolCacheUsed(PPGMPOOL pPool, PPGMPOOLPAGE pPage)
3545{
3546 /*
3547 * Move to the head of the age list.
3548 */
3549 if (pPage->iAgePrev != NIL_PGMPOOL_IDX)
3550 {
3551 /* unlink */
3552 pPool->aPages[pPage->iAgePrev].iAgeNext = pPage->iAgeNext;
3553 if (pPage->iAgeNext != NIL_PGMPOOL_IDX)
3554 pPool->aPages[pPage->iAgeNext].iAgePrev = pPage->iAgePrev;
3555 else
3556 pPool->iAgeTail = pPage->iAgePrev;
3557
3558 /* insert at head */
3559 pPage->iAgePrev = NIL_PGMPOOL_IDX;
3560 pPage->iAgeNext = pPool->iAgeHead;
3561 Assert(pPage->iAgeNext != NIL_PGMPOOL_IDX); /* we would've already been head then */
3562 pPool->iAgeHead = pPage->idx;
3563 pPool->aPages[pPage->iAgeNext].iAgePrev = pPage->idx;
3564 }
3565}
3566#endif /* PGMPOOL_WITH_CACHE */
3567
3568/**
3569 * Tells if mappings are to be put into the shadow page table or not
3570 *
3571 * @returns boolean result
3572 * @param pVM VM handle.
3573 */
3574
3575DECLINLINE(bool) pgmMapAreMappingsEnabled(PPGM pPGM)
3576{
3577 return !pPGM->fDisableMappings;
3578}
3579
3580/** @} */
3581
3582#endif
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