VirtualBox

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

Last change on this file since 2705 was 2679, checked in by vboxsync, 18 years ago

fixed alignment issue, move the code to the right place and fixed the style.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 111.3 KB
Line 
1/* $Id: PGMInternal.h 2679 2007-05-16 19:11:24Z vboxsync $ */
2/** @file
3 * PGM - Internal header file.
4 */
5
6/*
7 * Copyright (C) 2006 InnoTek Systemberatung 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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22#ifndef __PGMInternal_h__
23#define __PGMInternal_h__
24
25#include <VBox/cdefs.h>
26#include <VBox/types.h>
27#include <VBox/err.h>
28#include <VBox/stam.h>
29#include <VBox/param.h>
30#include <VBox/vmm.h>
31#include <VBox/mm.h>
32#include <VBox/pdm.h>
33#include <iprt/avl.h>
34#include <iprt/assert.h>
35#include <iprt/critsect.h>
36
37#if !defined(IN_PGM_R3) && !defined(IN_PGM_R0) && !defined(IN_PGM_GC)
38# error "Not in PGM! This is an internal header!"
39#endif
40
41
42/** @defgroup grp_pgm_int Internals
43 * @ingroup grp_pgm
44 * @internal
45 * @{
46 */
47
48
49/** @name PGM Compile Time Config
50 * @{
51 */
52
53/**
54 * Solve page is out of sync issues inside Guest Context (in PGMGC.cpp).
55 * Comment it if it will break something.
56 */
57#define PGM_OUT_OF_SYNC_IN_GC
58
59/**
60 * Virtualize the dirty bit
61 * This also makes a half-hearted attempt at the accessed bit. For full
62 * accessed bit virtualization define PGM_SYNC_ACCESSED_BIT.
63 */
64#define PGM_SYNC_DIRTY_BIT
65
66/**
67 * Fully virtualize the accessed bit.
68 * @remark This requires SYNC_DIRTY_ACCESSED_BITS to be defined!
69 */
70#define PGM_SYNC_ACCESSED_BIT
71
72/**
73 * Check and skip global PDEs for non-global flushes
74 */
75#define PGM_SKIP_GLOBAL_PAGEDIRS_ON_NONGLOBAL_FLUSH
76
77/**
78 * Sync N pages instead of a whole page table
79 */
80#define PGM_SYNC_N_PAGES
81
82/**
83 * Number of pages to sync during a page fault
84 *
85 * When PGMPOOL_WITH_GCPHYS_TRACKING is enabled using high values here
86 * causes a lot of unnecessary extents and also is slower than taking more \#PFs.
87 */
88#define PGM_SYNC_NR_PAGES 8
89
90/**
91 * Number of PGMPhysRead/Write cache entries (must be <= sizeof(uint64_t))
92 */
93#define PGM_MAX_PHYSCACHE_ENTRIES 64
94#define PGM_MAX_PHYSCACHE_ENTRIES_MASK (PGM_MAX_PHYSCACHE_ENTRIES-1)
95
96/**
97 * Enable caching of PGMR3PhysRead/WriteByte/Word/Dword
98 */
99#define PGM_PHYSMEMACCESS_CACHING
100
101/*
102 * Assert Sanity.
103 */
104#if defined(PGM_SYNC_ACCESSED_BIT) && !defined(PGM_SYNC_DIRTY_BIT)
105# error "PGM_SYNC_ACCESSED_BIT requires PGM_SYNC_DIRTY_BIT!"
106#endif
107
108/** @def PGMPOOL_WITH_CACHE
109 * Enable agressive caching using the page pool.
110 *
111 * This requires PGMPOOL_WITH_USER_TRACKING and PGMPOOL_WITH_MONITORING.
112 */
113#define PGMPOOL_WITH_CACHE
114
115/** @def PGMPOOL_WITH_MIXED_PT_CR3
116 * When defined, we'll deal with 'uncachable' pages.
117 */
118#ifdef PGMPOOL_WITH_CACHE
119# define PGMPOOL_WITH_MIXED_PT_CR3
120#endif
121
122/** @def PGMPOOL_WITH_MONITORING
123 * Monitor the guest pages which are shadowed.
124 * When this is enabled, PGMPOOL_WITH_CACHE or PGMPOOL_WITH_GCPHYS_TRACKING must
125 * be enabled as well.
126 * @remark doesn't really work without caching now. (Mixed PT/CR3 change.)
127 */
128#ifdef PGMPOOL_WITH_CACHE
129# define PGMPOOL_WITH_MONITORING
130#endif
131
132/** @def PGMPOOL_WITH_GCPHYS_TRACKING
133 * Tracking the of shadow pages mapping guest physical pages.
134 *
135 * This is very expensive, the current cache prototype is trying to figure out
136 * whether it will be acceptable with an agressive caching policy.
137 */
138#if defined(PGMPOOL_WITH_CACHE) || defined(PGMPOOL_WITH_MONITORING)
139# define PGMPOOL_WITH_GCPHYS_TRACKING
140#endif
141
142/** @def PGMPOOL_WITH_USER_TRACKING
143 * Tracking users of shadow pages. This is required for the linking of shadow page
144 * tables and physical guest addresses.
145 */
146#if defined(PGMPOOL_WITH_GCPHYS_TRACKING) || defined(PGMPOOL_WITH_CACHE) || defined(PGMPOOL_WITH_MONITORING)
147# define PGMPOOL_WITH_USER_TRACKING
148#endif
149
150/** @def PGMPOOL_CFG_MAX_GROW
151 * The maximum number of pages to add to the pool in one go.
152 */
153#define PGMPOOL_CFG_MAX_GROW (_256K >> PAGE_SHIFT)
154
155/** @def VBOX_STRICT_PGM_HANDLER_VIRTUAL
156 * Enables some extra assertions for virtual handlers (mainly phys2virt related).
157 */
158#ifdef VBOX_STRICT
159# define VBOX_STRICT_PGM_HANDLER_VIRTUAL
160#endif
161/** @} */
162
163
164/** @name PDPTR and PML4 flags.
165 * These are placed in the three bits available for system programs in
166 * the PDPTR and PML4 entries.
167 * @{ */
168/** The entry is a permanent one and it's must always be present.
169 * Never free such an entry. */
170#define PGM_PLXFLAGS_PERMANENT BIT64(10)
171/** @} */
172
173/** @name Page directory flags.
174 * These are placed in the three bits available for system programs in
175 * the page directory entries.
176 * @{ */
177/** Mapping (hypervisor allocated pagetable). */
178#define PGM_PDFLAGS_MAPPING BIT64(10)
179/** Made read-only to facilitate dirty bit tracking. */
180#define PGM_PDFLAGS_TRACK_DIRTY BIT64(11)
181/** @} */
182
183/** @name Page flags.
184 * These are placed in the three bits available for system programs in
185 * the page entries.
186 * @{ */
187/** Made read-only to facilitate dirty bit tracking. */
188#define PGM_PTFLAGS_TRACK_DIRTY BIT64(9)
189
190#ifndef PGM_PTFLAGS_CSAM_VALIDATED
191/** Scanned and approved by CSAM (tm).
192 * NOTE: Must be identical to the one defined in CSAMInternal.h!!
193 * @todo Move PGM_PTFLAGS_* and PGM_PDFLAGS_* to VBox/pgm.h. */
194#define PGM_PTFLAGS_CSAM_VALIDATED BIT64(11)
195#endif
196/** @} */
197
198/** @name Defines used to indicate the shadow and guest paging in the templates.
199 * @{ */
200#define PGM_TYPE_REAL 1
201#define PGM_TYPE_PROT 2
202#define PGM_TYPE_32BIT 3
203#define PGM_TYPE_PAE 4
204#define PGM_TYPE_AMD64 5
205/** @} */
206
207/** Macro for checking if the guest is using paging.
208 * @param uType PGM_TYPE_*
209 * @remark ASSUMES certain order of the PGM_TYPE_* values.
210 */
211#define PGM_WITH_PAGING(uType) ((uType) >= PGM_TYPE_32BIT)
212
213
214/** @def PGM_HCPHYS_2_PTR
215 * Maps a HC physical page pool address to a virtual address.
216 *
217 * @returns VBox status code.
218 * @param pVM The VM handle.
219 * @param HCPhys The HC physical address to map to a virtual one.
220 * @param ppv Where to store the virtual address. No need to cast this.
221 *
222 * @remark In GC this uses PGMGCDynMapHCPage(), so it will consume of the
223 * small page window employeed by that function. Be careful.
224 * @remark There is no need to assert on the result.
225 */
226#ifdef IN_GC
227# define PGM_HCPHYS_2_PTR(pVM, HCPhys, ppv) PGMGCDynMapHCPage(pVM, HCPhys, (void **)(ppv))
228#else
229# define PGM_HCPHYS_2_PTR(pVM, HCPhys, ppv) MMPagePhys2PageEx(pVM, HCPhys, (void **)(ppv))
230#endif
231
232/** @def PGM_GCPHYS_2_PTR
233 * Maps a GC physical page address to a virtual address.
234 *
235 * @returns VBox status code.
236 * @param pVM The VM handle.
237 * @param GCPhys The GC physical address to map to a virtual one.
238 * @param ppv Where to store the virtual address. No need to cast this.
239 *
240 * @remark In GC this uses PGMGCDynMapGCPage(), so it will consume of the
241 * small page window employeed by that function. Be careful.
242 * @remark There is no need to assert on the result.
243 */
244#ifdef IN_GC
245# define PGM_GCPHYS_2_PTR(pVM, GCPhys, ppv) PGMGCDynMapGCPage(pVM, GCPhys, (void **)(ppv))
246#else
247# define PGM_GCPHYS_2_PTR(pVM, GCPhys, ppv) PGMPhysGCPhys2HCPtr(pVM, GCPhys, 1 /* one page only */, (void **)(ppv)) /** @todo this isn't asserting, use PGMRamGCPhys2HCPtr! */
248#endif
249
250/** @def PGM_GCPHYS_2_PTR_EX
251 * Maps a unaligned GC physical page address to a virtual address.
252 *
253 * @returns VBox status code.
254 * @param pVM The VM handle.
255 * @param GCPhys The GC physical address to map to a virtual one.
256 * @param ppv Where to store the virtual address. No need to cast this.
257 *
258 * @remark In GC this uses PGMGCDynMapGCPage(), so it will consume of the
259 * small page window employeed by that function. Be careful.
260 * @remark There is no need to assert on the result.
261 */
262#ifdef IN_GC
263# define PGM_GCPHYS_2_PTR_EX(pVM, GCPhys, ppv) PGMGCDynMapGCPageEx(pVM, GCPhys, (void **)(ppv))
264#else
265# 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! */
266#endif
267
268/** @def PGM_INVL_PG
269 * Invalidates a page when in GC does nothing in HC.
270 *
271 * @param GCVirt The virtual address of the page to invalidate.
272 */
273#ifdef IN_GC
274# define PGM_INVL_PG(GCVirt) ASMInvalidatePage((void *)(GCVirt))
275#else
276# define PGM_INVL_PG(GCVirt) ((void)0)
277#endif
278
279/** @def PGM_INVL_BIG_PG
280 * Invalidates a 4MB page directory entry when in GC does nothing in HC.
281 *
282 * @param GCVirt The virtual address within the page directory to invalidate.
283 */
284#ifdef IN_GC
285# define PGM_INVL_BIG_PG(GCVirt) ASMReloadCR3()
286#else
287# define PGM_INVL_BIG_PG(GCVirt) ((void)0)
288#endif
289
290/** @def PGM_INVL_GUEST_TLBS()
291 * Invalidates all guest TLBs.
292 */
293#ifdef IN_GC
294# define PGM_INVL_GUEST_TLBS() ASMReloadCR3()
295#else
296# define PGM_INVL_GUEST_TLBS() ((void)0)
297#endif
298
299
300/**
301 * Structure for tracking GC Mappings.
302 *
303 * This structure is used by linked list in both GC and HC.
304 */
305typedef struct PGMMAPPING
306{
307 /** Pointer to next entry. */
308 R3PTRTYPE(struct PGMMAPPING *) pNextR3;
309 /** Pointer to next entry. */
310 R0PTRTYPE(struct PGMMAPPING *) pNextR0;
311 /** Pointer to next entry. */
312 GCPTRTYPE(struct PGMMAPPING *) pNextGC;
313 /** Start Virtual address. */
314 RTGCUINTPTR GCPtr;
315 /** Last Virtual address (inclusive). */
316 RTGCUINTPTR GCPtrLast;
317 /** Range size (bytes). */
318 RTGCUINTPTR cb;
319 /** Pointer to relocation callback function. */
320 R3PTRTYPE(PFNPGMRELOCATE) pfnRelocate;
321 /** User argument to the callback. */
322 R3PTRTYPE(void *) pvUser;
323 /** Mapping description / name. For easing debugging. */
324 R3PTRTYPE(const char *) pszDesc;
325 /** Number of page tables. */
326 RTUINT cPTs;
327#if HC_ARCH_BITS != GC_ARCH_BITS
328 RTUINT uPadding0; /**< Alignment padding. */
329#endif
330 /** Array of page table mapping data. Each entry
331 * describes one page table. The array can be longer
332 * than the declared length.
333 */
334 struct
335 {
336 /** The HC physical address of the page table. */
337 RTHCPHYS HCPhysPT;
338 /** The HC physical address of the first PAE page table. */
339 RTHCPHYS HCPhysPaePT0;
340 /** The HC physical address of the second PAE page table. */
341 RTHCPHYS HCPhysPaePT1;
342 /** The HC virtual address of the 32-bit page table. */
343 R3PTRTYPE(PVBOXPT) pPTR3;
344 /** The HC virtual address of the two PAE page table. (i.e 1024 entries instead of 512) */
345 R3PTRTYPE(PX86PTPAE) paPaePTsR3;
346 /** The GC virtual address of the 32-bit page table. */
347 GCPTRTYPE(PVBOXPT) pPTGC;
348 /** The GC virtual address of the two PAE page table. */
349 GCPTRTYPE(PX86PTPAE) paPaePTsGC;
350 /** The GC virtual address of the 32-bit page table. */
351 R0PTRTYPE(PVBOXPT) pPTR0;
352 /** The GC virtual address of the two PAE page table. */
353 R0PTRTYPE(PX86PTPAE) paPaePTsR0;
354 } aPTs[1];
355} PGMMAPPING;
356/** Pointer to structure for tracking GC Mappings. */
357typedef struct PGMMAPPING *PPGMMAPPING;
358
359
360/**
361 * Physical page access handler structure.
362 *
363 * This is used to keep track of physical address ranges
364 * which are being monitored in some kind of way.
365 */
366typedef struct PGMPHYSHANDLER
367{
368 AVLROGCPHYSNODECORE Core;
369 /** Alignment padding. */
370 uint32_t u32Padding;
371 /** Access type. */
372 PGMPHYSHANDLERTYPE enmType;
373 /** Number of pages to update. */
374 uint32_t cPages;
375 /** Pointer to R3 callback function. */
376 R3PTRTYPE(PFNPGMR3PHYSHANDLER) pfnHandlerR3;
377 /** User argument for R3 handlers. */
378 R3PTRTYPE(void *) pvUserR3;
379 /** Pointer to R0 callback function. */
380 R0PTRTYPE(PFNPGMR0PHYSHANDLER) pfnHandlerR0;
381 /** User argument for R0 handlers. */
382 R0PTRTYPE(void *) pvUserR0;
383 /** Pointer to GC callback function. */
384 GCPTRTYPE(PFNPGMGCPHYSHANDLER) pfnHandlerGC;
385 /** User argument for GC handlers. */
386 GCPTRTYPE(void *) pvUserGC;
387 /** Description / Name. For easing debugging. */
388 R3PTRTYPE(const char *) pszDesc;
389#ifdef VBOX_WITH_STATISTICS
390 /** Profiling of this handler. */
391 STAMPROFILE Stat;
392#endif
393} PGMPHYSHANDLER;
394/** Pointer to a physical page access handler structure. */
395typedef PGMPHYSHANDLER *PPGMPHYSHANDLER;
396
397
398/**
399 * Cache node for the physical addresses covered by a virtual handler.
400 */
401typedef struct PGMPHYS2VIRTHANDLER
402{
403 /** Core node for the tree based on physical ranges. */
404 AVLROGCPHYSNODECORE Core;
405 /** Offset from this struct to the PGMVIRTHANDLER structure. */
406 RTGCINTPTR offVirtHandler;
407 /** Offset of the next alias relativer to this one.
408 * Bit 0 is used for indicating whether we're in the tree.
409 * Bit 1 is used for indicating that we're the head node.
410 */
411 int32_t offNextAlias;
412} PGMPHYS2VIRTHANDLER;
413/** Pointer to a phys to virtual handler structure. */
414typedef PGMPHYS2VIRTHANDLER *PPGMPHYS2VIRTHANDLER;
415
416/** The bit in PGMPHYS2VIRTHANDLER::offNextAlias used to indicate that the
417 * node is in the tree. */
418#define PGMPHYS2VIRTHANDLER_IN_TREE BIT(0)
419/** The bit in PGMPHYS2VIRTHANDLER::offNextAlias used to indicate that the
420 * node is in the head of an alias chain.
421 * The PGMPHYS2VIRTHANDLER_IN_TREE is always set if this bit is set. */
422#define PGMPHYS2VIRTHANDLER_IS_HEAD BIT(1)
423/** The mask to apply to PGMPHYS2VIRTHANDLER::offNextAlias to get the offset. */
424#define PGMPHYS2VIRTHANDLER_OFF_MASK (~(int32_t)3)
425
426
427/**
428 * Virtual page access handler structure.
429 *
430 * This is used to keep track of virtual address ranges
431 * which are being monitored in some kind of way.
432 */
433typedef struct PGMVIRTHANDLER
434{
435 /** Core node for the tree based on virtual ranges. */
436 AVLROGCPTRNODECORE Core;
437 /** Number of cache pages. */
438 uint32_t u32Padding;
439 /** Access type. */
440 PGMVIRTHANDLERTYPE enmType;
441 /** Number of cache pages. */
442 uint32_t cPages;
443
444/** @todo The next two members are redundant. It adds some readability though. */
445 /** Start of the range. */
446 RTGCPTR GCPtr;
447 /** End of the range (exclusive). */
448 RTGCPTR GCPtrLast;
449 /** Size of the range (in bytes). */
450 RTGCUINTPTR cb;
451 /** Pointer to the GC callback function. */
452 GCPTRTYPE(PFNPGMGCVIRTHANDLER) pfnHandlerGC;
453 /** Pointer to the HC callback function for invalidation. */
454 HCPTRTYPE(PFNPGMHCVIRTINVALIDATE) pfnInvalidateHC;
455 /** Pointer to the HC callback function. */
456 HCPTRTYPE(PFNPGMHCVIRTHANDLER) pfnHandlerHC;
457 /** Description / Name. For easing debugging. */
458 HCPTRTYPE(const char *) pszDesc;
459#ifdef VBOX_WITH_STATISTICS
460 /** Profiling of this handler. */
461 STAMPROFILE Stat;
462#endif
463 /** Array of cached physical addresses for the monitored ranged. */
464 PGMPHYS2VIRTHANDLER aPhysToVirt[HC_ARCH_BITS == 32 ? 1 : 2];
465} PGMVIRTHANDLER;
466/** Pointer to a virtual page access handler structure. */
467typedef PGMVIRTHANDLER *PPGMVIRTHANDLER;
468
469
470/**
471 * Ram range for GC Phys to HC Phys conversion.
472 *
473 * Can be used for HC Virt to GC Phys and HC Virt to HC Phys
474 * conversions too, but we'll let MM handle that for now.
475 *
476 * This structure is used by linked lists in both GC and HC.
477 */
478typedef struct PGMRAMRANGE
479{
480 /** Pointer to the next RAM range - for HC. */
481 HCPTRTYPE(struct PGMRAMRANGE *) pNextHC;
482 /** Pointer to the next RAM range - for GC. */
483 GCPTRTYPE(struct PGMRAMRANGE *) pNextGC;
484 /** Start of the range. Page aligned. */
485 RTGCPHYS GCPhys;
486 /** Last address in the range (inclusive). Page aligned (-1). */
487 RTGCPHYS GCPhysLast;
488 /** Size of the range. (Page aligned of course). */
489 RTGCPHYS cb;
490 /** MM_RAM_* flags */
491 uint32_t fFlags;
492
493 /** HC virtual lookup ranges for chunks. Currently only used with MM_RAM_FLAGS_DYNAMIC_ALLOC ranges. */
494 GCPTRTYPE(PRTHCPTR) pavHCChunkGC;
495 /** HC virtual lookup ranges for chunks. Currently only used with MM_RAM_FLAGS_DYNAMIC_ALLOC ranges. */
496 HCPTRTYPE(PRTHCPTR) pavHCChunkHC;
497
498 /** Start of the HC mapping of the range.
499 * For pure MMIO and dynamically allocated ranges this is NULL, while for all ranges this is a valid pointer. */
500 HCPTRTYPE(void *) pvHC;
501
502 /** Array of the flags and HC physical addresses corresponding to the range.
503 * The index is the page number in the range. The size is cb >> PAGE_SHIFT.
504 *
505 * The 12 lower bits of the physical address are flags and must be masked
506 * off to get the correct physical address.
507 *
508 * For pure MMIO ranges only the flags are valid.
509 */
510 RTHCPHYS aHCPhys[1];
511} PGMRAMRANGE;
512/** Pointer to Ram range for GC Phys to HC Phys conversion. */
513typedef PGMRAMRANGE *PPGMRAMRANGE;
514
515/** Return hc ptr corresponding to the ram range and physical offset */
516#define PGMRAMRANGE_GETHCPTR(pRam, off) \
517 (pRam->fFlags & MM_RAM_FLAGS_DYNAMIC_ALLOC) ? (RTHCPTR)((RTHCUINTPTR)CTXSUFF(pRam->pavHCChunk)[(off >> PGM_DYNAMIC_CHUNK_SHIFT)] + (off & PGM_DYNAMIC_CHUNK_OFFSET_MASK)) \
518 : (RTHCPTR)((RTHCUINTPTR)pRam->pvHC + off);
519
520/** @todo r=bird: fix typename. */
521/**
522 * PGMPhysRead/Write cache entry
523 */
524typedef struct PGMPHYSCACHE_ENTRY
525{
526 /** HC pointer to physical page */
527 R3PTRTYPE(uint8_t *) pbHC;
528 /** GC Physical address for cache entry */
529 RTGCPHYS GCPhys;
530#if HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32
531 RTGCPHYS u32Padding0; /**< alignment padding. */
532#endif
533} PGMPHYSCACHE_ENTRY;
534
535/**
536 * PGMPhysRead/Write cache to reduce REM memory access overhead
537 */
538typedef struct PGMPHYSCACHE
539{
540 /** Bitmap of valid cache entries */
541 uint64_t aEntries;
542 /** Cache entries */
543 PGMPHYSCACHE_ENTRY Entry[PGM_MAX_PHYSCACHE_ENTRIES];
544} PGMPHYSCACHE;
545
546
547/** @name PGM Pool Indexes.
548 * Aka. the unique shadow page identifier.
549 * @{ */
550/** NIL page pool IDX. */
551#define NIL_PGMPOOL_IDX 0
552/** The first normal index. */
553#define PGMPOOL_IDX_FIRST_SPECIAL 1
554/** Page directory (32-bit root). */
555#define PGMPOOL_IDX_PD 1
556/** The extended PAE page directory (2048 entries, works as root currently). */
557#define PGMPOOL_IDX_PAE_PD 2
558/** Page Directory Pointer Table (PAE root, not currently used). */
559#define PGMPOOL_IDX_PDPTR 3
560/** Page Map Level-4 (64-bit root). */
561#define PGMPOOL_IDX_PML4 4
562/** The first normal index. */
563#define PGMPOOL_IDX_FIRST 5
564/** The last valid index. (inclusive, 14 bits) */
565#define PGMPOOL_IDX_LAST 0x3fff
566/** @} */
567
568/** The NIL index for the parent chain. */
569#define NIL_PGMPOOL_USER_INDEX ((uint16_t)0xffff)
570
571/**
572 * Node in the chain linking a shadowed page to it's parent (user).
573 */
574#pragma pack(1)
575typedef struct PGMPOOLUSER
576{
577 /** The index to the next item in the chain. NIL_PGMPOOL_USER_INDEX is no next. */
578 uint16_t iNext;
579 /** The user page index. */
580 uint16_t iUser;
581 /** Index into the user table. */
582 uint16_t iUserTable;
583} PGMPOOLUSER, *PPGMPOOLUSER;
584typedef const PGMPOOLUSER *PCPGMPOOLUSER;
585#pragma pack()
586
587
588/** The NIL index for the phys ext chain. */
589#define NIL_PGMPOOL_PHYSEXT_INDEX ((uint16_t)0xffff)
590
591/**
592 * Node in the chain of physical cross reference extents.
593 */
594#pragma pack(1)
595typedef struct PGMPOOLPHYSEXT
596{
597 /** The index to the next item in the chain. NIL_PGMPOOL_PHYSEXT_INDEX is no next. */
598 uint16_t iNext;
599 /** The user page index. */
600 uint16_t aidx[3];
601} PGMPOOLPHYSEXT, *PPGMPOOLPHYSEXT;
602typedef const PGMPOOLPHYSEXT *PCPGMPOOLPHYSEXT;
603#pragma pack()
604
605
606/**
607 * The kind of page that's being shadowed.
608 */
609typedef enum PGMPOOLKIND
610{
611 /** The virtual invalid 0 entry. */
612 PGMPOOLKIND_INVALID = 0,
613 /** The entry is free (=unused). */
614 PGMPOOLKIND_FREE,
615
616 /** Shw: 32-bit page table; Gst: no paging */
617 PGMPOOLKIND_32BIT_PT_FOR_PHYS,
618 /** Shw: 32-bit page table; Gst: 32-bit page table. */
619 PGMPOOLKIND_32BIT_PT_FOR_32BIT_PT,
620 /** Shw: 32-bit page table; Gst: 4MB page. */
621 PGMPOOLKIND_32BIT_PT_FOR_32BIT_4MB,
622 /** Shw: PAE page table; Gst: no paging */
623 PGMPOOLKIND_PAE_PT_FOR_PHYS,
624 /** Shw: PAE page table; Gst: 32-bit page table. */
625 PGMPOOLKIND_PAE_PT_FOR_32BIT_PT,
626 /** Shw: PAE page table; Gst: Half of a 4MB page. */
627 PGMPOOLKIND_PAE_PT_FOR_32BIT_4MB,
628 /** Shw: PAE page table; Gst: PAE page table. */
629 PGMPOOLKIND_PAE_PT_FOR_PAE_PT,
630 /** Shw: PAE page table; Gst: 2MB page. */
631 PGMPOOLKIND_PAE_PT_FOR_PAE_2MB,
632
633 /** Shw: PAE page directory; Gst: 32-bit page directory. */
634 PGMPOOLKIND_PAE_PD_FOR_32BIT_PD,
635 /** Shw: PAE page directory; Gst: PAE page directory. */
636 PGMPOOLKIND_PAE_PD_FOR_PAE_PD,
637
638 /** Shw: 64-bit page directory pointer table; Gst: 64-bit page directory pointer table. */
639 PGMPOOLKIND_64BIT_PDPTR_FOR_64BIT_PDPTR,
640
641 /** Shw: Root 32-bit page directory. */
642 PGMPOOLKIND_ROOT_32BIT_PD,
643 /** Shw: Root PAE page directory */
644 PGMPOOLKIND_ROOT_PAE_PD,
645 /** Shw: Root PAE page directory pointer table (legacy, 4 entries). */
646 PGMPOOLKIND_ROOT_PDPTR,
647 /** Shw: Root page map level-4 table. */
648 PGMPOOLKIND_ROOT_PML4,
649
650 /** The last valid entry. */
651 PGMPOOLKIND_LAST = PGMPOOLKIND_ROOT_PML4
652} PGMPOOLKIND;
653
654
655/**
656 * The tracking data for a page in the pool.
657 */
658typedef struct PGMPOOLPAGE
659{
660 /** AVL node code with the (HC) physical address of this page. */
661 AVLOHCPHYSNODECORE Core;
662 /** Pointer to the HC mapping of the page. */
663 HCPTRTYPE(void *) pvPageHC;
664 /** The guest physical address. */
665 RTGCPHYS GCPhys;
666 /** The kind of page we're shadowing. (This is really a PGMPOOLKIND enum.) */
667 uint8_t enmKind;
668 uint8_t bPadding;
669 /** The index of this page. */
670 uint16_t idx;
671 /** The next entry in the list this page currently resides in.
672 * It's either in the free list or in the GCPhys hash. */
673 uint16_t iNext;
674#ifdef PGMPOOL_WITH_USER_TRACKING
675 /** Head of the user chain. NIL_PGMPOOL_USER_INDEX if not currently in use. */
676 uint16_t iUserHead;
677 /** The number of present entries. */
678 uint16_t cPresent;
679 /** The first entry in the table which is present. */
680 uint16_t iFirstPresent;
681#endif
682#ifdef PGMPOOL_WITH_MONITORING
683 /** The number of modifications to the monitored page. */
684 uint16_t cModifications;
685 /** The next modified page. NIL_PGMPOOL_IDX if tail. */
686 uint16_t iModifiedNext;
687 /** The previous modified page. NIL_PGMPOOL_IDX if head. */
688 uint16_t iModifiedPrev;
689 /** The next page sharing access handler. NIL_PGMPOOL_IDX if tail. */
690 uint16_t iMonitoredNext;
691 /** The previous page sharing access handler. NIL_PGMPOOL_IDX if head. */
692 uint16_t iMonitoredPrev;
693#endif
694#ifdef PGMPOOL_WITH_CACHE
695 /** The next page in the age list. */
696 uint16_t iAgeNext;
697 /** The previous page in the age list. */
698 uint16_t iAgePrev;
699/** @todo add more from PGMCache.h when merging with it. */
700#endif /* PGMPOOL_WITH_CACHE */
701 /** Used to indicate that the page is zeroed. */
702 bool fZeroed;
703 /** Used to indicate that a PT has non-global entries. */
704 bool fSeenNonGlobal;
705 /** Used to indicate that we're monitoring writes to the guest page. */
706 bool fMonitored;
707 /** Used to indicate that the page is in the cache (e.g. in the GCPhys hash).
708 * (All pages are in the age list.) */
709 bool fCached;
710 /** This is used by the R3 access handlers when invoked by an async thread.
711 * It's a hack required because of REMR3NotifyHandlerPhysicalDeregister. */
712 bool volatile fReusedFlushPending;
713 /** Used to indicate that the guest is mapping the page is also used as a CR3.
714 * In these cases the access handler acts differently and will check
715 * for mapping conflicts like the normal CR3 handler.
716 * @todo When we change the CR3 shadowing to use pool pages, this flag can be
717 * replaced by a list of pages which share access handler.
718 */
719 bool fCR3Mix;
720#if HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64
721 bool Alignment[4]; /**< Align the structure size on a 64-bit boundrary. */
722#endif
723} PGMPOOLPAGE, *PPGMPOOLPAGE, **PPPGMPOOLPAGE;
724
725
726#ifdef PGMPOOL_WITH_CACHE
727/** The hash table size. */
728# define PGMPOOL_HASH_SIZE 0x40
729/** The hash function. */
730# define PGMPOOL_HASH(GCPhys) ( ((GCPhys) >> PAGE_SHIFT) & (PGMPOOL_HASH_SIZE - 1) )
731#endif
732
733
734/**
735 * The shadow page pool instance data.
736 *
737 * It's all one big allocation made at init time, except for the
738 * pages that is. The user nodes follows immediatly after the
739 * page structures.
740 */
741typedef struct PGMPOOL
742{
743 /** The VM handle - HC Ptr. */
744 HCPTRTYPE(PVM) pVMHC;
745 /** The VM handle - GC Ptr. */
746 GCPTRTYPE(PVM) pVMGC;
747 /** The max pool size. This includes the special IDs. */
748 uint16_t cMaxPages;
749 /** The current pool size. */
750 uint16_t cCurPages;
751 /** The head of the free page list. */
752 uint16_t iFreeHead;
753 /* Padding. */
754 uint16_t u16Padding;
755#ifdef PGMPOOL_WITH_USER_TRACKING
756 /** Head of the chain of free user nodes. */
757 uint16_t iUserFreeHead;
758 /** The number of user nodes we've allocated. */
759 uint16_t cMaxUsers;
760 /** The number of present page table entries in the entire pool. */
761 uint32_t cPresent;
762 /** Pointer to the array of user nodes - GC pointer. */
763 GCPTRTYPE(PPGMPOOLUSER) paUsersGC;
764 /** Pointer to the array of user nodes - HC pointer. */
765 HCPTRTYPE(PPGMPOOLUSER) paUsersHC;
766#endif /* PGMPOOL_WITH_USER_TRACKING */
767#ifdef PGMPOOL_WITH_GCPHYS_TRACKING
768 /** Head of the chain of free phys ext nodes. */
769 uint16_t iPhysExtFreeHead;
770 /** The number of user nodes we've allocated. */
771 uint16_t cMaxPhysExts;
772 /** Pointer to the array of physical xref extent - GC pointer. */
773 GCPTRTYPE(PPGMPOOLPHYSEXT) paPhysExtsGC;
774 /** Pointer to the array of physical xref extent nodes - HC pointer. */
775 HCPTRTYPE(PPGMPOOLPHYSEXT) paPhysExtsHC;
776#endif /* PGMPOOL_WITH_GCPHYS_TRACKING */
777#ifdef PGMPOOL_WITH_CACHE
778 /** Hash table for GCPhys addresses. */
779 uint16_t aiHash[PGMPOOL_HASH_SIZE];
780 /** The head of the age list. */
781 uint16_t iAgeHead;
782 /** The tail of the age list. */
783 uint16_t iAgeTail;
784 /** Set if the cache is enabled. */
785 bool fCacheEnabled;
786#endif /* PGMPOOL_WITH_CACHE */
787#ifdef PGMPOOL_WITH_MONITORING
788 /** Head of the list of modified pages. */
789 uint16_t iModifiedHead;
790 /** The current number of modified pages. */
791 uint16_t cModifiedPages;
792 /** Access handler, GC. */
793 GCPTRTYPE(PFNPGMGCPHYSHANDLER) pfnAccessHandlerGC;
794 /** Access handler, R0. */
795 R0PTRTYPE(PFNPGMR0PHYSHANDLER) pfnAccessHandlerR0;
796 /** Access handler, R3. */
797 R3PTRTYPE(PFNPGMR3PHYSHANDLER) pfnAccessHandlerR3;
798 /** The access handler description (HC ptr). */
799 R3PTRTYPE(const char *) pszAccessHandler;
800#endif /* PGMPOOL_WITH_MONITORING */
801 /** The number of pages currently in use. */
802 uint16_t cUsedPages;
803#ifdef VBOX_WITH_STATISTICS
804 /** The high wather mark for cUsedPages. */
805 uint16_t cUsedPagesHigh;
806 uint32_t Alignment1; /**< Align the next member on a 64-bit boundrary. */
807 /** Profiling pgmPoolAlloc(). */
808 STAMPROFILEADV StatAlloc;
809 /** Profiling pgmPoolClearAll(). */
810 STAMPROFILE StatClearAll;
811 /** Profiling pgmPoolFlushAllInt(). */
812 STAMPROFILE StatFlushAllInt;
813 /** Profiling pgmPoolFlushPage(). */
814 STAMPROFILE StatFlushPage;
815 /** Profiling pgmPoolFree(). */
816 STAMPROFILE StatFree;
817 /** Profiling time spent zeroing pages. */
818 STAMPROFILE StatZeroPage;
819# ifdef PGMPOOL_WITH_USER_TRACKING
820 /** Profiling of pgmPoolTrackDeref. */
821 STAMPROFILE StatTrackDeref;
822 /** Profiling pgmTrackFlushGCPhysPT. */
823 STAMPROFILE StatTrackFlushGCPhysPT;
824 /** Profiling pgmTrackFlushGCPhysPTs. */
825 STAMPROFILE StatTrackFlushGCPhysPTs;
826 /** Profiling pgmTrackFlushGCPhysPTsSlow. */
827 STAMPROFILE StatTrackFlushGCPhysPTsSlow;
828 /** Number of times we've been out of user records. */
829 STAMCOUNTER StatTrackFreeUpOneUser;
830# endif
831# ifdef PGMPOOL_WITH_GCPHYS_TRACKING
832 /** Profiling deref activity related tracking GC physical pages. */
833 STAMPROFILE StatTrackDerefGCPhys;
834 /** Number of linear searches for a HCPhys in the ram ranges. */
835 STAMCOUNTER StatTrackLinearRamSearches;
836 /** The number of failing pgmPoolTrackPhysExtAlloc calls. */
837 STAMCOUNTER StamTrackPhysExtAllocFailures;
838# endif
839# ifdef PGMPOOL_WITH_MONITORING
840 /** Profiling the GC PT access handler. */
841 STAMPROFILE StatMonitorGC;
842 /** Times we've failed interpreting the instruction. */
843 STAMCOUNTER StatMonitorGCEmulateInstr;
844 /** Profiling the pgmPoolFlushPage calls made from the GC PT access handler. */
845 STAMPROFILE StatMonitorGCFlushPage;
846 /** Times we've detected fork(). */
847 STAMCOUNTER StatMonitorGCFork;
848 /** Profiling the GC access we've handled (except REP STOSD). */
849 STAMPROFILE StatMonitorGCHandled;
850 /** Times we've failed interpreting a patch code instruction. */
851 STAMCOUNTER StatMonitorGCIntrFailPatch1;
852 /** Times we've failed interpreting a patch code instruction during flushing. */
853 STAMCOUNTER StatMonitorGCIntrFailPatch2;
854 /** The number of times we've seen rep prefixes we can't handle. */
855 STAMCOUNTER StatMonitorGCRepPrefix;
856 /** Profiling the REP STOSD cases we've handled. */
857 STAMPROFILE StatMonitorGCRepStosd;
858
859 /** Profiling the HC PT access handler. */
860 STAMPROFILE StatMonitorHC;
861 /** Times we've failed interpreting the instruction. */
862 STAMCOUNTER StatMonitorHCEmulateInstr;
863 /** Profiling the pgmPoolFlushPage calls made from the HC PT access handler. */
864 STAMPROFILE StatMonitorHCFlushPage;
865 /** Times we've detected fork(). */
866 STAMCOUNTER StatMonitorHCFork;
867 /** Profiling the HC access we've handled (except REP STOSD). */
868 STAMPROFILE StatMonitorHCHandled;
869 /** The number of times we've seen rep prefixes we can't handle. */
870 STAMCOUNTER StatMonitorHCRepPrefix;
871 /** Profiling the REP STOSD cases we've handled. */
872 STAMPROFILE StatMonitorHCRepStosd;
873 /** The number of times we're called in an async thread an need to flush. */
874 STAMCOUNTER StatMonitorHCAsync;
875 /** The high wather mark for cModifiedPages. */
876 uint16_t cModifiedPagesHigh;
877 uint16_t Alignment2[3]; /**< Align the next member on a 64-bit boundrary. */
878# endif
879# ifdef PGMPOOL_WITH_CACHE
880 /** The number of cache hits. */
881 STAMCOUNTER StatCacheHits;
882 /** The number of cache misses. */
883 STAMCOUNTER StatCacheMisses;
884 /** The number of times we've got a conflict of 'kind' in the cache. */
885 STAMCOUNTER StatCacheKindMismatches;
886 /** Number of times we've been out of pages. */
887 STAMCOUNTER StatCacheFreeUpOne;
888 /** The number of cacheable allocations. */
889 STAMCOUNTER StatCacheCacheable;
890 /** The number of uncacheable allocations. */
891 STAMCOUNTER StatCacheUncacheable;
892# endif
893#elif HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32
894 uint32_t Alignment1; /**< Align the next member on a 64-bit boundrary. */
895#endif
896 /** The AVL tree for looking up a page by its HC physical address. */
897 AVLOHCPHYSTREE HCPhysTree;
898 uint32_t Alignment3; /**< Align the next member on a 64-bit boundrary. */
899 /** Array of pages. (cMaxPages in length)
900 * The Id is the index into thist array.
901 */
902 PGMPOOLPAGE aPages[PGMPOOL_IDX_FIRST];
903} PGMPOOL, *PPGMPOOL, **PPPGMPOOL;
904
905
906/** @def PGMPOOL_PAGE_2_PTR
907 * Maps a pool page pool into the current context.
908 *
909 * @returns VBox status code.
910 * @param pVM The VM handle.
911 * @param pPage The pool page.
912 *
913 * @remark In HC this uses PGMGCDynMapHCPage(), so it will consume of the
914 * small page window employeed by that function. Be careful.
915 * @remark There is no need to assert on the result.
916 */
917#ifdef IN_GC
918# define PGMPOOL_PAGE_2_PTR(pVM, pPage) pgmGCPoolMapPage((pVM), (pPage))
919#else
920# define PGMPOOL_PAGE_2_PTR(pVM, pPage) ((pPage)->pvPageHC)
921#endif
922
923
924/**
925 * Trees are using self relative offsets as pointers.
926 * So, all its data, including the root pointer, must be in the heap for HC and GC
927 * to have the same layout.
928 */
929typedef struct PGMTREES
930{
931 /** Physical access handlers (AVL range+offsetptr tree). */
932 AVLROGCPHYSTREE PhysHandlers;
933 /** Virtual access handlers (AVL range + GC ptr tree). */
934 AVLROGCPTRTREE VirtHandlers;
935 /** Virtual access handlers (Phys range AVL range + offsetptr tree). */
936 AVLROGCPHYSTREE PhysToVirtHandlers;
937 uint32_t auPadding[1];
938} PGMTREES;
939/** Pointer to PGM trees. */
940typedef PGMTREES *PPGMTREES;
941
942
943/** @name Paging mode macros
944 * @{ */
945#ifdef IN_GC
946# define PGM_CTX(a,b) a##GC##b
947# define PGM_CTX_STR(a,b) a "GC" b
948# define PGM_CTX_DECL(type) PGMGCDECL(type)
949#else
950# ifdef IN_RING3
951# define PGM_CTX(a,b) a##R3##b
952# define PGM_CTX_STR(a,b) a "R3" b
953# define PGM_CTX_DECL(type) DECLCALLBACK(type)
954# else
955# define PGM_CTX(a,b) a##R0##b
956# define PGM_CTX_STR(a,b) a "R0" b
957# define PGM_CTX_DECL(type) PGMDECL(type)
958# endif
959#endif
960
961#define PGM_GST_NAME_REAL(name) PGM_CTX(pgm,GstReal##name)
962#define PGM_GST_NAME_GC_REAL_STR(name) "pgmGCGstReal" #name
963#define PGM_GST_NAME_R0_REAL_STR(name) "pgmR0GstReal" #name
964#define PGM_GST_NAME_PROT(name) PGM_CTX(pgm,GstProt##name)
965#define PGM_GST_NAME_GC_PROT_STR(name) "pgmGCGstProt" #name
966#define PGM_GST_NAME_R0_PROT_STR(name) "pgmR0GstProt" #name
967#define PGM_GST_NAME_32BIT(name) PGM_CTX(pgm,Gst32Bit##name)
968#define PGM_GST_NAME_GC_32BIT_STR(name) "pgmGCGst32Bit" #name
969#define PGM_GST_NAME_R0_32BIT_STR(name) "pgmR0Gst32Bit" #name
970#define PGM_GST_NAME_PAE(name) PGM_CTX(pgm,GstPAE##name)
971#define PGM_GST_NAME_GC_PAE_STR(name) "pgmGCGstPAE" #name
972#define PGM_GST_NAME_R0_PAE_STR(name) "pgmR0GstPAE" #name
973#define PGM_GST_NAME_AMD64(name) PGM_CTX(pgm,GstAMD64##name)
974#define PGM_GST_NAME_GC_AMD64_STR(name) "pgmGCGstAMD64" #name
975#define PGM_GST_NAME_R0_AMD64_STR(name) "pgmR0GstAMD64" #name
976#define PGM_GST_PFN(name, pVM) ((pVM)->pgm.s.PGM_CTX(pfn,Gst##name))
977#define PGM_GST_DECL(type, name) PGM_CTX_DECL(type) PGM_GST_NAME(name)
978
979#define PGM_SHW_NAME_32BIT(name) PGM_CTX(pgm,Shw32Bit##name)
980#define PGM_SHW_NAME_GC_32BIT_STR(name) "pgmGCShw32Bit" #name
981#define PGM_SHW_NAME_R0_32BIT_STR(name) "pgmR0Shw32Bit" #name
982#define PGM_SHW_NAME_PAE(name) PGM_CTX(pgm,ShwPAE##name)
983#define PGM_SHW_NAME_GC_PAE_STR(name) "pgmGCShwPAE" #name
984#define PGM_SHW_NAME_R0_PAE_STR(name) "pgmR0ShwPAE" #name
985#define PGM_SHW_NAME_AMD64(name) PGM_CTX(pgm,ShwAMD64##name)
986#define PGM_SHW_NAME_GC_AMD64_STR(name) "pgmGCShwAMD64" #name
987#define PGM_SHW_NAME_R0_AMD64_STR(name) "pgmR0ShwAMD64" #name
988#define PGM_SHW_DECL(type, name) PGM_CTX_DECL(type) PGM_SHW_NAME(name)
989#define PGM_SHW_PFN(name, pVM) ((pVM)->pgm.s.PGM_CTX(pfn,Shw##name))
990
991/* Shw_Gst */
992#define PGM_BTH_NAME_32BIT_REAL(name) PGM_CTX(pgm,Bth32BitReal##name)
993#define PGM_BTH_NAME_32BIT_PROT(name) PGM_CTX(pgm,Bth32BitProt##name)
994#define PGM_BTH_NAME_32BIT_32BIT(name) PGM_CTX(pgm,Bth32Bit32Bit##name)
995#define PGM_BTH_NAME_PAE_REAL(name) PGM_CTX(pgm,BthPAEReal##name)
996#define PGM_BTH_NAME_PAE_PROT(name) PGM_CTX(pgm,BthPAEProt##name)
997#define PGM_BTH_NAME_PAE_32BIT(name) PGM_CTX(pgm,BthPAE32Bit##name)
998#define PGM_BTH_NAME_PAE_PAE(name) PGM_CTX(pgm,BthPAEPAE##name)
999#define PGM_BTH_NAME_AMD64_REAL(name) PGM_CTX(pgm,BthAMD64Real##name)
1000#define PGM_BTH_NAME_AMD64_PROT(name) PGM_CTX(pgm,BthAMD64Prot##name)
1001#define PGM_BTH_NAME_AMD64_AMD64(name) PGM_CTX(pgm,BthAMD64AMD64##name)
1002#define PGM_BTH_NAME_GC_32BIT_REAL_STR(name) "pgmGCBth32BitReal" #name
1003#define PGM_BTH_NAME_GC_32BIT_PROT_STR(name) "pgmGCBth32BitProt" #name
1004#define PGM_BTH_NAME_GC_32BIT_32BIT_STR(name) "pgmGCBth32Bit32Bit" #name
1005#define PGM_BTH_NAME_GC_PAE_REAL_STR(name) "pgmGCBthPAEReal" #name
1006#define PGM_BTH_NAME_GC_PAE_PROT_STR(name) "pgmGCBthPAEProt" #name
1007#define PGM_BTH_NAME_GC_PAE_32BIT_STR(name) "pgmGCBthPAE32Bit" #name
1008#define PGM_BTH_NAME_GC_PAE_PAE_STR(name) "pgmGCBthPAEPAE" #name
1009#define PGM_BTH_NAME_GC_AMD64_REAL_STR(name) "pgmGCBthAMD64Real" #name
1010#define PGM_BTH_NAME_GC_AMD64_PROT_STR(name) "pgmGCBthAMD64Prot" #name
1011#define PGM_BTH_NAME_GC_AMD64_AMD64_STR(name) "pgmGCBthAMD64AMD64" #name
1012#define PGM_BTH_NAME_R0_32BIT_REAL_STR(name) "pgmR0Bth32BitReal" #name
1013#define PGM_BTH_NAME_R0_32BIT_PROT_STR(name) "pgmR0Bth32BitProt" #name
1014#define PGM_BTH_NAME_R0_32BIT_32BIT_STR(name) "pgmR0Bth32Bit32Bit" #name
1015#define PGM_BTH_NAME_R0_PAE_REAL_STR(name) "pgmR0BthPAEReal" #name
1016#define PGM_BTH_NAME_R0_PAE_PROT_STR(name) "pgmR0BthPAEProt" #name
1017#define PGM_BTH_NAME_R0_PAE_32BIT_STR(name) "pgmR0BthPAE32Bit" #name
1018#define PGM_BTH_NAME_R0_PAE_PAE_STR(name) "pgmR0BthPAEPAE" #name
1019#define PGM_BTH_NAME_R0_AMD64_REAL_STR(name) "pgmR0BthAMD64Real" #name
1020#define PGM_BTH_NAME_R0_AMD64_PROT_STR(name) "pgmR0BthAMD64Prot" #name
1021#define PGM_BTH_NAME_R0_AMD64_AMD64_STR(name) "pgmR0BthAMD64AMD64" #name
1022#define PGM_BTH_DECL(type, name) PGM_CTX_DECL(type) PGM_BTH_NAME(name)
1023#define PGM_BTH_PFN(name, pVM) ((pVM)->pgm.s.PGM_CTX(pfn,Bth##name))
1024/** @} */
1025
1026/**
1027 * Data for each paging mode.
1028 */
1029typedef struct PGMMODEDATA
1030{
1031 /** The guest mode type. */
1032 uint32_t uGstType;
1033 /** The shadow mode type. */
1034 uint32_t uShwType;
1035
1036 /** @name Function pointers for Shadow paging.
1037 * @{
1038 */
1039 DECLR3CALLBACKMEMBER(int, pfnR3ShwRelocate,(PVM pVM, RTGCUINTPTR offDelta));
1040 DECLR3CALLBACKMEMBER(int, pfnR3ShwExit,(PVM pVM));
1041 DECLR3CALLBACKMEMBER(int, pfnR3ShwGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
1042 DECLR3CALLBACKMEMBER(int, pfnR3ShwModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1043 DECLR3CALLBACKMEMBER(int, pfnR3ShwGetPDEByIndex,(PVM pVM, uint32_t iPD, PX86PDEPAE pPde));
1044 DECLR3CALLBACKMEMBER(int, pfnR3ShwSetPDEByIndex,(PVM pVM, uint32_t iPD, X86PDEPAE Pde));
1045 DECLR3CALLBACKMEMBER(int, pfnR3ShwModifyPDEByIndex,(PVM pVM, uint32_t iPD, uint64_t fFlags, uint64_t fMask));
1046
1047 DECLGCCALLBACKMEMBER(int, pfnGCShwGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
1048 DECLGCCALLBACKMEMBER(int, pfnGCShwModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1049 DECLGCCALLBACKMEMBER(int, pfnGCShwGetPDEByIndex,(PVM pVM, uint32_t iPD, PX86PDEPAE pPde));
1050 DECLGCCALLBACKMEMBER(int, pfnGCShwSetPDEByIndex,(PVM pVM, uint32_t iPD, X86PDEPAE Pde));
1051 DECLGCCALLBACKMEMBER(int, pfnGCShwModifyPDEByIndex,(PVM pVM, uint32_t iPD, uint64_t fFlags, uint64_t fMask));
1052
1053 DECLR0CALLBACKMEMBER(int, pfnR0ShwGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
1054 DECLR0CALLBACKMEMBER(int, pfnR0ShwModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1055 DECLR0CALLBACKMEMBER(int, pfnR0ShwGetPDEByIndex,(PVM pVM, uint32_t iPD, PX86PDEPAE pPde));
1056 DECLR0CALLBACKMEMBER(int, pfnR0ShwSetPDEByIndex,(PVM pVM, uint32_t iPD, X86PDEPAE Pde));
1057 DECLR0CALLBACKMEMBER(int, pfnR0ShwModifyPDEByIndex,(PVM pVM, uint32_t iPD, uint64_t fFlags, uint64_t fMask));
1058 /** @} */
1059
1060 /** @name Function pointers for Guest paging.
1061 * @{
1062 */
1063 DECLR3CALLBACKMEMBER(int, pfnR3GstRelocate,(PVM pVM, RTGCUINTPTR offDelta));
1064 DECLR3CALLBACKMEMBER(int, pfnR3GstExit,(PVM pVM));
1065 DECLR3CALLBACKMEMBER(int, pfnR3GstGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys));
1066 DECLR3CALLBACKMEMBER(int, pfnR3GstModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1067 DECLR3CALLBACKMEMBER(int, pfnR3GstGetPDE,(PVM pVM, RTGCUINTPTR GCPtr, PX86PDEPAE pPde));
1068 DECLR3CALLBACKMEMBER(int, pfnR3GstMonitorCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
1069 DECLR3CALLBACKMEMBER(int, pfnR3GstUnmonitorCR3,(PVM pVM));
1070 DECLR3CALLBACKMEMBER(int, pfnR3GstMapCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
1071 DECLR3CALLBACKMEMBER(int, pfnR3GstUnmapCR3,(PVM pVM));
1072 HCPTRTYPE(PFNPGMR3PHYSHANDLER) pfnHCGstWriteHandlerCR3;
1073 HCPTRTYPE(const char *) pszHCGstWriteHandlerCR3;
1074
1075 DECLGCCALLBACKMEMBER(int, pfnGCGstGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys));
1076 DECLGCCALLBACKMEMBER(int, pfnGCGstModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1077 DECLGCCALLBACKMEMBER(int, pfnGCGstGetPDE,(PVM pVM, RTGCUINTPTR GCPtr, PX86PDEPAE pPde));
1078 DECLGCCALLBACKMEMBER(int, pfnGCGstMonitorCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
1079 DECLGCCALLBACKMEMBER(int, pfnGCGstUnmonitorCR3,(PVM pVM));
1080 DECLGCCALLBACKMEMBER(int, pfnGCGstMapCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
1081 DECLGCCALLBACKMEMBER(int, pfnGCGstUnmapCR3,(PVM pVM));
1082 GCPTRTYPE(PFNPGMGCPHYSHANDLER) pfnGCGstWriteHandlerCR3;
1083
1084 DECLR0CALLBACKMEMBER(int, pfnR0GstGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys));
1085 DECLR0CALLBACKMEMBER(int, pfnR0GstModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1086 DECLR0CALLBACKMEMBER(int, pfnR0GstGetPDE,(PVM pVM, RTGCUINTPTR GCPtr, PX86PDEPAE pPde));
1087 DECLR0CALLBACKMEMBER(int, pfnR0GstMonitorCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
1088 DECLR0CALLBACKMEMBER(int, pfnR0GstUnmonitorCR3,(PVM pVM));
1089 DECLR0CALLBACKMEMBER(int, pfnR0GstMapCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
1090 DECLR0CALLBACKMEMBER(int, pfnR0GstUnmapCR3,(PVM pVM));
1091 R0PTRTYPE(PFNPGMR0PHYSHANDLER) pfnR0GstWriteHandlerCR3;
1092 /** @} */
1093
1094 /** @name Function pointers for Both Shadow and Guest paging.
1095 * @{
1096 */
1097 DECLR3CALLBACKMEMBER(int, pfnR3BthRelocate,(PVM pVM, RTGCUINTPTR offDelta));
1098 DECLR3CALLBACKMEMBER(int, pfnR3BthTrap0eHandler,(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault));
1099 DECLR3CALLBACKMEMBER(int, pfnR3BthInvalidatePage,(PVM pVM, RTGCPTR GCPtrPage));
1100 DECLR3CALLBACKMEMBER(int, pfnR3BthSyncCR3,(PVM pVM, uint32_t cr0, uint32_t cr3, uint32_t cr4, bool fGlobal));
1101 DECLR3CALLBACKMEMBER(int, pfnR3BthSyncPage,(PVM pVM, VBOXPDE PdeSrc, RTGCUINTPTR GCPtrPage, unsigned cPages, unsigned uError));
1102 DECLR3CALLBACKMEMBER(int, pfnR3BthPrefetchPage,(PVM pVM, RTGCUINTPTR GCPtrPage));
1103 DECLR3CALLBACKMEMBER(int, pfnR3BthVerifyAccessSyncPage,(PVM pVM, RTGCUINTPTR GCPtrPage, unsigned fFlags, unsigned uError));
1104#ifdef VBOX_STRICT
1105 DECLR3CALLBACKMEMBER(unsigned, pfnR3BthAssertCR3,(PVM pVM, uint32_t cr3, uint32_t cr4, RTGCUINTPTR GCPtr, RTGCUINTPTR cb));
1106#endif
1107
1108 DECLGCCALLBACKMEMBER(int, pfnGCBthTrap0eHandler,(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault));
1109 DECLGCCALLBACKMEMBER(int, pfnGCBthInvalidatePage,(PVM pVM, RTGCPTR GCPtrPage));
1110 DECLGCCALLBACKMEMBER(int, pfnGCBthSyncCR3,(PVM pVM, uint32_t cr0, uint32_t cr3, uint32_t cr4, bool fGlobal));
1111 DECLGCCALLBACKMEMBER(int, pfnGCBthSyncPage,(PVM pVM, VBOXPDE PdeSrc, RTGCUINTPTR GCPtrPage, unsigned cPages, unsigned uError));
1112 DECLGCCALLBACKMEMBER(int, pfnGCBthPrefetchPage,(PVM pVM, RTGCUINTPTR GCPtrPage));
1113 DECLGCCALLBACKMEMBER(int, pfnGCBthVerifyAccessSyncPage,(PVM pVM, RTGCUINTPTR GCPtrPage, unsigned fFlags, unsigned uError));
1114#ifdef VBOX_STRICT
1115 DECLGCCALLBACKMEMBER(unsigned, pfnGCBthAssertCR3,(PVM pVM, uint32_t cr3, uint32_t cr4, RTGCUINTPTR GCPtr, RTGCUINTPTR cb));
1116#endif
1117
1118 DECLR0CALLBACKMEMBER(int, pfnR0BthTrap0eHandler,(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault));
1119 DECLR0CALLBACKMEMBER(int, pfnR0BthInvalidatePage,(PVM pVM, RTGCPTR GCPtrPage));
1120 DECLR0CALLBACKMEMBER(int, pfnR0BthSyncCR3,(PVM pVM, uint32_t cr0, uint32_t cr3, uint32_t cr4, bool fGlobal));
1121 DECLR0CALLBACKMEMBER(int, pfnR0BthSyncPage,(PVM pVM, VBOXPDE PdeSrc, RTGCUINTPTR GCPtrPage, unsigned cPages, unsigned uError));
1122 DECLR0CALLBACKMEMBER(int, pfnR0BthPrefetchPage,(PVM pVM, RTGCUINTPTR GCPtrPage));
1123 DECLR0CALLBACKMEMBER(int, pfnR0BthVerifyAccessSyncPage,(PVM pVM, RTGCUINTPTR GCPtrPage, unsigned fFlags, unsigned uError));
1124#ifdef VBOX_STRICT
1125 DECLR0CALLBACKMEMBER(unsigned, pfnR0BthAssertCR3,(PVM pVM, uint32_t cr3, uint32_t cr4, RTGCUINTPTR GCPtr, RTGCUINTPTR cb));
1126#endif
1127 /** @} */
1128} PGMMODEDATA, *PPGMMODEDATA;
1129
1130
1131
1132/**
1133 * Converts a PGM pointer into a VM pointer.
1134 * @returns Pointer to the VM structure the PGM is part of.
1135 * @param pPGM Pointer to PGM instance data.
1136 */
1137#define PGM2VM(pPGM) ( (PVM)((char*)pPGM - pPGM->offVM) )
1138
1139/**
1140 * PGM Data (part of VM)
1141 */
1142typedef struct PGM
1143{
1144 /** Offset to the VM structure. */
1145 RTINT offVM;
1146
1147 /*
1148 * This will be redefined at least two more times before we're done, I'm sure.
1149 * The current code is only to get on with the coding.
1150 * - 2004-06-10: initial version, bird.
1151 * - 2004-07-02: 1st time, bird.
1152 * - 2004-10-18: 2nd time, bird.
1153 * - 2005-07-xx: 3rd time, bird.
1154 */
1155
1156 /** Pointer to the page table entries for the dynamic page mapping area - GCPtr. */
1157 GCPTRTYPE(PX86PTE) paDynPageMap32BitPTEsGC;
1158 /** Pointer to the page table entries for the dynamic page mapping area - GCPtr. */
1159 GCPTRTYPE(PX86PTEPAE) paDynPageMapPaePTEsGC;
1160
1161 /** The host paging mode. (This is what SUPLib reports.) */
1162 SUPPAGINGMODE enmHostMode;
1163 /** The shadow paging mode. */
1164 PGMMODE enmShadowMode;
1165 /** The guest paging mode. */
1166 PGMMODE enmGuestMode;
1167
1168 /** The current physical address representing in the guest CR3 register. */
1169 RTGCPHYS GCPhysCR3;
1170 /** Pointer to the 5 page CR3 content mapping.
1171 * The first page is always the CR3 (in some form) while the 4 other pages
1172 * are used of the PDs in PAE mode. */
1173 RTGCPTR GCPtrCR3Mapping;
1174 /** The physical address of the currently monitored guest CR3 page.
1175 * When this value is NIL_RTGCPHYS no page is being monitored. */
1176 RTGCPHYS GCPhysGstCR3Monitored;
1177#if HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64
1178 RTGCPHYS GCPhysPadding0; /**< alignment padding. */
1179#endif
1180
1181 /** @name 32-bit Guest Paging.
1182 * @{ */
1183 /** The guest's page directory, HC pointer. */
1184 HCPTRTYPE(PVBOXPD) pGuestPDHC;
1185 /** The guest's page directory, static GC mapping. */
1186 GCPTRTYPE(PVBOXPD) pGuestPDGC;
1187 /** @} */
1188
1189 /** @name PAE Guest Paging.
1190 * @{ */
1191 /** The guest's page directory pointer table, static GC mapping. */
1192 GCPTRTYPE(PX86PDPTR) pGstPaePDPTRGC;
1193 /** The guest's page directory pointer table, HC pointer. */
1194 HCPTRTYPE(PX86PDPTR) pGstPaePDPTRHC;
1195 /** The guest's page directories, HC pointers.
1196 * These are individual pointers and doesn't have to be adjecent.
1197 * These doesn't have to be update to date - use pgmGstGetPaePD() to access them. */
1198 HCPTRTYPE(PX86PDPAE) apGstPaePDsHC[4];
1199 /** The guest's page directories, static GC mapping.
1200 * Unlike the HC array the first entry can be accessed as a 2048 entry PD.
1201 * These doesn't have to be update to date - use pgmGstGetPaePD() to access them. */
1202 GCPTRTYPE(PX86PDPAE) apGstPaePDsGC[4];
1203 /** The physical addresses of the guest page directories (PAE) pointed to by apGstPagePDsHC/GC. */
1204 RTGCPHYS aGCPhysGstPaePDs[4];
1205 /** The physical addresses of the monitored guest page directories (PAE). */
1206 RTGCPHYS aGCPhysGstPaePDsMonitored[4];
1207 /** @} */
1208
1209
1210 /** @name 32-bit Shadow Paging
1211 * @{ */
1212 /** The 32-Bit PD - HC Ptr. */
1213 HCPTRTYPE(PX86PD) pHC32BitPD;
1214 /** The 32-Bit PD - GC Ptr. */
1215 GCPTRTYPE(PX86PD) pGC32BitPD;
1216#if HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32
1217 uint32_t u32Padding1; /**< alignment padding. */
1218#endif
1219 /** The Physical Address (HC) of the 32-Bit PD. */
1220 RTHCPHYS HCPhys32BitPD;
1221 /** @} */
1222
1223 /** @name PAE Shadow Paging
1224 * @{ */
1225 /** The four PDs for the low 4GB - HC Ptr.
1226 * Even though these are 4 pointers, what they point at is a single table.
1227 * Thus, it's possible to walk the 2048 entries starting where apHCPaePDs[0] points. */
1228 HCPTRTYPE(PX86PDPAE) apHCPaePDs[4];
1229 /** The four PDs for the low 4GB - GC Ptr.
1230 * Same kind of mapping as apHCPaePDs. */
1231 GCPTRTYPE(PX86PDPAE) apGCPaePDs[4];
1232 /** The Physical Address (HC) of the four PDs for the low 4GB.
1233 * These are *NOT* 4 contiguous pages. */
1234 RTHCPHYS aHCPhysPaePDs[4];
1235 /** The PAE PDPTR - HC Ptr. */
1236 HCPTRTYPE(PX86PDPTR) pHCPaePDPTR;
1237 /** The Physical Address (HC) of the PAE PDPTR. */
1238 RTHCPHYS HCPhysPaePDPTR;
1239 /** The PAE PDPTR - GC Ptr. */
1240 GCPTRTYPE(PX86PDPTR) pGCPaePDPTR;
1241 /** @} */
1242
1243 /** @name AMD64 Shadow Paging
1244 * Extends PAE Paging.
1245 * @{ */
1246 /** The Page Map Level 4 table - HC Ptr. */
1247 GCPTRTYPE(PX86PML4) pGCPaePML4;
1248 /** The Page Map Level 4 table - GC Ptr. */
1249 HCPTRTYPE(PX86PML4) pHCPaePML4;
1250 /** The Physical Address (HC) of the Page Map Level 4 table. */
1251 RTHCPHYS HCPhysPaePML4;
1252 /** @}*/
1253
1254 /** @name Function pointers for Shadow paging.
1255 * @{
1256 */
1257 DECLR3CALLBACKMEMBER(int, pfnR3ShwRelocate,(PVM pVM, RTGCUINTPTR offDelta));
1258 DECLR3CALLBACKMEMBER(int, pfnR3ShwExit,(PVM pVM));
1259 DECLR3CALLBACKMEMBER(int, pfnR3ShwGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
1260 DECLR3CALLBACKMEMBER(int, pfnR3ShwModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1261 DECLR3CALLBACKMEMBER(int, pfnR3ShwGetPDEByIndex,(PVM pVM, uint32_t iPD, PX86PDEPAE pPde));
1262 DECLR3CALLBACKMEMBER(int, pfnR3ShwSetPDEByIndex,(PVM pVM, uint32_t iPD, X86PDEPAE Pde));
1263 DECLR3CALLBACKMEMBER(int, pfnR3ShwModifyPDEByIndex,(PVM pVM, uint32_t iPD, uint64_t fFlags, uint64_t fMask));
1264
1265 DECLGCCALLBACKMEMBER(int, pfnGCShwGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
1266 DECLGCCALLBACKMEMBER(int, pfnGCShwModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1267 DECLGCCALLBACKMEMBER(int, pfnGCShwGetPDEByIndex,(PVM pVM, uint32_t iPD, PX86PDEPAE pPde));
1268 DECLGCCALLBACKMEMBER(int, pfnGCShwSetPDEByIndex,(PVM pVM, uint32_t iPD, X86PDEPAE Pde));
1269 DECLGCCALLBACKMEMBER(int, pfnGCShwModifyPDEByIndex,(PVM pVM, uint32_t iPD, uint64_t fFlags, uint64_t fMask));
1270#if GC_ARCH_BITS == 32 && HC_ARCH_BITS == 64
1271 RTGCPTR alignment0; /**< structure size alignment. */
1272#endif
1273
1274 DECLR0CALLBACKMEMBER(int, pfnR0ShwGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
1275 DECLR0CALLBACKMEMBER(int, pfnR0ShwModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1276 DECLR0CALLBACKMEMBER(int, pfnR0ShwGetPDEByIndex,(PVM pVM, uint32_t iPD, PX86PDEPAE pPde));
1277 DECLR0CALLBACKMEMBER(int, pfnR0ShwSetPDEByIndex,(PVM pVM, uint32_t iPD, X86PDEPAE Pde));
1278 DECLR0CALLBACKMEMBER(int, pfnR0ShwModifyPDEByIndex,(PVM pVM, uint32_t iPD, uint64_t fFlags, uint64_t fMask));
1279
1280 /** @} */
1281
1282 /** @name Function pointers for Guest paging.
1283 * @{
1284 */
1285 DECLR3CALLBACKMEMBER(int, pfnR3GstRelocate,(PVM pVM, RTGCUINTPTR offDelta));
1286 DECLR3CALLBACKMEMBER(int, pfnR3GstExit,(PVM pVM));
1287 DECLR3CALLBACKMEMBER(int, pfnR3GstGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys));
1288 DECLR3CALLBACKMEMBER(int, pfnR3GstModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1289 DECLR3CALLBACKMEMBER(int, pfnR3GstGetPDE,(PVM pVM, RTGCUINTPTR GCPtr, PX86PDEPAE pPde));
1290 DECLR3CALLBACKMEMBER(int, pfnR3GstMonitorCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
1291 DECLR3CALLBACKMEMBER(int, pfnR3GstUnmonitorCR3,(PVM pVM));
1292 DECLR3CALLBACKMEMBER(int, pfnR3GstMapCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
1293 DECLR3CALLBACKMEMBER(int, pfnR3GstUnmapCR3,(PVM pVM));
1294 HCPTRTYPE(PFNPGMR3PHYSHANDLER) pfnHCGstWriteHandlerCR3;
1295 HCPTRTYPE(const char *) pszHCGstWriteHandlerCR3;
1296
1297 DECLGCCALLBACKMEMBER(int, pfnGCGstGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys));
1298 DECLGCCALLBACKMEMBER(int, pfnGCGstModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1299 DECLGCCALLBACKMEMBER(int, pfnGCGstGetPDE,(PVM pVM, RTGCUINTPTR GCPtr, PX86PDEPAE pPde));
1300 DECLGCCALLBACKMEMBER(int, pfnGCGstMonitorCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
1301 DECLGCCALLBACKMEMBER(int, pfnGCGstUnmonitorCR3,(PVM pVM));
1302 DECLGCCALLBACKMEMBER(int, pfnGCGstMapCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
1303 DECLGCCALLBACKMEMBER(int, pfnGCGstUnmapCR3,(PVM pVM));
1304 GCPTRTYPE(PFNPGMGCPHYSHANDLER) pfnGCGstWriteHandlerCR3;
1305
1306 DECLR0CALLBACKMEMBER(int, pfnR0GstGetPage,(PVM pVM, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys));
1307 DECLR0CALLBACKMEMBER(int, pfnR0GstModifyPage,(PVM pVM, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
1308 DECLR0CALLBACKMEMBER(int, pfnR0GstGetPDE,(PVM pVM, RTGCUINTPTR GCPtr, PX86PDEPAE pPde));
1309 DECLR0CALLBACKMEMBER(int, pfnR0GstMonitorCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
1310 DECLR0CALLBACKMEMBER(int, pfnR0GstUnmonitorCR3,(PVM pVM));
1311 DECLR0CALLBACKMEMBER(int, pfnR0GstMapCR3,(PVM pVM, RTGCPHYS GCPhysCR3));
1312 DECLR0CALLBACKMEMBER(int, pfnR0GstUnmapCR3,(PVM pVM));
1313 R0PTRTYPE(PFNPGMR0PHYSHANDLER) pfnR0GstWriteHandlerCR3;
1314 /** @} */
1315
1316 /** @name Function pointers for Both Shadow and Guest paging.
1317 * @{
1318 */
1319 DECLR3CALLBACKMEMBER(int, pfnR3BthRelocate,(PVM pVM, RTGCUINTPTR offDelta));
1320 DECLR3CALLBACKMEMBER(int, pfnR3BthTrap0eHandler,(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault));
1321 DECLR3CALLBACKMEMBER(int, pfnR3BthInvalidatePage,(PVM pVM, RTGCPTR GCPtrPage));
1322 DECLR3CALLBACKMEMBER(int, pfnR3BthSyncCR3,(PVM pVM, uint32_t cr0, uint32_t cr3, uint32_t cr4, bool fGlobal));
1323 DECLR3CALLBACKMEMBER(int, pfnR3BthSyncPage,(PVM pVM, VBOXPDE PdeSrc, RTGCUINTPTR GCPtrPage, unsigned cPages, unsigned uError));
1324 DECLR3CALLBACKMEMBER(int, pfnR3BthPrefetchPage,(PVM pVM, RTGCUINTPTR GCPtrPage));
1325 DECLR3CALLBACKMEMBER(int, pfnR3BthVerifyAccessSyncPage,(PVM pVM, RTGCUINTPTR GCPtrPage, unsigned fFlags, unsigned uError));
1326 DECLR3CALLBACKMEMBER(unsigned, pfnR3BthAssertCR3,(PVM pVM, uint32_t cr3, uint32_t cr4, RTGCUINTPTR GCPtr, RTGCUINTPTR cb));
1327
1328 DECLR0CALLBACKMEMBER(int, pfnR0BthTrap0eHandler,(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault));
1329 DECLR0CALLBACKMEMBER(int, pfnR0BthInvalidatePage,(PVM pVM, RTGCPTR GCPtrPage));
1330 DECLR0CALLBACKMEMBER(int, pfnR0BthSyncCR3,(PVM pVM, uint32_t cr0, uint32_t cr3, uint32_t cr4, bool fGlobal));
1331 DECLR0CALLBACKMEMBER(int, pfnR0BthSyncPage,(PVM pVM, VBOXPDE PdeSrc, RTGCUINTPTR GCPtrPage, unsigned cPages, unsigned uError));
1332 DECLR0CALLBACKMEMBER(int, pfnR0BthPrefetchPage,(PVM pVM, RTGCUINTPTR GCPtrPage));
1333 DECLR0CALLBACKMEMBER(int, pfnR0BthVerifyAccessSyncPage,(PVM pVM, RTGCUINTPTR GCPtrPage, unsigned fFlags, unsigned uError));
1334 DECLR0CALLBACKMEMBER(unsigned, pfnR0BthAssertCR3,(PVM pVM, uint32_t cr3, uint32_t cr4, RTGCUINTPTR GCPtr, RTGCUINTPTR cb));
1335
1336 DECLGCCALLBACKMEMBER(int, pfnGCBthTrap0eHandler,(PVM pVM, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault));
1337 DECLGCCALLBACKMEMBER(int, pfnGCBthInvalidatePage,(PVM pVM, RTGCPTR GCPtrPage));
1338 DECLGCCALLBACKMEMBER(int, pfnGCBthSyncCR3,(PVM pVM, uint32_t cr0, uint32_t cr3, uint32_t cr4, bool fGlobal));
1339 DECLGCCALLBACKMEMBER(int, pfnGCBthSyncPage,(PVM pVM, VBOXPDE PdeSrc, RTGCUINTPTR GCPtrPage, unsigned cPages, unsigned uError));
1340 DECLGCCALLBACKMEMBER(int, pfnGCBthPrefetchPage,(PVM pVM, RTGCUINTPTR GCPtrPage));
1341 DECLGCCALLBACKMEMBER(int, pfnGCBthVerifyAccessSyncPage,(PVM pVM, RTGCUINTPTR GCPtrPage, unsigned fFlags, unsigned uError));
1342 DECLGCCALLBACKMEMBER(unsigned, pfnGCBthAssertCR3,(PVM pVM, uint32_t cr3, uint32_t cr4, RTGCUINTPTR GCPtr, RTGCUINTPTR cb));
1343#if GC_ARCH_BITS == 32 && HC_ARCH_BITS == 64
1344 RTGCPTR alignment2; /**< structure size alignment. */
1345#endif
1346 /** @} */
1347
1348 /** Pointer to SHW+GST mode data (function pointers).
1349 * The index into this table is made up from */
1350 R3PTRTYPE(PPGMMODEDATA) paModeData;
1351
1352
1353 /** Pointer to the list of RAM ranges (Phys GC -> Phys HC conversion) - for HC.
1354 * This is sorted by physical address and contains no overlaps.
1355 * The memory locks and other conversions are managed by MM at the moment.
1356 */
1357 HCPTRTYPE(PPGMRAMRANGE) pRamRangesHC;
1358 /** Pointer to the list of RAM ranges (Phys GC -> Phys HC conversion) - for GC.
1359 * This is sorted by physical address and contains no overlaps.
1360 * The memory locks and other conversions are managed by MM at the moment.
1361 */
1362 GCPTRTYPE(PPGMRAMRANGE) pRamRangesGC;
1363 /** The configured RAM size. */
1364 RTUINT cbRamSize;
1365
1366 /** PGM offset based trees - HC Ptr. */
1367 HCPTRTYPE(PPGMTREES) pTreesHC;
1368 /** PGM offset based trees - GC Ptr. */
1369 GCPTRTYPE(PPGMTREES) pTreesGC;
1370
1371 /** Linked list of GC mappings - for GC.
1372 * The list is sorted ascending on address.
1373 */
1374 GCPTRTYPE(PPGMMAPPING) pMappingsGC;
1375 /** Linked list of GC mappings - for HC.
1376 * The list is sorted ascending on address.
1377 */
1378 R3PTRTYPE(PPGMMAPPING) pMappingsR3;
1379 /** Linked list of GC mappings - for R0.
1380 * The list is sorted ascending on address.
1381 */
1382 R0PTRTYPE(PPGMMAPPING) pMappingsR0;
1383
1384 /** If set no conflict checks are required. (boolean) */
1385 bool fMappingsFixed;
1386 /** If set, then no mappings are put into the shadow page table. (boolean) */
1387 bool fDisableMappings;
1388 /** Size of fixed mapping */
1389 uint32_t cbMappingFixed;
1390 /** Base address (GC) of fixed mapping */
1391 RTGCPTR GCPtrMappingFixed;
1392#if HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32
1393 uint32_t u32Padding0; /**< alignment padding. */
1394#endif
1395
1396
1397 /** @name Intermediate Context
1398 * @{ */
1399 /** Pointer to the intermediate page directory - Normal. */
1400 HCPTRTYPE(PX86PD) pInterPD;
1401 /** Pointer to the intermedate page tables - Normal.
1402 * There are two page tables, one for the identity mapping and one for
1403 * the host context mapping (of the core code). */
1404 HCPTRTYPE(PX86PT) apInterPTs[2];
1405 /** Pointer to the intermedate page tables - PAE. */
1406 HCPTRTYPE(PX86PTPAE) apInterPaePTs[2];
1407 /** Pointer to the intermedate page directory - PAE. */
1408 HCPTRTYPE(PX86PDPAE) apInterPaePDs[4];
1409 /** Pointer to the intermedate page directory - PAE. */
1410 HCPTRTYPE(PX86PDPTR) pInterPaePDPTR;
1411 /** Pointer to the intermedate page-map level 4 - AMD64. */
1412 HCPTRTYPE(PX86PML4) pInterPaePML4;
1413 /** Pointer to the intermedate page directory - AMD64. */
1414 HCPTRTYPE(PX86PDPTR) pInterPaePDPTR64;
1415 /** The Physical Address (HC) of the intermediate Page Directory - Normal. */
1416 RTHCPHYS HCPhysInterPD;
1417 /** The Physical Address (HC) of the intermediate Page Directory Pointer Table - PAE. */
1418 RTHCPHYS HCPhysInterPaePDPTR;
1419 /** The Physical Address (HC) of the intermediate Page Map Level 4 table - AMD64. */
1420 RTHCPHYS HCPhysInterPaePML4;
1421 /** @} */
1422
1423 /** Base address of the dynamic page mapping area.
1424 * The array is MM_HYPER_DYNAMIC_SIZE bytes big.
1425 */
1426 GCPTRTYPE(uint8_t *) pbDynPageMapBaseGC;
1427 /** The index of the last entry used in the dynamic page mapping area. */
1428 RTUINT iDynPageMapLast;
1429 /** Cache containing the last entries in the dynamic page mapping area.
1430 * The cache size is covering half of the mapping area. */
1431 RTHCPHYS aHCPhysDynPageMapCache[MM_HYPER_DYNAMIC_SIZE >> (PAGE_SHIFT + 1)];
1432
1433 /** A20 gate mask.
1434 * Our current approach to A20 emulation is to let REM do it and don't bother
1435 * anywhere else. The interesting Guests will be operating with it enabled anyway.
1436 * But whould need arrise, we'll subject physical addresses to this mask. */
1437 RTGCPHYS GCPhysA20Mask;
1438 /** A20 gate state - boolean! */
1439 RTUINT fA20Enabled;
1440
1441 /** What needs syncing (PGM_SYNC_*).
1442 * This is used to queue operations for PGMSyncCR3, PGMInvalidatePage,
1443 * PGMFlushTLB, and PGMR3Load. */
1444 RTUINT fSyncFlags;
1445
1446#if HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32
1447 RTUINT uPadding3; /**< alignment padding. */
1448#endif
1449 /** PGM critical section.
1450 * This protects the physical & virtual access handlers, ram ranges,
1451 * and the page flag updating (some of it anyway).
1452 */
1453 PDMCRITSECT CritSect;
1454
1455 /** Shadow Page Pool - HC Ptr. */
1456 HCPTRTYPE(PPGMPOOL) pPoolHC;
1457 /** Shadow Page Pool - GC Ptr. */
1458 GCPTRTYPE(PPGMPOOL) pPoolGC;
1459
1460 /** We're not in a state which permits writes to guest memory.
1461 * (Only used in strict builds.) */
1462 bool fNoMorePhysWrites;
1463
1464 /** Flush the cache on the next access. */
1465 bool fPhysCacheFlushPending;
1466/** @todo r=bird: Fix member names!*/
1467 /** PGMPhysRead cache */
1468 PGMPHYSCACHE pgmphysreadcache;
1469 /** PGMPhysWrite cache */
1470 PGMPHYSCACHE pgmphyswritecache;
1471
1472 /** @name Release Statistics
1473 * @{ */
1474 /** The number of times the guest has switched mode since last reset or statistics reset. */
1475 STAMCOUNTER cGuestModeChanges;
1476 /** @} */
1477
1478#ifdef VBOX_WITH_STATISTICS
1479 /** GC: Which statistic this \#PF should be attributed to. */
1480 GCPTRTYPE(PSTAMPROFILE) pStatTrap0eAttributionGC;
1481 RTGCPTR padding0;
1482 /** HC: Which statistic this \#PF should be attributed to. */
1483 HCPTRTYPE(PSTAMPROFILE) pStatTrap0eAttributionHC;
1484 RTHCPTR padding1;
1485 STAMPROFILE StatGCTrap0e; /**< GC: PGMGCTrap0eHandler() profiling. */
1486 STAMPROFILE StatTrap0eCSAM; /**< Profiling of the Trap0eHandler body when the cause is CSAM. */
1487 STAMPROFILE StatTrap0eDirtyAndAccessedBits; /**< Profiling of the Trap0eHandler body when the cause is dirty and/or accessed bit emulation. */
1488 STAMPROFILE StatTrap0eGuestTrap; /**< Profiling of the Trap0eHandler body when the cause is a guest trap. */
1489 STAMPROFILE StatTrap0eHndPhys; /**< Profiling of the Trap0eHandler body when the cause is a physical handler. */
1490 STAMPROFILE StatTrap0eHndVirt; /**< Profiling of the Trap0eHandler body when the cause is a virtual handler. */
1491 STAMPROFILE StatTrap0eHndUnhandled; /**< Profiling of the Trap0eHandler body when the cause is access outside the monitored areas of a monitored page. */
1492 STAMPROFILE StatTrap0eMisc; /**< Profiling of the Trap0eHandler body when the cause is not known. */
1493 STAMPROFILE StatTrap0eOutOfSync; /**< Profiling of the Trap0eHandler body when the cause is an out-of-sync page. */
1494 STAMPROFILE StatTrap0eOutOfSyncHndPhys; /**< Profiling of the Trap0eHandler body when the cause is an out-of-sync physical handler page. */
1495 STAMPROFILE StatTrap0eOutOfSyncHndVirt; /**< Profiling of the Trap0eHandler body when the cause is an out-of-sync virtual handler page. */
1496 STAMPROFILE StatTrap0eOutOfSyncObsHnd; /**< Profiling of the Trap0eHandler body when the cause is an obsolete handler page. */
1497 STAMPROFILE StatTrap0eSyncPT; /**< Profiling of the Trap0eHandler body when the cause is lazy syncing of a PT. */
1498
1499 STAMCOUNTER StatTrap0eMapHandler; /**< Number of traps due to access handlers in mappings. */
1500 STAMCOUNTER StatGCTrap0eConflicts; /**< GC: The number of times \#PF was caused by an undetected conflict. */
1501
1502 STAMCOUNTER StatGCTrap0eUSNotPresentRead;
1503 STAMCOUNTER StatGCTrap0eUSNotPresentWrite;
1504 STAMCOUNTER StatGCTrap0eUSWrite;
1505 STAMCOUNTER StatGCTrap0eUSReserved;
1506 STAMCOUNTER StatGCTrap0eUSRead;
1507
1508 STAMCOUNTER StatGCTrap0eSVNotPresentRead;
1509 STAMCOUNTER StatGCTrap0eSVNotPresentWrite;
1510 STAMCOUNTER StatGCTrap0eSVWrite;
1511 STAMCOUNTER StatGCTrap0eSVReserved;
1512
1513 STAMCOUNTER StatGCTrap0eUnhandled;
1514 STAMCOUNTER StatGCTrap0eMap;
1515
1516 /** GC: PGMSyncPT() profiling. */
1517 STAMPROFILE StatGCSyncPT;
1518 /** GC: The number of times PGMSyncPT() needed to allocate page tables. */
1519 STAMCOUNTER StatGCSyncPTAlloc;
1520 /** GC: The number of times PGMSyncPT() detected conflicts. */
1521 STAMCOUNTER StatGCSyncPTConflict;
1522 /** GC: The number of times PGMSyncPT() failed. */
1523 STAMCOUNTER StatGCSyncPTFailed;
1524 /** GC: PGMGCInvalidatePage() profiling. */
1525 STAMPROFILE StatGCInvalidatePage;
1526 /** GC: The number of times PGMGCInvalidatePage() was called for a 4KB page. */
1527 STAMCOUNTER StatGCInvalidatePage4KBPages;
1528 /** GC: The number of times PGMGCInvalidatePage() was called for a 4MB page. */
1529 STAMCOUNTER StatGCInvalidatePage4MBPages;
1530 /** GC: The number of times PGMGCInvalidatePage() skipped a 4MB page. */
1531 STAMCOUNTER StatGCInvalidatePage4MBPagesSkip;
1532 /** GC: The number of times PGMGCInvalidatePage() was called for a not accessed page directory. */
1533 STAMCOUNTER StatGCInvalidatePagePDNAs;
1534 /** GC: The number of times PGMGCInvalidatePage() was called for a not present page directory. */
1535 STAMCOUNTER StatGCInvalidatePagePDNPs;
1536 /** GC: The number of times PGMGCInvalidatePage() was called for a page directory containing mappings (no conflict). */
1537 STAMCOUNTER StatGCInvalidatePagePDMappings;
1538 /** GC: The number of times PGMGCInvalidatePage() was called for an out of sync page directory. */
1539 STAMCOUNTER StatGCInvalidatePagePDOutOfSync;
1540 /** HC: The number of times PGMGCInvalidatePage() was skipped due to not present shw or pending pending SyncCR3. */
1541 STAMCOUNTER StatGCInvalidatePageSkipped;
1542 /** GC: The number of times user page is out of sync was detected in GC. */
1543 STAMCOUNTER StatGCPageOutOfSyncUser;
1544 /** GC: The number of times supervisor page is out of sync was detected in GC. */
1545 STAMCOUNTER StatGCPageOutOfSyncSupervisor;
1546 /** GC: The number of dynamic page mapping cache hits */
1547 STAMCOUNTER StatDynMapCacheMisses;
1548 /** GC: The number of dynamic page mapping cache misses */
1549 STAMCOUNTER StatDynMapCacheHits;
1550 /** GC: The number of times pgmGCGuestPDWriteHandler() was successfully called. */
1551 STAMCOUNTER StatGCGuestCR3WriteHandled;
1552 /** GC: The number of times pgmGCGuestPDWriteHandler() was called and we had to fall back to the recompiler. */
1553 STAMCOUNTER StatGCGuestCR3WriteUnhandled;
1554 /** GC: The number of times pgmGCGuestPDWriteHandler() was called and a conflict was detected. */
1555 STAMCOUNTER StatGCGuestCR3WriteConflict;
1556 /** GC: Number of out-of-sync handled pages. */
1557 STAMCOUNTER StatHandlersOutOfSync;
1558 /** GC: Number of traps due to physical access handlers. */
1559 STAMCOUNTER StatHandlersPhysical;
1560 /** GC: Number of traps due to virtual access handlers. */
1561 STAMCOUNTER StatHandlersVirtual;
1562 /** GC: Number of traps due to virtual access handlers found by physical address. */
1563 STAMCOUNTER StatHandlersVirtualByPhys;
1564 /** GC: Number of traps due to virtual access handlers found by virtual address (without proper physical flags). */
1565 STAMCOUNTER StatHandlersVirtualUnmarked;
1566 /** GC: Number of traps due to access outside range of monitored page(s). */
1567 STAMCOUNTER StatHandlersUnhandled;
1568
1569 /** GC: The number of times pgmGCGuestROMWriteHandler() was successfully called. */
1570 STAMCOUNTER StatGCGuestROMWriteHandled;
1571 /** GC: The number of times pgmGCGuestROMWriteHandler() was called and we had to fall back to the recompiler */
1572 STAMCOUNTER StatGCGuestROMWriteUnhandled;
1573
1574 /** HC: PGMR3InvalidatePage() profiling. */
1575 STAMPROFILE StatHCInvalidatePage;
1576 /** HC: The number of times PGMR3InvalidatePage() was called for a 4KB page. */
1577 STAMCOUNTER StatHCInvalidatePage4KBPages;
1578 /** HC: The number of times PGMR3InvalidatePage() was called for a 4MB page. */
1579 STAMCOUNTER StatHCInvalidatePage4MBPages;
1580 /** HC: The number of times PGMR3InvalidatePage() skipped a 4MB page. */
1581 STAMCOUNTER StatHCInvalidatePage4MBPagesSkip;
1582 /** HC: The number of times PGMR3InvalidatePage() was called for a not accessed page directory. */
1583 STAMCOUNTER StatHCInvalidatePagePDNAs;
1584 /** HC: The number of times PGMR3InvalidatePage() was called for a not present page directory. */
1585 STAMCOUNTER StatHCInvalidatePagePDNPs;
1586 /** HC: The number of times PGMR3InvalidatePage() was called for a page directory containing mappings (no conflict). */
1587 STAMCOUNTER StatHCInvalidatePagePDMappings;
1588 /** HC: The number of times PGMGCInvalidatePage() was called for an out of sync page directory. */
1589 STAMCOUNTER StatHCInvalidatePagePDOutOfSync;
1590 /** HC: The number of times PGMR3InvalidatePage() was skipped due to not present shw or pending pending SyncCR3. */
1591 STAMCOUNTER StatHCInvalidatePageSkipped;
1592 /** HC: PGMR3SyncPT() profiling. */
1593 STAMPROFILE StatHCSyncPT;
1594 /** HC: pgmr3SyncPTResolveConflict() profiling (includes the entire relocation). */
1595 STAMPROFILE StatHCResolveConflict;
1596 /** HC: Number of times PGMR3CheckMappingConflicts() detected a conflict. */
1597 STAMCOUNTER StatHCDetectedConflicts;
1598 /** HC: The total number of times pgmHCGuestPDWriteHandler() was called. */
1599 STAMCOUNTER StatHCGuestPDWrite;
1600 /** HC: The number of times pgmHCGuestPDWriteHandler() detected a conflict */
1601 STAMCOUNTER StatHCGuestPDWriteConflict;
1602
1603 /** HC: The number of pages marked not present for accessed bit emulation. */
1604 STAMCOUNTER StatHCAccessedPage;
1605 /** HC: The number of pages marked read-only for dirty bit tracking. */
1606 STAMCOUNTER StatHCDirtyPage;
1607 /** HC: The number of pages marked read-only for dirty bit tracking. */
1608 STAMCOUNTER StatHCDirtyPageBig;
1609 /** HC: The number of traps generated for dirty bit tracking. */
1610 STAMCOUNTER StatHCDirtyPageTrap;
1611 /** HC: The number of pages already dirty or readonly. */
1612 STAMCOUNTER StatHCDirtyPageSkipped;
1613
1614 /** GC: The number of pages marked not present for accessed bit emulation. */
1615 STAMCOUNTER StatGCAccessedPage;
1616 /** GC: The number of pages marked read-only for dirty bit tracking. */
1617 STAMCOUNTER StatGCDirtyPage;
1618 /** GC: The number of pages marked read-only for dirty bit tracking. */
1619 STAMCOUNTER StatGCDirtyPageBig;
1620 /** GC: The number of traps generated for dirty bit tracking. */
1621 STAMCOUNTER StatGCDirtyPageTrap;
1622 /** GC: The number of pages already dirty or readonly. */
1623 STAMCOUNTER StatGCDirtyPageSkipped;
1624 /** GC: The number of pages marked dirty because of write accesses. */
1625 STAMCOUNTER StatGCDirtiedPage;
1626 /** GC: The number of pages already marked dirty because of write accesses. */
1627 STAMCOUNTER StatGCPageAlreadyDirty;
1628 /** GC: The number of real pages faults during dirty bit tracking. */
1629 STAMCOUNTER StatGCDirtyTrackRealPF;
1630
1631 /** GC: Profiling of the PGMTrackDirtyBit() body */
1632 STAMPROFILE StatGCDirtyBitTracking;
1633 /** HC: Profiling of the PGMTrackDirtyBit() body */
1634 STAMPROFILE StatHCDirtyBitTracking;
1635
1636 /** GC: Profiling of the PGMGstModifyPage() body */
1637 STAMPROFILE StatGCGstModifyPage;
1638 /** HC: Profiling of the PGMGstModifyPage() body */
1639 STAMPROFILE StatHCGstModifyPage;
1640
1641 /** GC: The number of time we've marked a PD not present from SyncPage to virtualize the accessed bit. */
1642 STAMCOUNTER StatGCSyncPagePDNAs;
1643 /** GC: The number of time we've encountered an out-of-sync PD in SyncPage. */
1644 STAMCOUNTER StatGCSyncPagePDOutOfSync;
1645 /** HC: The number of time we've marked a PD not present from SyncPage to virtualize the accessed bit. */
1646 STAMCOUNTER StatHCSyncPagePDNAs;
1647 /** HC: The number of time we've encountered an out-of-sync PD in SyncPage. */
1648 STAMCOUNTER StatHCSyncPagePDOutOfSync;
1649
1650 STAMCOUNTER StatSynPT4kGC;
1651 STAMCOUNTER StatSynPT4kHC;
1652 STAMCOUNTER StatSynPT4MGC;
1653 STAMCOUNTER StatSynPT4MHC;
1654
1655 /** Profiling of the PGMFlushTLB() body. */
1656 STAMPROFILE StatFlushTLB;
1657 /** The number of times PGMFlushTLB was called with a new CR3, non-global. (switch) */
1658 STAMCOUNTER StatFlushTLBNewCR3;
1659 /** The number of times PGMFlushTLB was called with a new CR3, global. (switch) */
1660 STAMCOUNTER StatFlushTLBNewCR3Global;
1661 /** The number of times PGMFlushTLB was called with the same CR3, non-global. (flush) */
1662 STAMCOUNTER StatFlushTLBSameCR3;
1663 /** The number of times PGMFlushTLB was called with the same CR3, global. (flush) */
1664 STAMCOUNTER StatFlushTLBSameCR3Global;
1665
1666 STAMPROFILE StatGCSyncCR3; /**< GC: PGMSyncCR3() profiling. */
1667 STAMPROFILE StatGCSyncCR3Handlers; /**< GC: Profiling of the PGMSyncCR3() update handler section. */
1668 STAMPROFILE StatGCSyncCR3HandlerVirtualReset; /**< GC: Profiling of the virtual handler resets. */
1669 STAMPROFILE StatGCSyncCR3HandlerVirtualUpdate; /**< GC: Profiling of the virtual handler updates. */
1670 STAMCOUNTER StatGCSyncCR3Global; /**< GC: The number of global CR3 syncs. */
1671 STAMCOUNTER StatGCSyncCR3NotGlobal; /**< GC: The number of non-global CR3 syncs. */
1672 STAMCOUNTER StatGCSyncCR3DstFreed; /**< GC: The number of times we've had to free a shadow entry. */
1673 STAMCOUNTER StatGCSyncCR3DstFreedSrcNP; /**< GC: The number of times we've had to free a shadow entry for which the source entry was not present. */
1674 STAMCOUNTER StatGCSyncCR3DstNotPresent; /**< GC: The number of times we've encountered a not present shadow entry for a present guest entry. */
1675 STAMCOUNTER StatGCSyncCR3DstSkippedGlobalPD; /**< GC: The number of times a global page directory wasn't flushed. */
1676 STAMCOUNTER StatGCSyncCR3DstSkippedGlobalPT; /**< GC: The number of times a page table with only global entries wasn't flushed. */
1677 STAMCOUNTER StatGCSyncCR3DstCacheHit; /**< GC: The number of times we got some kind of cache hit on a page table. */
1678
1679 STAMPROFILE StatHCSyncCR3; /**< HC: PGMSyncCR3() profiling. */
1680 STAMPROFILE StatHCSyncCR3Handlers; /**< HC: Profiling of the PGMSyncCR3() update handler section. */
1681 STAMPROFILE StatHCSyncCR3HandlerVirtualReset; /**< HC: Profiling of the virtual handler resets. */
1682 STAMPROFILE StatHCSyncCR3HandlerVirtualUpdate; /**< HC: Profiling of the virtual handler updates. */
1683 STAMCOUNTER StatHCSyncCR3Global; /**< HC: The number of global CR3 syncs. */
1684 STAMCOUNTER StatHCSyncCR3NotGlobal; /**< HC: The number of non-global CR3 syncs. */
1685 STAMCOUNTER StatHCSyncCR3DstFreed; /**< HC: The number of times we've had to free a shadow entry. */
1686 STAMCOUNTER StatHCSyncCR3DstFreedSrcNP; /**< HC: The number of times we've had to free a shadow entry for which the source entry was not present. */
1687 STAMCOUNTER StatHCSyncCR3DstNotPresent; /**< HC: The number of times we've encountered a not present shadow entry for a present guest entry. */
1688 STAMCOUNTER StatHCSyncCR3DstSkippedGlobalPD; /**< HC: The number of times a global page directory wasn't flushed. */
1689 STAMCOUNTER StatHCSyncCR3DstSkippedGlobalPT; /**< HC: The number of times a page table with only global entries wasn't flushed. */
1690 STAMCOUNTER StatHCSyncCR3DstCacheHit; /**< HC: The number of times we got some kind of cache hit on a page table. */
1691
1692 /** GC: Profiling of pgmHandlerVirtualFindByPhysAddr. */
1693 STAMPROFILE StatVirtHandleSearchByPhysGC;
1694 /** HC: Profiling of pgmHandlerVirtualFindByPhysAddr. */
1695 STAMPROFILE StatVirtHandleSearchByPhysHC;
1696 /** HC: The number of times PGMR3HandlerPhysicalReset is called. */
1697 STAMCOUNTER StatHandlePhysicalReset;
1698
1699 STAMPROFILE StatCheckPageFault;
1700 STAMPROFILE StatLazySyncPT;
1701 STAMPROFILE StatMapping;
1702 STAMPROFILE StatOutOfSync;
1703 STAMPROFILE StatHandlers;
1704 STAMPROFILE StatEIPHandlers;
1705 STAMPROFILE StatHCPrefetch;
1706
1707# ifdef PGMPOOL_WITH_GCPHYS_TRACKING
1708 /** The number of first time shadowings. */
1709 STAMCOUNTER StatTrackVirgin;
1710 /** The number of times switching to cRef2, i.e. the page is being shadowed by two PTs. */
1711 STAMCOUNTER StatTrackAliased;
1712 /** The number of times we're tracking using cRef2. */
1713 STAMCOUNTER StatTrackAliasedMany;
1714 /** The number of times we're hitting pages which has overflowed cRef2. */
1715 STAMCOUNTER StatTrackAliasedLots;
1716 /** The number of times the extent list grows to long. */
1717 STAMCOUNTER StatTrackOverflows;
1718 /** Profiling of SyncPageWorkerTrackDeref (expensive). */
1719 STAMPROFILE StatTrackDeref;
1720# endif
1721
1722 /** Allocated mbs of guest ram */
1723 STAMCOUNTER StatDynRamTotal;
1724 /** Nr of pgmr3PhysGrowRange calls. */
1725 STAMCOUNTER StatDynRamGrow;
1726
1727 STAMCOUNTER StatGCTrap0ePD[X86_PG_ENTRIES];
1728 STAMCOUNTER StatGCSyncPtPD[X86_PG_ENTRIES];
1729 STAMCOUNTER StatGCSyncPagePD[X86_PG_ENTRIES];
1730#endif
1731} PGM, *PPGM;
1732
1733
1734/** @name PGM::fSyncFlags Flags
1735 * @{
1736 */
1737/** Updates the MM_RAM_FLAGS_VIRTUAL_HANDLER page bit. */
1738#define PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL BIT(0)
1739/** Always sync CR3. */
1740#define PGM_SYNC_ALWAYS BIT(1)
1741/** Check monitoring on next CR3 (re)load and invalidate page. */
1742#define PGM_SYNC_MONITOR_CR3 BIT(2)
1743/** Clear the page pool (a light weight flush). */
1744#define PGM_SYNC_CLEAR_PGM_POOL BIT(8)
1745/** @} */
1746
1747
1748__BEGIN_DECLS
1749
1750PGMGCDECL(int) pgmGCGuestPDWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser);
1751PGMDECL(int) pgmGuestROMWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser);
1752PGMGCDECL(int) pgmCachePTWriteGC(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser);
1753int pgmR3SyncPTResolveConflict(PVM pVM, PPGMMAPPING pMapping, PVBOXPD pPDSrc, int iPDOld);
1754PPGMMAPPING pgmGetMapping(PVM pVM, RTGCPTR GCPtr);
1755void pgmR3MapRelocate(PVM pVM, PPGMMAPPING pMapping, int iPDOld, int iPDNew);
1756int pgmR3ChangeMode(PVM pVM, PGMMODE enmGuestMode);
1757int pgmLock(PVM pVM);
1758void pgmUnlock(PVM pVM);
1759
1760void pgmR3HandlerPhysicalUpdateAll(PVM pVM);
1761int pgmHandlerVirtualFindByPhysAddr(PVM pVM, RTGCPHYS GCPhys, PPGMVIRTHANDLER *ppVirt, unsigned *piPage);
1762DECLCALLBACK(int) pgmHandlerVirtualResetOne(PAVLROGCPTRNODECORE pNode, void *pvUser);
1763#ifdef VBOX_STRICT
1764void pgmHandlerVirtualDumpPhysPages(PVM pVM);
1765#else
1766# define pgmHandlerVirtualDumpPhysPages(a) do { } while (0)
1767#endif
1768DECLCALLBACK(void) pgmR3InfoHandlers(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
1769
1770
1771#ifdef IN_RING3
1772int pgmr3PhysGrowRange(PVM pVM, RTGCPHYS GCPhys);
1773
1774int pgmR3PoolInit(PVM pVM);
1775void pgmR3PoolRelocate(PVM pVM);
1776void pgmR3PoolReset(PVM pVM);
1777
1778#endif
1779#ifdef IN_GC
1780void *pgmGCPoolMapPage(PVM pVM, PPGMPOOLPAGE pPage);
1781#endif
1782int pgmPoolAlloc(PVM pVM, RTGCPHYS GCPhys, PGMPOOLKIND enmKind, uint16_t iUser, uint16_t iUserTable, PPPGMPOOLPAGE ppPage);
1783PPGMPOOLPAGE pgmPoolGetPageByHCPhys(PVM pVM, RTHCPHYS HCPhys);
1784void pgmPoolFree(PVM pVM, RTHCPHYS HCPhys, uint16_t iUser, uint16_t iUserTable);
1785void pgmPoolFreeByPage(PPGMPOOL pPool, PPGMPOOLPAGE pPage, uint16_t iUser, uint16_t iUserTable);
1786int pgmPoolFlushPage(PPGMPOOL pPool, PPGMPOOLPAGE pPage);
1787void pgmPoolFlushAll(PVM pVM);
1788void pgmPoolClearAll(PVM pVM);
1789void pgmPoolTrackFlushGCPhysPT(PVM pVM, PRTHCPHYS pHCPhys, uint16_t iShw, uint16_t cRefs);
1790void pgmPoolTrackFlushGCPhysPTs(PVM pVM, PRTHCPHYS pHCPhys, uint16_t iPhysExt);
1791int pgmPoolTrackFlushGCPhysPTsSlow(PVM pVM, PRTHCPHYS pHCPhys);
1792PPGMPOOLPHYSEXT pgmPoolTrackPhysExtAlloc(PVM pVM, uint16_t *piPhysExt);
1793void pgmPoolTrackPhysExtFree(PVM pVM, uint16_t iPhysExt);
1794void pgmPoolTrackPhysExtFreeList(PVM pVM, uint16_t iPhysExt);
1795uint16_t pgmPoolTrackPhysExtAddref(PVM pVM, uint16_t u16, uint16_t iShwPT);
1796void pgmPoolTrackPhysExtDerefGCPhys(PPGMPOOL pPool, PPGMPOOLPAGE pPage, PRTHCPHYS pHCPhys);
1797#ifdef PGMPOOL_WITH_MONITORING
1798# ifdef IN_RING3
1799void pgmPoolMonitorChainChanging(PPGMPOOL pPool, PPGMPOOLPAGE pPage, RTGCPHYS GCPhysFault, RTHCPTR pvAddress, PDISCPUSTATE pCpu);
1800# else
1801void pgmPoolMonitorChainChanging(PPGMPOOL pPool, PPGMPOOLPAGE pPage, RTGCPHYS GCPhysFault, RTGCPTR pvAddress, PDISCPUSTATE pCpu);
1802# endif
1803int pgmPoolMonitorChainFlush(PPGMPOOL pPool, PPGMPOOLPAGE pPage);
1804void pgmPoolMonitorModifiedInsert(PPGMPOOL pPool, PPGMPOOLPAGE pPage);
1805void pgmPoolMonitorModifiedClearAll(PVM pVM);
1806int pgmPoolMonitorMonitorCR3(PPGMPOOL pPool, uint16_t idxRoot, RTGCPHYS GCPhysCR3);
1807int pgmPoolMonitorUnmonitorCR3(PPGMPOOL pPool, uint16_t idxRoot);
1808#endif
1809
1810__END_DECLS
1811
1812
1813/**
1814 * Convert GC Phys to HC Phys.
1815 *
1816 * @returns VBox status.
1817 * @param pPGM PGM handle.
1818 * @param GCPhys The GC physical address.
1819 * @param pHCPhys Where to store the corresponding HC physical address.
1820 */
1821DECLINLINE(int) PGMRamGCPhys2HCPhys(PPGM pPGM, RTGCPHYS GCPhys, PRTHCPHYS pHCPhys)
1822{
1823 /*
1824 * Walk range list.
1825 */
1826 PPGMRAMRANGE pRam = CTXSUFF(pPGM->pRamRanges);
1827 while (pRam)
1828 {
1829 RTGCPHYS off = GCPhys - pRam->GCPhys;
1830 if (off < pRam->cb)
1831 {
1832 unsigned iPage = off >> PAGE_SHIFT;
1833 /* Physical chunk in dynamically allocated range not present? */
1834 if (RT_UNLIKELY(!(pRam->aHCPhys[iPage] & X86_PTE_PAE_PG_MASK)))
1835 {
1836#ifdef IN_RING3
1837 int rc = pgmr3PhysGrowRange(PGM2VM(pPGM), GCPhys);
1838#else
1839 int rc = CTXALLMID(VMM, CallHost)(PGM2VM(pPGM), VMMCALLHOST_PGM_RAM_GROW_RANGE, GCPhys);
1840#endif
1841 if (rc != VINF_SUCCESS)
1842 return rc;
1843 }
1844 *pHCPhys = (pRam->aHCPhys[iPage] & X86_PTE_PAE_PG_MASK) | (off & PAGE_OFFSET_MASK);
1845 return VINF_SUCCESS;
1846 }
1847
1848 pRam = CTXSUFF(pRam->pNext);
1849 }
1850 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
1851}
1852
1853
1854/**
1855 * Convert GC Phys to HC Virt.
1856 *
1857 * @returns VBox status.
1858 * @param pPGM PGM handle.
1859 * @param GCPhys The GC physical address.
1860 * @param pHCPtr Where to store the corresponding HC virtual address.
1861 */
1862DECLINLINE(int) PGMRamGCPhys2HCPtr(PPGM pPGM, RTGCPHYS GCPhys, PRTHCPTR pHCPtr)
1863{
1864 /*
1865 * Walk range list.
1866 */
1867 PPGMRAMRANGE pRam = CTXSUFF(pPGM->pRamRanges);
1868 while (pRam)
1869 {
1870 RTGCPHYS off = GCPhys - pRam->GCPhys;
1871 if (off < pRam->cb)
1872 {
1873 if (pRam->fFlags & MM_RAM_FLAGS_DYNAMIC_ALLOC)
1874 {
1875 unsigned idx = (off >> PGM_DYNAMIC_CHUNK_SHIFT);
1876 /* Physical chunk in dynamically allocated range not present? */
1877 if (RT_UNLIKELY(!CTXSUFF(pRam->pavHCChunk)[idx]))
1878 {
1879#ifdef IN_RING3
1880 int rc = pgmr3PhysGrowRange(PGM2VM(pPGM), GCPhys);
1881#else
1882 int rc = CTXALLMID(VMM, CallHost)(PGM2VM(pPGM), VMMCALLHOST_PGM_RAM_GROW_RANGE, GCPhys);
1883#endif
1884 if (rc != VINF_SUCCESS)
1885 return rc;
1886 }
1887 *pHCPtr = (RTHCPTR)((RTHCUINTPTR)CTXSUFF(pRam->pavHCChunk)[idx] + (off & PGM_DYNAMIC_CHUNK_OFFSET_MASK));
1888 return VINF_SUCCESS;
1889 }
1890 if (pRam->pvHC)
1891 {
1892 *pHCPtr = (RTHCPTR)((RTHCUINTPTR)pRam->pvHC + off);
1893 return VINF_SUCCESS;
1894 }
1895 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
1896 }
1897
1898 pRam = CTXSUFF(pRam->pNext);
1899 }
1900 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
1901}
1902
1903
1904/**
1905 * Convert GC Phys to HC Virt.
1906 *
1907 * @returns VBox status.
1908 * @param PVM VM handle.
1909 * @param pRam Ram range
1910 * @param GCPhys The GC physical address.
1911 * @param pHCPtr Where to store the corresponding HC virtual address.
1912 */
1913DECLINLINE(int) PGMRamGCPhys2HCPtr(PVM pVM, PPGMRAMRANGE pRam, RTGCPHYS GCPhys, PRTHCPTR pHCPtr)
1914{
1915 RTGCPHYS off = GCPhys - pRam->GCPhys;
1916 Assert(off < pRam->cb);
1917
1918 if (pRam->fFlags & MM_RAM_FLAGS_DYNAMIC_ALLOC)
1919 {
1920 unsigned idx = (off >> PGM_DYNAMIC_CHUNK_SHIFT);
1921 /* Physical chunk in dynamically allocated range not present? */
1922 if (RT_UNLIKELY(!CTXSUFF(pRam->pavHCChunk)[idx]))
1923 {
1924#ifdef IN_RING3
1925 int rc = pgmr3PhysGrowRange(pVM, GCPhys);
1926#else
1927 int rc = CTXALLMID(VMM, CallHost)(pVM, VMMCALLHOST_PGM_RAM_GROW_RANGE, GCPhys);
1928#endif
1929 if (rc != VINF_SUCCESS)
1930 return rc;
1931 }
1932 *pHCPtr = (RTHCPTR)((RTHCUINTPTR)CTXSUFF(pRam->pavHCChunk)[idx] + (off & PGM_DYNAMIC_CHUNK_OFFSET_MASK));
1933 return VINF_SUCCESS;
1934 }
1935 if (pRam->pvHC)
1936 {
1937 *pHCPtr = (RTHCPTR)((RTHCUINTPTR)pRam->pvHC + off);
1938 return VINF_SUCCESS;
1939 }
1940 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
1941}
1942
1943
1944/**
1945 * Convert GC Phys to HC Virt and HC Phys.
1946 *
1947 * @returns VBox status.
1948 * @param pPGM PGM handle.
1949 * @param GCPhys The GC physical address.
1950 * @param pHCPtr Where to store the corresponding HC virtual address.
1951 * @param pHCPhys Where to store the HC Physical address and its flags.
1952 */
1953DECLINLINE(int) PGMRamGCPhys2HCPtrAndHCPhysWithFlags(PPGM pPGM, RTGCPHYS GCPhys, PRTHCPTR pHCPtr, PRTHCPHYS pHCPhys)
1954{
1955 /*
1956 * Walk range list.
1957 */
1958 PPGMRAMRANGE pRam = CTXSUFF(pPGM->pRamRanges);
1959 while (pRam)
1960 {
1961 RTGCPHYS off = GCPhys - pRam->GCPhys;
1962 if (off < pRam->cb)
1963 {
1964 unsigned iPage = off >> PAGE_SHIFT;
1965 /* Physical chunk in dynamically allocated range not present? */
1966 if (RT_UNLIKELY(!(pRam->aHCPhys[iPage] & X86_PTE_PAE_PG_MASK)))
1967 {
1968#ifdef IN_RING3
1969 int rc = pgmr3PhysGrowRange(PGM2VM(pPGM), GCPhys);
1970#else
1971 int rc = CTXALLMID(VMM, CallHost)(PGM2VM(pPGM), VMMCALLHOST_PGM_RAM_GROW_RANGE, GCPhys);
1972#endif
1973 if (rc != VINF_SUCCESS)
1974 return rc;
1975 }
1976 *pHCPhys = pRam->aHCPhys[iPage];
1977
1978 if (pRam->fFlags & MM_RAM_FLAGS_DYNAMIC_ALLOC)
1979 {
1980 unsigned idx = (off >> PGM_DYNAMIC_CHUNK_SHIFT);
1981 *pHCPtr = (RTHCPTR)((RTHCUINTPTR)CTXSUFF(pRam->pavHCChunk)[idx] + (off & PGM_DYNAMIC_CHUNK_OFFSET_MASK));
1982 return VINF_SUCCESS;
1983 }
1984 if (pRam->pvHC)
1985 {
1986 *pHCPtr = (RTHCPTR)((RTHCUINTPTR)pRam->pvHC + off);
1987 return VINF_SUCCESS;
1988 }
1989 *pHCPtr = 0;
1990 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
1991 }
1992
1993 pRam = CTXSUFF(pRam->pNext);
1994 }
1995 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
1996}
1997
1998
1999/**
2000 * Convert GC Phys page to a page entry pointer.
2001 *
2002 * This is used by code which may have to update the flags.
2003 *
2004 * @returns VBox status.
2005 * @param pPGM PGM handle.
2006 * @param GCPhys The GC physical address.
2007 * @param ppHCPhys Where to store the pointer to the page entry.
2008 */
2009DECLINLINE(int) PGMRamGCPhys2PagePtr(PPGM pPGM, RTGCPHYS GCPhys, PRTHCPHYS *ppHCPhys)
2010{
2011 /*
2012 * Walk range list.
2013 */
2014 PPGMRAMRANGE pRam = CTXSUFF(pPGM->pRamRanges);
2015 while (pRam)
2016 {
2017 RTGCPHYS off = GCPhys - pRam->GCPhys;
2018 if (off < pRam->cb)
2019 {
2020 unsigned iPage = off >> PAGE_SHIFT;
2021 /* Physical chunk in dynamically allocated range not present? */
2022 if (RT_UNLIKELY(!(pRam->aHCPhys[iPage] & X86_PTE_PAE_PG_MASK)))
2023 {
2024#ifdef IN_RING3
2025 int rc = pgmr3PhysGrowRange(PGM2VM(pPGM), GCPhys);
2026#else
2027 int rc = CTXALLMID(VMM, CallHost)(PGM2VM(pPGM), VMMCALLHOST_PGM_RAM_GROW_RANGE, GCPhys);
2028#endif
2029 if (rc != VINF_SUCCESS)
2030 return rc;
2031 }
2032 *ppHCPhys = &pRam->aHCPhys[iPage];
2033 return VINF_SUCCESS;
2034 }
2035
2036 pRam = CTXSUFF(pRam->pNext);
2037 }
2038 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
2039}
2040
2041
2042/**
2043 * Convert GC Phys page to HC Phys page and flags.
2044 *
2045 * @returns VBox status.
2046 * @param pPGM PGM handle.
2047 * @param GCPhys The GC physical address.
2048 * @param pHCPhys Where to store the corresponding HC physical address of the page
2049 * and the page flags.
2050 */
2051DECLINLINE(int) PGMRamGCPhys2HCPhysWithFlags(PPGM pPGM, RTGCPHYS GCPhys, PRTHCPHYS pHCPhys)
2052{
2053 /*
2054 * Walk range list.
2055 */
2056 PPGMRAMRANGE pRam = CTXSUFF(pPGM->pRamRanges);
2057 while (pRam)
2058 {
2059 RTGCPHYS off = GCPhys - pRam->GCPhys;
2060 if (off < pRam->cb)
2061 {
2062 unsigned iPage = off >> PAGE_SHIFT;
2063 /* Physical chunk in dynamically allocated range not present? */
2064 if (RT_UNLIKELY(!(pRam->aHCPhys[iPage] & X86_PTE_PAE_PG_MASK)))
2065 {
2066#ifdef IN_RING3
2067 int rc = pgmr3PhysGrowRange(PGM2VM(pPGM), GCPhys);
2068#else
2069 int rc = CTXALLMID(VMM, CallHost)(PGM2VM(pPGM), VMMCALLHOST_PGM_RAM_GROW_RANGE, GCPhys);
2070#endif
2071 if (rc != VINF_SUCCESS)
2072 return rc;
2073 }
2074 *pHCPhys = pRam->aHCPhys[iPage];
2075 return VINF_SUCCESS;
2076 }
2077
2078 pRam = CTXSUFF(pRam->pNext);
2079 }
2080 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
2081}
2082
2083
2084/**
2085 * Clears flags associated with a RAM address.
2086 *
2087 * @returns VBox status code.
2088 * @param pPGM PGM handle.
2089 * @param GCPhys Guest context physical address.
2090 * @param fFlags fFlags to clear. (Bits 0-11.)
2091 */
2092DECLINLINE(int) PGMRamFlagsClearByGCPhys(PPGM pPGM, RTGCPHYS GCPhys, unsigned fFlags)
2093{
2094 /*
2095 * Walk range list.
2096 */
2097 PPGMRAMRANGE pRam = CTXSUFF(pPGM->pRamRanges);
2098 while (pRam)
2099 {
2100 RTGCPHYS off = GCPhys - pRam->GCPhys;
2101 if (off < pRam->cb)
2102 {
2103 unsigned iPage = off >> PAGE_SHIFT;
2104 /* Physical chunk in dynamically allocated range not present? */
2105 if (RT_UNLIKELY(!(pRam->aHCPhys[iPage] & X86_PTE_PAE_PG_MASK)))
2106 {
2107#ifdef IN_RING3
2108 int rc = pgmr3PhysGrowRange(PGM2VM(pPGM), GCPhys);
2109#else
2110 int rc = CTXALLMID(VMM, CallHost)(PGM2VM(pPGM), VMMCALLHOST_PGM_RAM_GROW_RANGE, GCPhys);
2111#endif
2112 if (rc != VINF_SUCCESS)
2113 return rc;
2114 }
2115 fFlags &= ~X86_PTE_PAE_PG_MASK;
2116 pRam->aHCPhys[iPage] &= ~(RTHCPHYS)fFlags;
2117 return VINF_SUCCESS;
2118 }
2119
2120 pRam = CTXSUFF(pRam->pNext);
2121 }
2122 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
2123}
2124
2125
2126/**
2127 * Clears flags associated with a RAM address.
2128 *
2129 * @returns VBox status code.
2130 * @param pPGM PGM handle.
2131 * @param GCPhys Guest context physical address.
2132 * @param fFlags fFlags to clear. (Bits 0-11.)
2133 * @param ppRamHint Where to read and store the ram list hint.
2134 * The caller initializes this to NULL before the call.
2135 */
2136DECLINLINE(int) PGMRamFlagsClearByGCPhysWithHint(PPGM pPGM, RTGCPHYS GCPhys, unsigned fFlags, PPGMRAMRANGE *ppRamHint)
2137{
2138 /*
2139 * Check the hint.
2140 */
2141 PPGMRAMRANGE pRam = *ppRamHint;
2142 if (pRam)
2143 {
2144 RTGCPHYS off = GCPhys - pRam->GCPhys;
2145 if (off < pRam->cb)
2146 {
2147 unsigned iPage = off >> PAGE_SHIFT;
2148 /* Physical chunk in dynamically allocated range not present? */
2149 if (RT_UNLIKELY(!(pRam->aHCPhys[iPage] & X86_PTE_PAE_PG_MASK)))
2150 {
2151#ifdef IN_RING3
2152 int rc = pgmr3PhysGrowRange(PGM2VM(pPGM), GCPhys);
2153#else
2154 int rc = CTXALLMID(VMM, CallHost)(PGM2VM(pPGM), VMMCALLHOST_PGM_RAM_GROW_RANGE, GCPhys);
2155#endif
2156 if (rc != VINF_SUCCESS)
2157 return rc;
2158 }
2159 fFlags &= ~X86_PTE_PAE_PG_MASK;
2160 pRam->aHCPhys[iPage] &= ~(RTHCPHYS)fFlags;
2161 return VINF_SUCCESS;
2162 }
2163 }
2164
2165 /*
2166 * Walk range list.
2167 */
2168 pRam = CTXSUFF(pPGM->pRamRanges);
2169 while (pRam)
2170 {
2171 RTGCPHYS off = GCPhys - pRam->GCPhys;
2172 if (off < pRam->cb)
2173 {
2174 unsigned iPage = off >> PAGE_SHIFT;
2175 /* Physical chunk in dynamically allocated range not present? */
2176 if (RT_UNLIKELY(!(pRam->aHCPhys[iPage] & X86_PTE_PAE_PG_MASK)))
2177 {
2178#ifdef IN_RING3
2179 int rc = pgmr3PhysGrowRange(PGM2VM(pPGM), GCPhys);
2180#else
2181 int rc = CTXALLMID(VMM, CallHost)(PGM2VM(pPGM), VMMCALLHOST_PGM_RAM_GROW_RANGE, GCPhys);
2182#endif
2183 if (rc != VINF_SUCCESS)
2184 return rc;
2185 }
2186 fFlags &= ~X86_PTE_PAE_PG_MASK;
2187 pRam->aHCPhys[iPage] &= ~(RTHCPHYS)fFlags;
2188 *ppRamHint = pRam;
2189 return VINF_SUCCESS;
2190 }
2191
2192 pRam = CTXSUFF(pRam->pNext);
2193 }
2194 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
2195}
2196
2197/**
2198 * Sets (bitwise OR) flags associated with a RAM address.
2199 *
2200 * @returns VBox status code.
2201 * @param pPGM PGM handle.
2202 * @param GCPhys Guest context physical address.
2203 * @param fFlags fFlags to set clear. (Bits 0-11.)
2204 */
2205DECLINLINE(int) PGMRamFlagsSetByGCPhys(PPGM pPGM, RTGCPHYS GCPhys, unsigned fFlags)
2206{
2207 /*
2208 * Walk range list.
2209 */
2210 PPGMRAMRANGE pRam = CTXSUFF(pPGM->pRamRanges);
2211 while (pRam)
2212 {
2213 RTGCPHYS off = GCPhys - pRam->GCPhys;
2214 if (off < pRam->cb)
2215 {
2216 unsigned iPage = off >> PAGE_SHIFT;
2217 /* Physical chunk in dynamically allocated range not present? */
2218 if (RT_UNLIKELY(!(pRam->aHCPhys[iPage] & X86_PTE_PAE_PG_MASK)))
2219 {
2220#ifdef IN_RING3
2221 int rc = pgmr3PhysGrowRange(PGM2VM(pPGM), GCPhys);
2222#else
2223 int rc = CTXALLMID(VMM, CallHost)(PGM2VM(pPGM), VMMCALLHOST_PGM_RAM_GROW_RANGE, GCPhys);
2224#endif
2225 if (rc != VINF_SUCCESS)
2226 return rc;
2227 }
2228 fFlags &= ~X86_PTE_PAE_PG_MASK;
2229 pRam->aHCPhys[iPage] |= fFlags;
2230 return VINF_SUCCESS;
2231 }
2232
2233 pRam = CTXSUFF(pRam->pNext);
2234 }
2235 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
2236}
2237
2238/**
2239 * Sets (bitwise OR) flags associated with a RAM address.
2240 *
2241 * @returns VBox status code.
2242 * @param pPGM PGM handle.
2243 * @param GCPhys Guest context physical address.
2244 * @param fFlags fFlags to set clear. (Bits 0-11.)
2245 * @param ppRamHint Where to read and store the ram list hint.
2246 * The caller initializes this to NULL before the call.
2247 */
2248DECLINLINE(int) PGMRamFlagsSetByGCPhysWithHint(PPGM pPGM, RTGCPHYS GCPhys, unsigned fFlags, PPGMRAMRANGE *ppRamHint)
2249{
2250 /*
2251 * Check the hint.
2252 */
2253 PPGMRAMRANGE pRam = *ppRamHint;
2254 if (pRam)
2255 {
2256 RTGCPHYS off = GCPhys - pRam->GCPhys;
2257 if (off < pRam->cb)
2258 {
2259 unsigned iPage = off >> PAGE_SHIFT;
2260 /* Physical chunk in dynamically allocated range not present? */
2261 if (RT_UNLIKELY(!(pRam->aHCPhys[iPage] & X86_PTE_PAE_PG_MASK)))
2262 {
2263#ifdef IN_RING3
2264 int rc = pgmr3PhysGrowRange(PGM2VM(pPGM), GCPhys);
2265#else
2266 int rc = CTXALLMID(VMM, CallHost)(PGM2VM(pPGM), VMMCALLHOST_PGM_RAM_GROW_RANGE, GCPhys);
2267#endif
2268 if (rc != VINF_SUCCESS)
2269 return rc;
2270 }
2271 fFlags &= ~X86_PTE_PAE_PG_MASK;
2272 pRam->aHCPhys[iPage] |= fFlags;
2273 return VINF_SUCCESS;
2274 }
2275 }
2276
2277 /*
2278 * Walk range list.
2279 */
2280 pRam = CTXSUFF(pPGM->pRamRanges);
2281 while (pRam)
2282 {
2283 RTGCPHYS off = GCPhys - pRam->GCPhys;
2284 if (off < pRam->cb)
2285 {
2286 unsigned iPage = off >> PAGE_SHIFT;
2287 /* Physical chunk in dynamically allocated range not present? */
2288 if (RT_UNLIKELY(!(pRam->aHCPhys[iPage] & X86_PTE_PAE_PG_MASK)))
2289 {
2290#ifdef IN_RING3
2291 int rc = pgmr3PhysGrowRange(PGM2VM(pPGM), GCPhys);
2292#else
2293 int rc = CTXALLMID(VMM, CallHost)(PGM2VM(pPGM), VMMCALLHOST_PGM_RAM_GROW_RANGE, GCPhys);
2294#endif
2295 if (rc != VINF_SUCCESS)
2296 return rc;
2297 }
2298 fFlags &= ~X86_PTE_PAE_PG_MASK;
2299 pRam->aHCPhys[iPage] |= fFlags;
2300 *ppRamHint = pRam;
2301 return VINF_SUCCESS;
2302 }
2303
2304 pRam = CTXSUFF(pRam->pNext);
2305 }
2306 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
2307}
2308
2309
2310/**
2311 * Gets the page directory for the specified address.
2312 *
2313 * @returns Pointer to the page directory in question.
2314 * @returns NULL if the page directory is not present or on an invalid page.
2315 * @param pPGM Pointer to the PGM instance data.
2316 * @param GCPtr The address.
2317 */
2318DECLINLINE(PX86PDPAE) pgmGstGetPaePD(PPGM pPGM, RTGCUINTPTR GCPtr)
2319{
2320 const unsigned iPdPtr = GCPtr >> X86_PDPTR_SHIFT;
2321 if (CTXSUFF(pPGM->pGstPaePDPTR)->a[iPdPtr].n.u1Present)
2322 {
2323 if ((CTXSUFF(pPGM->pGstPaePDPTR)->a[iPdPtr].u & X86_PDPE_PG_MASK) == pPGM->aGCPhysGstPaePDs[iPdPtr])
2324 return CTXSUFF(pPGM->apGstPaePDs)[iPdPtr];
2325
2326 /* cache is out-of-sync. */
2327 PX86PDPAE pPD;
2328 int rc = PGM_GCPHYS_2_PTR(PGM2VM(pPGM), CTXSUFF(pPGM->pGstPaePDPTR)->a[iPdPtr].u & X86_PDPE_PG_MASK, &pPD);
2329 if (VBOX_SUCCESS(rc))
2330 return pPD;
2331 AssertMsgFailed(("Impossible! rc=%d PDPE=%#llx\n", rc, CTXSUFF(pPGM->pGstPaePDPTR)->a[iPdPtr].u));
2332 /* returning NIL_RTGCPHYS is ok if we assume it's just an invalid page of some kind emualted as all 0s. */
2333 }
2334 return NULL;
2335}
2336
2337
2338/**
2339 * Gets the page directory entry for the specified address.
2340 *
2341 * @returns Pointer to the page directory entry in question.
2342 * @returns NULL if the page directory is not present or on an invalid page.
2343 * @param pPGM Pointer to the PGM instance data.
2344 * @param GCPtr The address.
2345 */
2346DECLINLINE(PX86PDEPAE) pgmGstGetPaePDEPtr(PPGM pPGM, RTGCUINTPTR GCPtr)
2347{
2348 const unsigned iPdPtr = GCPtr >> X86_PDPTR_SHIFT;
2349 if (CTXSUFF(pPGM->pGstPaePDPTR)->a[iPdPtr].n.u1Present)
2350 {
2351 const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
2352 if ((CTXSUFF(pPGM->pGstPaePDPTR)->a[iPdPtr].u & X86_PDPE_PG_MASK) == pPGM->aGCPhysGstPaePDs[iPdPtr])
2353 return &CTXSUFF(pPGM->apGstPaePDs)[iPdPtr]->a[iPD];
2354
2355 /* cache is out-of-sync. */
2356 PX86PDPAE pPD;
2357 int rc = PGM_GCPHYS_2_PTR(PGM2VM(pPGM), CTXSUFF(pPGM->pGstPaePDPTR)->a[iPdPtr].u & X86_PDPE_PG_MASK, &pPD);
2358 if (VBOX_SUCCESS(rc))
2359 return &pPD->a[iPD];
2360 AssertMsgFailed(("Impossible! rc=%d PDPE=%#llx\n", rc, CTXSUFF(pPGM->pGstPaePDPTR)->a[iPdPtr].u));
2361 /* returning NIL_RTGCPHYS is ok if we assume it's just an invalid page or something which we'll emulate as all 0s. */
2362 }
2363 return NULL;
2364}
2365
2366
2367/**
2368 * Gets the page directory entry for the specified address.
2369 *
2370 * @returns The page directory entry in question.
2371 * @returns A non-present entry if the page directory is not present or on an invalid page.
2372 * @param pPGM Pointer to the PGM instance data.
2373 * @param GCPtr The address.
2374 */
2375DECLINLINE(uint64_t) pgmGstGetPaePDE(PPGM pPGM, RTGCUINTPTR GCPtr)
2376{
2377 const unsigned iPdPtr = GCPtr >> X86_PDPTR_SHIFT;
2378 if (CTXSUFF(pPGM->pGstPaePDPTR)->a[iPdPtr].n.u1Present)
2379 {
2380 const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
2381 if ((CTXSUFF(pPGM->pGstPaePDPTR)->a[iPdPtr].u & X86_PDPE_PG_MASK) == pPGM->aGCPhysGstPaePDs[iPdPtr])
2382 return CTXSUFF(pPGM->apGstPaePDs)[iPdPtr]->a[iPD].u;
2383
2384 /* cache is out-of-sync. */
2385 PX86PDPAE pPD;
2386 int rc = PGM_GCPHYS_2_PTR(PGM2VM(pPGM), CTXSUFF(pPGM->pGstPaePDPTR)->a[iPdPtr].u & X86_PDPE_PG_MASK, &pPD);
2387 if (VBOX_SUCCESS(rc))
2388 return pPD->a[iPD].u;
2389 AssertMsgFailed(("Impossible! rc=%d PDPE=%#llx\n", rc, CTXSUFF(pPGM->pGstPaePDPTR)->a[iPdPtr].u));
2390 }
2391 return 0;
2392}
2393
2394
2395/**
2396 * Checks if any of the specified page flags are set for the given page.
2397 *
2398 * @returns true if any of the flags are set.
2399 * @returns false if all the flags are clear.
2400 * @param pPGM PGM handle.
2401 * @param GCPhys The GC physical address.
2402 * @param fFlags The flags to check for.
2403 */
2404DECLINLINE(bool) PGMRamTestFlags(PPGM pPGM, RTGCPHYS GCPhys, uint64_t fFlags)
2405{
2406 /*
2407 * Walk range list.
2408 */
2409 for (PPGMRAMRANGE pRam = CTXSUFF(pPGM->pRamRanges);
2410 pRam;
2411 pRam = CTXSUFF(pRam->pNext))
2412 {
2413 RTGCPHYS off = GCPhys - pRam->GCPhys;
2414 if (off < pRam->cb)
2415 return (pRam->aHCPhys[off >> PAGE_SHIFT] & fFlags) != 0;
2416 }
2417 return false;
2418}
2419
2420
2421/**
2422 * Gets the ram flags for a handler.
2423 *
2424 * @returns The ram flags.
2425 * @param pCur The physical handler in question.
2426 */
2427DECLINLINE(unsigned) pgmHandlerPhysicalCalcFlags(PPGMPHYSHANDLER pCur)
2428{
2429 switch (pCur->enmType)
2430 {
2431 case PGMPHYSHANDLERTYPE_PHYSICAL:
2432 return MM_RAM_FLAGS_PHYSICAL_HANDLER;
2433
2434 case PGMPHYSHANDLERTYPE_PHYSICAL_WRITE:
2435 return MM_RAM_FLAGS_PHYSICAL_HANDLER | MM_RAM_FLAGS_PHYSICAL_WRITE;
2436
2437 case PGMPHYSHANDLERTYPE_MMIO:
2438 case PGMPHYSHANDLERTYPE_PHYSICAL_ALL:
2439 return MM_RAM_FLAGS_PHYSICAL_HANDLER | MM_RAM_FLAGS_PHYSICAL_ALL;
2440
2441 default:
2442 AssertFatalMsgFailed(("Invalid type %d\n", pCur->enmType));
2443 }
2444}
2445
2446
2447/**
2448 * Clears one physical page of a virtual handler
2449 *
2450 * @param pPGM Pointer to the PGM instance.
2451 * @param pCur Virtual handler structure
2452 * @param iPage Physical page index
2453 */
2454DECLINLINE(void) pgmHandlerVirtualClearPage(PPGM pPGM, PPGMVIRTHANDLER pCur, unsigned iPage)
2455{
2456 const PPGMPHYS2VIRTHANDLER pPhys2Virt = &pCur->aPhysToVirt[iPage];
2457
2458 /*
2459 * Remove the node from the tree (it's supposed to be in the tree if we get here!).
2460 */
2461#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
2462 AssertReleaseMsg(pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_IN_TREE,
2463 ("pPhys2Virt=%p:{.Core.Key=%VGp, .Core.KeyLast=%VGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
2464 pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias));
2465#endif
2466 if (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_IS_HEAD)
2467 {
2468 /* We're the head of the alias chain. */
2469 PPGMPHYS2VIRTHANDLER pRemove = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysRemove(&pPGM->CTXSUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key); NOREF(pRemove);
2470#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
2471 AssertReleaseMsg(pRemove != NULL,
2472 ("pPhys2Virt=%p:{.Core.Key=%VGp, .Core.KeyLast=%VGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
2473 pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias));
2474 AssertReleaseMsg(pRemove == pPhys2Virt,
2475 ("wanted: pPhys2Virt=%p:{.Core.Key=%VGp, .Core.KeyLast=%VGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n"
2476 " got: pRemove=%p:{.Core.Key=%VGp, .Core.KeyLast=%VGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
2477 pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias,
2478 pRemove, pRemove->Core.Key, pRemove->Core.KeyLast, pRemove->offVirtHandler, pRemove->offNextAlias));
2479#endif
2480 if (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK)
2481 {
2482 /* Insert the next list in the alias chain into the tree. */
2483 PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
2484#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
2485 AssertReleaseMsg(pNext->offNextAlias & PGMPHYS2VIRTHANDLER_IN_TREE,
2486 ("pNext=%p:{.Core.Key=%VGp, .Core.KeyLast=%VGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
2487 pNext, pNext->Core.Key, pNext->Core.KeyLast, pNext->offVirtHandler, pNext->offNextAlias));
2488#endif
2489 pNext->offNextAlias |= PGMPHYS2VIRTHANDLER_IS_HEAD;
2490 bool fRc = RTAvlroGCPhysInsert(&pPGM->CTXSUFF(pTrees)->PhysToVirtHandlers, &pNext->Core);
2491 AssertRelease(fRc);
2492 }
2493 }
2494 else
2495 {
2496 /* Locate the previous node in the alias chain. */
2497 PPGMPHYS2VIRTHANDLER pPrev = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGet(&pPGM->CTXSUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key);
2498#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
2499 AssertReleaseMsg(pPrev != pPhys2Virt,
2500 ("pPhys2Virt=%p:{.Core.Key=%VGp, .Core.KeyLast=%VGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} pPrev=%p\n",
2501 pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias, pPrev));
2502#endif
2503 for (;;)
2504 {
2505 PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPrev + (pPrev->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
2506 if (pNext == pPhys2Virt)
2507 {
2508 /* unlink. */
2509 LogFlow(("pgmHandlerVirtualClearPage: removed %p:{.offNextAlias=%#RX32} from alias chain. prev %p:{.offNextAlias=%#RX32} [%VGp-%VGp]\n",
2510 pPhys2Virt, pPhys2Virt->offNextAlias, pPrev, pPrev->offNextAlias, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast));
2511 if (!(pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK))
2512 pPrev->offNextAlias &= ~PGMPHYS2VIRTHANDLER_OFF_MASK;
2513 else
2514 {
2515 PPGMPHYS2VIRTHANDLER pNewNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
2516 pPrev->offNextAlias = ((intptr_t)pNewNext - (intptr_t)pPrev)
2517 | (pPrev->offNextAlias & ~PGMPHYS2VIRTHANDLER_OFF_MASK);
2518 }
2519 break;
2520 }
2521
2522 /* next */
2523 if (pNext == pPrev)
2524 {
2525#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
2526 AssertReleaseMsg(pNext != pPrev,
2527 ("pPhys2Virt=%p:{.Core.Key=%VGp, .Core.KeyLast=%VGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} pPrev=%p\n",
2528 pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias, pPrev));
2529#endif
2530 break;
2531 }
2532 pPrev = pNext;
2533 }
2534 }
2535 Log2(("PHYS2VIRT: Removing %VGp-%VGp %#RX32 %s\n",
2536 pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offNextAlias, HCSTRING(pCur->pszDesc)));
2537 pPhys2Virt->offNextAlias = 0;
2538 pPhys2Virt->Core.KeyLast = NIL_RTGCPHYS; /* require reinsert */
2539
2540 /*
2541 * Clear the ram flags for this page.
2542 */
2543 int rc = PGMRamFlagsClearByGCPhys(pPGM, pPhys2Virt->Core.Key,
2544 MM_RAM_FLAGS_VIRTUAL_HANDLER | MM_RAM_FLAGS_VIRTUAL_ALL | MM_RAM_FLAGS_VIRTUAL_WRITE);
2545 AssertRC(rc);
2546}
2547
2548
2549/**
2550 * Internal worker for finding a 'in-use' shadow page give by it's physical address.
2551 *
2552 * @returns Pointer to the shadow page structure.
2553 * @param pPool The pool.
2554 * @param HCPhys The HC physical address of the shadow page.
2555 */
2556DECLINLINE(PPGMPOOLPAGE) pgmPoolGetPage(PPGMPOOL pPool, RTHCPHYS HCPhys)
2557{
2558 /*
2559 * Look up the page.
2560 */
2561 PPGMPOOLPAGE pPage = (PPGMPOOLPAGE)RTAvloHCPhysGet(&pPool->HCPhysTree, HCPhys & X86_PTE_PAE_PG_MASK);
2562 AssertFatalMsg(pPage && pPage->enmKind != PGMPOOLKIND_FREE, ("HCPhys=%VHp pPage=%p type=%d\n", HCPhys, pPage, (pPage) ? pPage->enmKind : 0));
2563 return pPage;
2564}
2565
2566
2567/**
2568 * Internal worker for finding a 'in-use' shadow page give by it's physical address.
2569 *
2570 * @returns Pointer to the shadow page structure.
2571 * @param pPool The pool.
2572 * @param idx The pool page index.
2573 */
2574DECLINLINE(PPGMPOOLPAGE) pgmPoolGetPageByIdx(PPGMPOOL pPool, unsigned idx)
2575{
2576 AssertFatalMsg(idx >= PGMPOOL_IDX_FIRST && idx < pPool->cCurPages, ("idx=%d\n", idx));
2577 return &pPool->aPages[idx];
2578}
2579
2580
2581#ifdef PGMPOOL_WITH_GCPHYS_TRACKING
2582/**
2583 * Clear references to guest physical memory.
2584 *
2585 * @param pPool The pool.
2586 * @param pPage The page.
2587 * @param pHCPhys Pointer to the aHCPhys entry in the ram range.
2588 */
2589DECLINLINE(void) pgmTrackDerefGCPhys(PPGMPOOL pPool, PPGMPOOLPAGE pPage, PRTHCPHYS pHCPhys)
2590{
2591 /*
2592 * Just deal with the simple case here.
2593 */
2594#ifdef LOG_ENABLED
2595 const RTHCPHYS HCPhysOrg = *pHCPhys;
2596#endif
2597 const unsigned cRefs = *pHCPhys >> MM_RAM_FLAGS_CREFS_SHIFT;
2598 if (cRefs == 1)
2599 {
2600 Assert(pPage->idx == ((*pHCPhys >> MM_RAM_FLAGS_IDX_SHIFT) & MM_RAM_FLAGS_IDX_MASK));
2601 *pHCPhys = *pHCPhys & MM_RAM_FLAGS_NO_REFS_MASK;
2602 }
2603 else
2604 pgmPoolTrackPhysExtDerefGCPhys(pPool, pPage, pHCPhys);
2605 LogFlow(("pgmTrackDerefGCPhys: *pHCPhys=%RHp -> %RHp\n", HCPhysOrg, *pHCPhys));
2606}
2607#endif
2608
2609
2610#ifdef PGMPOOL_WITH_CACHE
2611/**
2612 * Moves the page to the head of the age list.
2613 *
2614 * This is done when the cached page is used in one way or another.
2615 *
2616 * @param pPool The pool.
2617 * @param pPage The cached page.
2618 * @todo inline in PGMInternal.h!
2619 */
2620DECLINLINE(void) pgmPoolCacheUsed(PPGMPOOL pPool, PPGMPOOLPAGE pPage)
2621{
2622 /*
2623 * Move to the head of the age list.
2624 */
2625 if (pPage->iAgePrev != NIL_PGMPOOL_IDX)
2626 {
2627 /* unlink */
2628 pPool->aPages[pPage->iAgePrev].iAgeNext = pPage->iAgeNext;
2629 if (pPage->iAgeNext != NIL_PGMPOOL_IDX)
2630 pPool->aPages[pPage->iAgeNext].iAgePrev = pPage->iAgePrev;
2631 else
2632 pPool->iAgeTail = pPage->iAgePrev;
2633
2634 /* insert at head */
2635 pPage->iAgePrev = NIL_PGMPOOL_IDX;
2636 pPage->iAgeNext = pPool->iAgeHead;
2637 Assert(pPage->iAgeNext != NIL_PGMPOOL_IDX); /* we would've already been head then */
2638 pPool->iAgeHead = pPage->idx;
2639 pPool->aPages[pPage->iAgeNext].iAgePrev = pPage->idx;
2640 }
2641}
2642#endif /* PGMPOOL_WITH_CACHE */
2643
2644/**
2645 * Tells if mappings are to be put into the shadow page table or not
2646 *
2647 * @returns boolean result
2648 * @param pVM VM handle.
2649 */
2650
2651DECLINLINE(bool) pgmMapAreMappingsEnabled(PPGM pPGM)
2652{
2653 return !pPGM->fDisableMappings;
2654}
2655
2656/** @} */
2657
2658#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