1
/* $Id: PGMInline.h $ */
3
* PGM - Inlined functions.
7
* Copyright (C) 2006-2010 Oracle Corporation
9
* This file is part of VirtualBox Open Source Edition (OSE), as
10
* available from http://www.virtualbox.org. This file is free software;
11
* you can redistribute it and/or modify it under the terms of the GNU
12
* General Public License (GPL) as published by the Free Software
13
* Foundation, in version 2 as it comes in the "COPYING" file of the
14
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18
#ifndef ___PGMInline_h
19
#define ___PGMInline_h
21
#include <VBox/cdefs.h>
22
#include <VBox/types.h>
24
#include <VBox/stam.h>
25
#include <VBox/param.h>
28
#include <VBox/pdmcritsect.h>
29
#include <VBox/pdmapi.h>
31
#include <VBox/dbgf.h>
34
#include <VBox/hwaccm.h>
36
#include <iprt/assert.h>
38
#include <iprt/critsect.h>
43
/** @addtogroup grp_pgm_int Internals
48
/** @todo Split out all the inline stuff into a separate file. Then we can
49
* include it later when VM and VMCPU are defined and so avoid all that
50
* &pVM->pgm.s and &pVCpu->pgm.s stuff. It also chops ~1600 lines off
51
* this file and will make it somewhat easier to navigate... */
54
* Gets the PGMRAMRANGE structure for a guest page.
56
* @returns Pointer to the RAM range on success.
57
* @returns NULL on a VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS condition.
59
* @param pPGM PGM handle.
60
* @param GCPhys The GC physical address.
62
DECLINLINE(PPGMRAMRANGE) pgmPhysGetRange(PPGM pPGM, RTGCPHYS GCPhys)
65
* Optimize for the first range.
67
PPGMRAMRANGE pRam = pPGM->CTX_SUFF(pRamRanges);
68
RTGCPHYS off = GCPhys - pRam->GCPhys;
69
if (RT_UNLIKELY(off >= pRam->cb))
73
pRam = pRam->CTX_SUFF(pNext);
74
if (RT_UNLIKELY(!pRam))
76
off = GCPhys - pRam->GCPhys;
77
} while (off >= pRam->cb);
84
* Gets the PGMPAGE structure for a guest page.
86
* @returns Pointer to the page on success.
87
* @returns NULL on a VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS condition.
89
* @param pPGM PGM handle.
90
* @param GCPhys The GC physical address.
92
DECLINLINE(PPGMPAGE) pgmPhysGetPage(PPGM pPGM, RTGCPHYS GCPhys)
95
* Optimize for the first range.
97
PPGMRAMRANGE pRam = pPGM->CTX_SUFF(pRamRanges);
98
RTGCPHYS off = GCPhys - pRam->GCPhys;
99
if (RT_UNLIKELY(off >= pRam->cb))
103
pRam = pRam->CTX_SUFF(pNext);
104
if (RT_UNLIKELY(!pRam))
106
off = GCPhys - pRam->GCPhys;
107
} while (off >= pRam->cb);
109
return &pRam->aPages[off >> PAGE_SHIFT];
114
* Gets the PGMPAGE structure for a guest page.
116
* Old Phys code: Will make sure the page is present.
118
* @returns VBox status code.
119
* @retval VINF_SUCCESS and a valid *ppPage on success.
120
* @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if the address isn't valid.
122
* @param pPGM PGM handle.
123
* @param GCPhys The GC physical address.
124
* @param ppPage Where to store the page pointer on success.
126
DECLINLINE(int) pgmPhysGetPageEx(PPGM pPGM, RTGCPHYS GCPhys, PPPGMPAGE ppPage)
129
* Optimize for the first range.
131
PPGMRAMRANGE pRam = pPGM->CTX_SUFF(pRamRanges);
132
RTGCPHYS off = GCPhys - pRam->GCPhys;
133
if (RT_UNLIKELY(off >= pRam->cb))
137
pRam = pRam->CTX_SUFF(pNext);
138
if (RT_UNLIKELY(!pRam))
140
*ppPage = NULL; /* avoid incorrect and very annoying GCC warnings */
141
return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
143
off = GCPhys - pRam->GCPhys;
144
} while (off >= pRam->cb);
146
*ppPage = &pRam->aPages[off >> PAGE_SHIFT];
154
* Gets the PGMPAGE structure for a guest page.
156
* Old Phys code: Will make sure the page is present.
158
* @returns VBox status code.
159
* @retval VINF_SUCCESS and a valid *ppPage on success.
160
* @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if the address isn't valid.
162
* @param pPGM PGM handle.
163
* @param GCPhys The GC physical address.
164
* @param ppPage Where to store the page pointer on success.
165
* @param ppRamHint Where to read and store the ram list hint.
166
* The caller initializes this to NULL before the call.
168
DECLINLINE(int) pgmPhysGetPageWithHintEx(PPGM pPGM, RTGCPHYS GCPhys, PPPGMPAGE ppPage, PPGMRAMRANGE *ppRamHint)
171
PPGMRAMRANGE pRam = *ppRamHint;
173
|| RT_UNLIKELY((off = GCPhys - pRam->GCPhys) >= pRam->cb))
175
pRam = pPGM->CTX_SUFF(pRamRanges);
176
off = GCPhys - pRam->GCPhys;
177
if (RT_UNLIKELY(off >= pRam->cb))
181
pRam = pRam->CTX_SUFF(pNext);
182
if (RT_UNLIKELY(!pRam))
184
*ppPage = NULL; /* Kill the incorrect and extremely annoying GCC warnings. */
185
return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
187
off = GCPhys - pRam->GCPhys;
188
} while (off >= pRam->cb);
192
*ppPage = &pRam->aPages[off >> PAGE_SHIFT];
198
* Gets the PGMPAGE structure for a guest page together with the PGMRAMRANGE.
200
* @returns Pointer to the page on success.
201
* @returns NULL on a VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS condition.
203
* @param pPGM PGM handle.
204
* @param GCPhys The GC physical address.
205
* @param ppRam Where to store the pointer to the PGMRAMRANGE.
207
DECLINLINE(PPGMPAGE) pgmPhysGetPageAndRange(PPGM pPGM, RTGCPHYS GCPhys, PPGMRAMRANGE *ppRam)
210
* Optimize for the first range.
212
PPGMRAMRANGE pRam = pPGM->CTX_SUFF(pRamRanges);
213
RTGCPHYS off = GCPhys - pRam->GCPhys;
214
if (RT_UNLIKELY(off >= pRam->cb))
218
pRam = pRam->CTX_SUFF(pNext);
219
if (RT_UNLIKELY(!pRam))
221
off = GCPhys - pRam->GCPhys;
222
} while (off >= pRam->cb);
225
return &pRam->aPages[off >> PAGE_SHIFT];
230
* Gets the PGMPAGE structure for a guest page together with the PGMRAMRANGE.
232
* @returns Pointer to the page on success.
233
* @returns NULL on a VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS condition.
235
* @param pPGM PGM handle.
236
* @param GCPhys The GC physical address.
237
* @param ppPage Where to store the pointer to the PGMPAGE structure.
238
* @param ppRam Where to store the pointer to the PGMRAMRANGE structure.
240
DECLINLINE(int) pgmPhysGetPageAndRangeEx(PPGM pPGM, RTGCPHYS GCPhys, PPPGMPAGE ppPage, PPGMRAMRANGE *ppRam)
243
* Optimize for the first range.
245
PPGMRAMRANGE pRam = pPGM->CTX_SUFF(pRamRanges);
246
RTGCPHYS off = GCPhys - pRam->GCPhys;
247
if (RT_UNLIKELY(off >= pRam->cb))
251
pRam = pRam->CTX_SUFF(pNext);
252
if (RT_UNLIKELY(!pRam))
254
*ppRam = NULL; /* Shut up silly GCC warnings. */
255
*ppPage = NULL; /* ditto */
256
return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
258
off = GCPhys - pRam->GCPhys;
259
} while (off >= pRam->cb);
262
*ppPage = &pRam->aPages[off >> PAGE_SHIFT];
268
* Convert GC Phys to HC Phys.
270
* @returns VBox status.
271
* @param pPGM PGM handle.
272
* @param GCPhys The GC physical address.
273
* @param pHCPhys Where to store the corresponding HC physical address.
275
* @deprecated Doesn't deal with zero, shared or write monitored pages.
276
* Avoid when writing new code!
278
DECLINLINE(int) pgmRamGCPhys2HCPhys(PPGM pPGM, RTGCPHYS GCPhys, PRTHCPHYS pHCPhys)
281
int rc = pgmPhysGetPageEx(pPGM, GCPhys, &pPage);
284
*pHCPhys = PGM_PAGE_GET_HCPHYS(pPage) | (GCPhys & PAGE_OFFSET_MASK);
288
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
291
* Inlined version of the ring-0 version of PGMDynMapHCPage that
292
* optimizes access to pages already in the set.
294
* @returns VINF_SUCCESS. Will bail out to ring-3 on failure.
295
* @param pPGM Pointer to the PVM instance data.
296
* @param HCPhys The physical address of the page.
297
* @param ppv Where to store the mapping address.
299
DECLINLINE(int) pgmR0DynMapHCPageInlined(PPGM pPGM, RTHCPHYS HCPhys, void **ppv)
301
PVM pVM = PGM2VM(pPGM);
302
PPGMCPU pPGMCPU = (PPGMCPU)((uint8_t *)VMMGetCpu(pVM) + pPGM->offVCpuPGM); /* very pretty ;-) */
303
PPGMMAPSET pSet = &pPGMCPU->AutoSet;
305
STAM_PROFILE_START(&pPGMCPU->StatR0DynMapHCPageInl, a);
306
Assert(!(HCPhys & PAGE_OFFSET_MASK));
307
Assert(pSet->cEntries <= RT_ELEMENTS(pSet->aEntries));
309
unsigned iHash = PGMMAPSET_HASH(HCPhys);
310
unsigned iEntry = pSet->aiHashTable[iHash];
311
if ( iEntry < pSet->cEntries
312
&& pSet->aEntries[iEntry].HCPhys == HCPhys)
314
*ppv = pSet->aEntries[iEntry].pvPage;
315
STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapHCPageInlHits);
319
STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapHCPageInlMisses);
320
pgmR0DynMapHCPageCommon(pVM, pSet, HCPhys, ppv);
323
STAM_PROFILE_STOP(&pPGMCPU->StatR0DynMapHCPageInl, a);
329
* Inlined version of the ring-0 version of PGMDynMapGCPage that optimizes
330
* access to pages already in the set.
332
* @returns See PGMDynMapGCPage.
333
* @param pPGM Pointer to the PVM instance data.
334
* @param GCPhys The guest physical address of the page.
335
* @param ppv Where to store the mapping address.
337
DECLINLINE(int) pgmR0DynMapGCPageInlined(PPGM pPGM, RTGCPHYS GCPhys, void **ppv)
339
PVM pVM = PGM2VM(pPGM);
340
PPGMCPU pPGMCPU = (PPGMCPU)((uint8_t *)VMMGetCpu(pVM) + pPGM->offVCpuPGM); /* very pretty ;-) */
342
STAM_PROFILE_START(&pPGMCPU->StatR0DynMapGCPageInl, a);
343
AssertMsg(!(GCPhys & PAGE_OFFSET_MASK), ("%RGp\n", GCPhys));
348
PPGMRAMRANGE pRam = pPGM->CTX_SUFF(pRamRanges);
349
RTGCPHYS off = GCPhys - pRam->GCPhys;
350
if (RT_UNLIKELY(off >= pRam->cb
351
/** @todo || page state stuff */))
353
/* This case is not counted into StatR0DynMapGCPageInl. */
354
STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapGCPageInlRamMisses);
355
return PGMDynMapGCPage(pVM, GCPhys, ppv);
358
RTHCPHYS HCPhys = PGM_PAGE_GET_HCPHYS(&pRam->aPages[off >> PAGE_SHIFT]);
359
STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapGCPageInlRamHits);
362
* pgmR0DynMapHCPageInlined with out stats.
364
PPGMMAPSET pSet = &pPGMCPU->AutoSet;
365
Assert(!(HCPhys & PAGE_OFFSET_MASK));
366
Assert(pSet->cEntries <= RT_ELEMENTS(pSet->aEntries));
368
unsigned iHash = PGMMAPSET_HASH(HCPhys);
369
unsigned iEntry = pSet->aiHashTable[iHash];
370
if ( iEntry < pSet->cEntries
371
&& pSet->aEntries[iEntry].HCPhys == HCPhys)
373
*ppv = pSet->aEntries[iEntry].pvPage;
374
STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapGCPageInlHits);
378
STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapGCPageInlMisses);
379
pgmR0DynMapHCPageCommon(pVM, pSet, HCPhys, ppv);
382
STAM_PROFILE_STOP(&pPGMCPU->StatR0DynMapGCPageInl, a);
388
* Inlined version of the ring-0 version of PGMDynMapGCPageOff that optimizes
389
* access to pages already in the set.
391
* @returns See PGMDynMapGCPage.
392
* @param pPGM Pointer to the PVM instance data.
393
* @param HCPhys The physical address of the page.
394
* @param ppv Where to store the mapping address.
396
DECLINLINE(int) pgmR0DynMapGCPageOffInlined(PPGM pPGM, RTGCPHYS GCPhys, void **ppv)
398
PVM pVM = PGM2VM(pPGM);
399
PPGMCPU pPGMCPU = (PPGMCPU)((uint8_t *)VMMGetCpu(pVM) + pPGM->offVCpuPGM); /* very pretty ;-) */
401
STAM_PROFILE_START(&pPGMCPU->StatR0DynMapGCPageInl, a);
406
PPGMRAMRANGE pRam = pPGM->CTX_SUFF(pRamRanges);
407
RTGCPHYS off = GCPhys - pRam->GCPhys;
408
if (RT_UNLIKELY(off >= pRam->cb
409
/** @todo || page state stuff */))
411
/* This case is not counted into StatR0DynMapGCPageInl. */
412
STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapGCPageInlRamMisses);
413
return PGMDynMapGCPageOff(pVM, GCPhys, ppv);
416
RTHCPHYS HCPhys = PGM_PAGE_GET_HCPHYS(&pRam->aPages[off >> PAGE_SHIFT]);
417
STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapGCPageInlRamHits);
420
* pgmR0DynMapHCPageInlined with out stats.
422
PPGMMAPSET pSet = &pPGMCPU->AutoSet;
423
Assert(!(HCPhys & PAGE_OFFSET_MASK));
424
Assert(pSet->cEntries <= RT_ELEMENTS(pSet->aEntries));
426
unsigned iHash = PGMMAPSET_HASH(HCPhys);
427
unsigned iEntry = pSet->aiHashTable[iHash];
428
if ( iEntry < pSet->cEntries
429
&& pSet->aEntries[iEntry].HCPhys == HCPhys)
431
*ppv = (void *)((uintptr_t)pSet->aEntries[iEntry].pvPage | (PAGE_OFFSET_MASK & (uintptr_t)GCPhys));
432
STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapGCPageInlHits);
436
STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapGCPageInlMisses);
437
pgmR0DynMapHCPageCommon(pVM, pSet, HCPhys, ppv);
438
*ppv = (void *)((uintptr_t)*ppv | (PAGE_OFFSET_MASK & (uintptr_t)GCPhys));
441
STAM_PROFILE_STOP(&pPGMCPU->StatR0DynMapGCPageInl, a);
445
#endif /* VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0 */
446
#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
449
* Maps the page into current context (RC and maybe R0).
451
* @returns pointer to the mapping.
452
* @param pVM Pointer to the PGM instance data.
453
* @param pPage The page.
455
DECLINLINE(void *) pgmPoolMapPageInlined(PPGM pPGM, PPGMPOOLPAGE pPage)
457
if (pPage->idx >= PGMPOOL_IDX_FIRST)
459
Assert(pPage->idx < pPGM->CTX_SUFF(pPool)->cCurPages);
461
# ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
462
pgmR0DynMapHCPageInlined(pPGM, pPage->Core.Key, &pv);
464
PGMDynMapHCPage(PGM2VM(pPGM), pPage->Core.Key, &pv);
468
AssertFatalMsgFailed(("pgmPoolMapPageInlined invalid page index %x\n", pPage->idx));
472
* Temporarily maps one host page specified by HC physical address, returning
473
* pointer within the page.
475
* Be WARNED that the dynamic page mapping area is small, 8 pages, thus the space is
476
* reused after 8 mappings (or perhaps a few more if you score with the cache).
478
* @returns The address corresponding to HCPhys.
479
* @param pPGM Pointer to the PVM instance data.
480
* @param HCPhys HC Physical address of the page.
482
DECLINLINE(void *) pgmDynMapHCPageOff(PPGM pPGM, RTHCPHYS HCPhys)
485
# ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
486
pgmR0DynMapHCPageInlined(pPGM, HCPhys & ~(RTHCPHYS)PAGE_OFFSET_MASK, &pv);
488
PGMDynMapHCPage(PGM2VM(pPGM), HCPhys & ~(RTHCPHYS)PAGE_OFFSET_MASK, &pv);
490
pv = (void *)((uintptr_t)pv | ((uintptr_t)HCPhys & PAGE_OFFSET_MASK));
494
#endif /* VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0 || IN_RC */
498
* Queries the Physical TLB entry for a physical guest page,
499
* attempting to load the TLB entry if necessary.
501
* @returns VBox status code.
502
* @retval VINF_SUCCESS on success
503
* @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if it's not a valid physical address.
505
* @param pPGM The PGM instance handle.
506
* @param GCPhys The address of the guest page.
507
* @param ppTlbe Where to store the pointer to the TLB entry.
509
DECLINLINE(int) pgmPhysPageQueryTlbe(PPGM pPGM, RTGCPHYS GCPhys, PPPGMPAGEMAPTLBE ppTlbe)
512
PPGMPAGEMAPTLBE pTlbe = &pPGM->CTXSUFF(PhysTlb).aEntries[PGM_PAGEMAPTLB_IDX(GCPhys)];
513
if (pTlbe->GCPhys == (GCPhys & X86_PTE_PAE_PG_MASK))
515
STAM_COUNTER_INC(&pPGM->CTX_MID_Z(Stat,PageMapTlbHits));
519
rc = pgmPhysPageLoadIntoTlb(pPGM, GCPhys);
526
* Queries the Physical TLB entry for a physical guest page,
527
* attempting to load the TLB entry if necessary.
529
* @returns VBox status code.
530
* @retval VINF_SUCCESS on success
531
* @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if it's not a valid physical address.
533
* @param pPGM The PGM instance handle.
534
* @param pPage Pointer to the PGMPAGE structure corresponding to
536
* @param GCPhys The address of the guest page.
537
* @param ppTlbe Where to store the pointer to the TLB entry.
539
DECLINLINE(int) pgmPhysPageQueryTlbeWithPage(PPGM pPGM, PPGMPAGE pPage, RTGCPHYS GCPhys, PPPGMPAGEMAPTLBE ppTlbe)
542
PPGMPAGEMAPTLBE pTlbe = &pPGM->CTXSUFF(PhysTlb).aEntries[PGM_PAGEMAPTLB_IDX(GCPhys)];
543
if (pTlbe->GCPhys == (GCPhys & X86_PTE_PAE_PG_MASK))
545
STAM_COUNTER_INC(&pPGM->CTX_MID_Z(Stat,PageMapTlbHits));
549
rc = pgmPhysPageLoadIntoTlbWithPage(pPGM, pPage, GCPhys);
557
* Calculated the guest physical address of the large (4 MB) page in 32 bits paging mode.
558
* Takes PSE-36 into account.
560
* @returns guest physical address
561
* @param pPGM Pointer to the PGM instance data.
562
* @param Pde Guest Pde
564
DECLINLINE(RTGCPHYS) pgmGstGet4MBPhysPage(PPGM pPGM, X86PDE Pde)
566
RTGCPHYS GCPhys = Pde.u & X86_PDE4M_PG_MASK;
567
GCPhys |= (RTGCPHYS)Pde.b.u8PageNoHigh << 32;
569
return GCPhys & pPGM->GCPhys4MBPSEMask;
574
* Gets the page directory entry for the specified address (32-bit paging).
576
* @returns The page directory entry in question.
577
* @param pPGM Pointer to the PGM instance data.
578
* @param GCPtr The address.
580
DECLINLINE(X86PDE) pgmGstGet32bitPDE(PPGMCPU pPGM, RTGCPTR GCPtr)
582
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
583
PCX86PD pGuestPD = NULL;
584
int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pPGM->GCPhysCR3, (void **)&pGuestPD);
587
X86PDE ZeroPde = {0};
588
AssertMsgFailedReturn(("%Rrc\n", rc), ZeroPde);
591
PX86PD pGuestPD = pPGM->CTX_SUFF(pGst32BitPd);
594
pGuestPD = pgmGstLazyMap32BitPD(pPGM);
597
return pGuestPD->a[GCPtr >> X86_PD_SHIFT];
602
* Gets the address of a specific page directory entry (32-bit paging).
604
* @returns Pointer the page directory entry in question.
605
* @param pPGM Pointer to the PGM instance data.
606
* @param GCPtr The address.
608
DECLINLINE(PX86PDE) pgmGstGet32bitPDEPtr(PPGMCPU pPGM, RTGCPTR GCPtr)
610
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
611
PX86PD pGuestPD = NULL;
612
int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pPGM->GCPhysCR3, (void **)&pGuestPD);
613
AssertRCReturn(rc, NULL);
615
PX86PD pGuestPD = pPGM->CTX_SUFF(pGst32BitPd);
618
pGuestPD = pgmGstLazyMap32BitPD(pPGM);
621
return &pGuestPD->a[GCPtr >> X86_PD_SHIFT];
626
* Gets the address the guest page directory (32-bit paging).
628
* @returns Pointer the page directory entry in question.
629
* @param pPGM Pointer to the PGM instance data.
631
DECLINLINE(PX86PD) pgmGstGet32bitPDPtr(PPGMCPU pPGM)
633
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
634
PX86PD pGuestPD = NULL;
635
int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pPGM->GCPhysCR3, (void **)&pGuestPD);
636
AssertRCReturn(rc, NULL);
638
PX86PD pGuestPD = pPGM->CTX_SUFF(pGst32BitPd);
641
pGuestPD = pgmGstLazyMap32BitPD(pPGM);
649
* Gets the guest page directory pointer table.
651
* @returns Pointer to the page directory in question.
652
* @returns NULL if the page directory is not present or on an invalid page.
653
* @param pPGM Pointer to the PGM instance data.
655
DECLINLINE(PX86PDPT) pgmGstGetPaePDPTPtr(PPGMCPU pPGM)
657
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
658
PX86PDPT pGuestPDPT = NULL;
659
int rc = pgmR0DynMapGCPageOffInlined(PGMCPU2PGM(pPGM), pPGM->GCPhysCR3, (void **)&pGuestPDPT);
660
AssertRCReturn(rc, NULL);
662
PX86PDPT pGuestPDPT = pPGM->CTX_SUFF(pGstPaePdpt);
665
pGuestPDPT = pgmGstLazyMapPaePDPT(pPGM);
673
* Gets the guest page directory pointer table entry for the specified address.
675
* @returns Pointer to the page directory in question.
676
* @returns NULL if the page directory is not present or on an invalid page.
677
* @param pPGM Pointer to the PGM instance data.
678
* @param GCPtr The address.
680
DECLINLINE(PX86PDPE) pgmGstGetPaePDPEPtr(PPGMCPU pPGM, RTGCPTR GCPtr)
682
AssertGCPtr32(GCPtr);
684
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
685
PX86PDPT pGuestPDPT = 0;
686
int rc = pgmR0DynMapGCPageOffInlined(PGMCPU2PGM(pPGM), pPGM->GCPhysCR3, (void **)&pGuestPDPT);
687
AssertRCReturn(rc, 0);
689
PX86PDPT pGuestPDPT = pPGM->CTX_SUFF(pGstPaePdpt);
692
pGuestPDPT = pgmGstLazyMapPaePDPT(pPGM);
695
return &pGuestPDPT->a[(GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE];
700
* Gets the page directory for the specified address.
702
* @returns Pointer to the page directory in question.
703
* @returns NULL if the page directory is not present or on an invalid page.
704
* @param pPGM Pointer to the PGM instance data.
705
* @param GCPtr The address.
707
DECLINLINE(PX86PDPAE) pgmGstGetPaePD(PPGMCPU pPGM, RTGCPTR GCPtr)
709
AssertGCPtr32(GCPtr);
711
PX86PDPT pGuestPDPT = pgmGstGetPaePDPTPtr(pPGM);
712
AssertReturn(pGuestPDPT, NULL);
713
const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE;
714
if (pGuestPDPT->a[iPdpt].n.u1Present)
716
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
717
PX86PDPAE pGuestPD = NULL;
718
int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pGuestPDPT->a[iPdpt].u & X86_PDPE_PG_MASK, (void **)&pGuestPD);
719
AssertRCReturn(rc, NULL);
721
PX86PDPAE pGuestPD = pPGM->CTX_SUFF(apGstPaePDs)[iPdpt];
723
|| (pGuestPDPT->a[iPdpt].u & X86_PDPE_PG_MASK) != pPGM->aGCPhysGstPaePDs[iPdpt])
724
pGuestPD = pgmGstLazyMapPaePD(pPGM, iPdpt);
727
/* returning NULL is ok if we assume it's just an invalid page of some kind emulated as all 0s. (not quite true) */
734
* Gets the page directory entry for the specified address.
736
* @returns Pointer to the page directory entry in question.
737
* @returns NULL if the page directory is not present or on an invalid page.
738
* @param pPGM Pointer to the PGM instance data.
739
* @param GCPtr The address.
741
DECLINLINE(PX86PDEPAE) pgmGstGetPaePDEPtr(PPGMCPU pPGM, RTGCPTR GCPtr)
743
AssertGCPtr32(GCPtr);
745
PX86PDPT pGuestPDPT = pgmGstGetPaePDPTPtr(pPGM);
746
AssertReturn(pGuestPDPT, NULL);
747
const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE;
748
if (pGuestPDPT->a[iPdpt].n.u1Present)
750
const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
751
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
752
PX86PDPAE pGuestPD = NULL;
753
int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pGuestPDPT->a[iPdpt].u & X86_PDPE_PG_MASK, (void **)&pGuestPD);
754
AssertRCReturn(rc, NULL);
756
PX86PDPAE pGuestPD = pPGM->CTX_SUFF(apGstPaePDs)[iPdpt];
758
|| (pGuestPDPT->a[iPdpt].u & X86_PDPE_PG_MASK) != pPGM->aGCPhysGstPaePDs[iPdpt])
759
pGuestPD = pgmGstLazyMapPaePD(pPGM, iPdpt);
761
return &pGuestPD->a[iPD];
762
/* returning NIL_RTGCPHYS is ok if we assume it's just an invalid page or something which we'll emulate as all 0s. (not quite true) */
769
* Gets the page directory entry for the specified address.
771
* @returns The page directory entry in question.
772
* @returns A non-present entry if the page directory is not present or on an invalid page.
773
* @param pPGM Pointer to the PGM instance data.
774
* @param GCPtr The address.
776
DECLINLINE(X86PDEPAE) pgmGstGetPaePDE(PPGMCPU pPGM, RTGCPTR GCPtr)
778
AssertGCPtr32(GCPtr);
779
X86PDEPAE ZeroPde = {0};
780
PX86PDPT pGuestPDPT = pgmGstGetPaePDPTPtr(pPGM);
781
if (RT_LIKELY(pGuestPDPT))
783
const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE;
784
if (pGuestPDPT->a[iPdpt].n.u1Present)
786
const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
787
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
788
PX86PDPAE pGuestPD = NULL;
789
int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pGuestPDPT->a[iPdpt].u & X86_PDPE_PG_MASK, (void **)&pGuestPD);
790
AssertRCReturn(rc, ZeroPde);
792
PX86PDPAE pGuestPD = pPGM->CTX_SUFF(apGstPaePDs)[iPdpt];
794
|| (pGuestPDPT->a[iPdpt].u & X86_PDPE_PG_MASK) != pPGM->aGCPhysGstPaePDs[iPdpt])
795
pGuestPD = pgmGstLazyMapPaePD(pPGM, iPdpt);
797
return pGuestPD->a[iPD];
805
* Gets the page directory pointer table entry for the specified address
806
* and returns the index into the page directory
808
* @returns Pointer to the page directory in question.
809
* @returns NULL if the page directory is not present or on an invalid page.
810
* @param pPGM Pointer to the PGM instance data.
811
* @param GCPtr The address.
812
* @param piPD Receives the index into the returned page directory
813
* @param pPdpe Receives the page directory pointer entry. Optional.
815
DECLINLINE(PX86PDPAE) pgmGstGetPaePDPtr(PPGMCPU pPGM, RTGCPTR GCPtr, unsigned *piPD, PX86PDPE pPdpe)
817
AssertGCPtr32(GCPtr);
819
PX86PDPT pGuestPDPT = pgmGstGetPaePDPTPtr(pPGM);
820
AssertReturn(pGuestPDPT, NULL);
821
const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE;
823
*pPdpe = pGuestPDPT->a[iPdpt];
824
if (pGuestPDPT->a[iPdpt].n.u1Present)
826
const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
827
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
828
PX86PDPAE pGuestPD = NULL;
829
int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pGuestPDPT->a[iPdpt].u & X86_PDPE_PG_MASK, (void **)&pGuestPD);
830
AssertRCReturn(rc, NULL);
832
PX86PDPAE pGuestPD = pPGM->CTX_SUFF(apGstPaePDs)[iPdpt];
834
|| (pGuestPDPT->a[iPdpt].u & X86_PDPE_PG_MASK) != pPGM->aGCPhysGstPaePDs[iPdpt])
835
pGuestPD = pgmGstLazyMapPaePD(pPGM, iPdpt);
839
/* returning NIL_RTGCPHYS is ok if we assume it's just an invalid page of some kind emulated as all 0s. */
847
* Gets the page map level-4 pointer for the guest.
849
* @returns Pointer to the PML4 page.
850
* @param pPGM Pointer to the PGM instance data.
852
DECLINLINE(PX86PML4) pgmGstGetLongModePML4Ptr(PPGMCPU pPGM)
854
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
856
int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pPGM->GCPhysCR3, (void **)&pGuestPml4);
857
AssertRCReturn(rc, NULL);
859
PX86PML4 pGuestPml4 = pPGM->CTX_SUFF(pGstAmd64Pml4);
860
# ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R3
862
pGuestPml4 = pgmGstLazyMapPml4(pPGM);
871
* Gets the pointer to a page map level-4 entry.
873
* @returns Pointer to the PML4 entry.
874
* @param pPGM Pointer to the PGM instance data.
875
* @param iPml4 The index.
877
DECLINLINE(PX86PML4E) pgmGstGetLongModePML4EPtr(PPGMCPU pPGM, unsigned int iPml4)
879
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
881
int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pPGM->GCPhysCR3, (void **)&pGuestPml4);
882
AssertRCReturn(rc, NULL);
884
PX86PML4 pGuestPml4 = pPGM->CTX_SUFF(pGstAmd64Pml4);
885
# ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R3
887
pGuestPml4 = pgmGstLazyMapPml4(pPGM);
891
return &pGuestPml4->a[iPml4];
896
* Gets a page map level-4 entry.
898
* @returns The PML4 entry.
899
* @param pPGM Pointer to the PGM instance data.
900
* @param iPml4 The index.
902
DECLINLINE(X86PML4E) pgmGstGetLongModePML4E(PPGMCPU pPGM, unsigned int iPml4)
904
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
906
int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pPGM->GCPhysCR3, (void **)&pGuestPml4);
909
X86PML4E ZeroPml4e = {0};
910
AssertMsgFailedReturn(("%Rrc\n", rc), ZeroPml4e);
913
PX86PML4 pGuestPml4 = pPGM->CTX_SUFF(pGstAmd64Pml4);
914
# ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R3
916
pGuestPml4 = pgmGstLazyMapPml4(pPGM);
920
return pGuestPml4->a[iPml4];
925
* Gets the page directory pointer entry for the specified address.
927
* @returns Pointer to the page directory pointer entry in question.
928
* @returns NULL if the page directory is not present or on an invalid page.
929
* @param pPGM Pointer to the PGM instance data.
930
* @param GCPtr The address.
931
* @param ppPml4e Page Map Level-4 Entry (out)
933
DECLINLINE(PX86PDPE) pgmGstGetLongModePDPTPtr(PPGMCPU pPGM, RTGCPTR64 GCPtr, PX86PML4E *ppPml4e)
935
PX86PML4 pGuestPml4 = pgmGstGetLongModePML4Ptr(pPGM);
936
const unsigned iPml4 = (GCPtr >> X86_PML4_SHIFT) & X86_PML4_MASK;
937
PCX86PML4E pPml4e = *ppPml4e = &pGuestPml4->a[iPml4];
938
if (pPml4e->n.u1Present)
941
int rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pPml4e->u & X86_PML4E_PG_MASK, &pPdpt);
942
AssertRCReturn(rc, NULL);
944
const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64;
945
return &pPdpt->a[iPdpt];
952
* Gets the page directory entry for the specified address.
954
* @returns The page directory entry in question.
955
* @returns A non-present entry if the page directory is not present or on an invalid page.
956
* @param pPGM Pointer to the PGM instance data.
957
* @param GCPtr The address.
958
* @param ppPml4e Page Map Level-4 Entry (out)
959
* @param pPdpe Page directory pointer table entry (out)
961
DECLINLINE(X86PDEPAE) pgmGstGetLongModePDEEx(PPGMCPU pPGM, RTGCPTR64 GCPtr, PX86PML4E *ppPml4e, PX86PDPE pPdpe)
963
X86PDEPAE ZeroPde = {0};
964
PX86PML4 pGuestPml4 = pgmGstGetLongModePML4Ptr(pPGM);
965
const unsigned iPml4 = (GCPtr >> X86_PML4_SHIFT) & X86_PML4_MASK;
966
PCX86PML4E pPml4e = *ppPml4e = &pGuestPml4->a[iPml4];
967
if (pPml4e->n.u1Present)
970
int rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pPml4e->u & X86_PML4E_PG_MASK, &pPdptTemp);
971
AssertRCReturn(rc, ZeroPde);
973
const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64;
974
*pPdpe = pPdptTemp->a[iPdpt];
975
if (pPdptTemp->a[iPdpt].n.u1Present)
978
rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pPdptTemp->a[iPdpt].u & X86_PDPE_PG_MASK, &pPD);
979
AssertRCReturn(rc, ZeroPde);
981
const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
991
* Gets the page directory entry for the specified address.
993
* @returns The page directory entry in question.
994
* @returns A non-present entry if the page directory is not present or on an invalid page.
995
* @param pPGM Pointer to the PGM instance data.
996
* @param GCPtr The address.
998
DECLINLINE(X86PDEPAE) pgmGstGetLongModePDE(PPGMCPU pPGM, RTGCPTR64 GCPtr)
1000
X86PDEPAE ZeroPde = {0};
1001
PCX86PML4 pGuestPml4 = pgmGstGetLongModePML4Ptr(pPGM);
1002
const unsigned iPml4 = (GCPtr >> X86_PML4_SHIFT) & X86_PML4_MASK;
1003
if (pGuestPml4->a[iPml4].n.u1Present)
1005
PCX86PDPT pPdptTemp;
1006
int rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pGuestPml4->a[iPml4].u & X86_PML4E_PG_MASK, &pPdptTemp);
1007
AssertRCReturn(rc, ZeroPde);
1009
const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64;
1010
if (pPdptTemp->a[iPdpt].n.u1Present)
1013
rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pPdptTemp->a[iPdpt].u & X86_PDPE_PG_MASK, &pPD);
1014
AssertRCReturn(rc, ZeroPde);
1016
const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
1025
* Gets the page directory entry for the specified address.
1027
* @returns Pointer to the page directory entry in question.
1028
* @returns NULL if the page directory is not present or on an invalid page.
1029
* @param pPGM Pointer to the PGM instance data.
1030
* @param GCPtr The address.
1032
DECLINLINE(PX86PDEPAE) pgmGstGetLongModePDEPtr(PPGMCPU pPGM, RTGCPTR64 GCPtr)
1034
PCX86PML4 pGuestPml4 = pgmGstGetLongModePML4Ptr(pPGM);
1035
const unsigned iPml4 = (GCPtr >> X86_PML4_SHIFT) & X86_PML4_MASK;
1036
if (pGuestPml4->a[iPml4].n.u1Present)
1038
PCX86PDPT pPdptTemp;
1039
int rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pGuestPml4->a[iPml4].u & X86_PML4E_PG_MASK, &pPdptTemp);
1040
AssertRCReturn(rc, NULL);
1042
const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64;
1043
if (pPdptTemp->a[iPdpt].n.u1Present)
1046
rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pPdptTemp->a[iPdpt].u & X86_PDPE_PG_MASK, &pPD);
1047
AssertRCReturn(rc, NULL);
1049
const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
1050
return &pPD->a[iPD];
1058
* Gets the GUEST page directory pointer for the specified address.
1060
* @returns The page directory in question.
1061
* @returns NULL if the page directory is not present or on an invalid page.
1062
* @param pPGM Pointer to the PGM instance data.
1063
* @param GCPtr The address.
1064
* @param ppPml4e Page Map Level-4 Entry (out)
1065
* @param pPdpe Page directory pointer table entry (out)
1066
* @param piPD Receives the index into the returned page directory
1068
DECLINLINE(PX86PDPAE) pgmGstGetLongModePDPtr(PPGMCPU pPGM, RTGCPTR64 GCPtr, PX86PML4E *ppPml4e, PX86PDPE pPdpe, unsigned *piPD)
1070
PX86PML4 pGuestPml4 = pgmGstGetLongModePML4Ptr(pPGM);
1071
const unsigned iPml4 = (GCPtr >> X86_PML4_SHIFT) & X86_PML4_MASK;
1072
PCX86PML4E pPml4e = *ppPml4e = &pGuestPml4->a[iPml4];
1073
if (pPml4e->n.u1Present)
1075
PCX86PDPT pPdptTemp;
1076
int rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pPml4e->u & X86_PML4E_PG_MASK, &pPdptTemp);
1077
AssertRCReturn(rc, NULL);
1079
const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64;
1080
*pPdpe = pPdptTemp->a[iPdpt];
1081
if (pPdptTemp->a[iPdpt].n.u1Present)
1084
rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pPdptTemp->a[iPdpt].u & X86_PDPE_PG_MASK, &pPD);
1085
AssertRCReturn(rc, NULL);
1087
*piPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
1097
* Gets the shadow page directory, 32-bit.
1099
* @returns Pointer to the shadow 32-bit PD.
1100
* @param pPGM Pointer to the PGM instance data.
1102
DECLINLINE(PX86PD) pgmShwGet32BitPDPtr(PPGMCPU pPGM)
1104
return (PX86PD)PGMPOOL_PAGE_2_PTR_BY_PGMCPU(pPGM, pPGM->CTX_SUFF(pShwPageCR3));
1109
* Gets the shadow page directory entry for the specified address, 32-bit.
1111
* @returns Shadow 32-bit PDE.
1112
* @param pPGM Pointer to the PGM instance data.
1113
* @param GCPtr The address.
1115
DECLINLINE(X86PDE) pgmShwGet32BitPDE(PPGMCPU pPGM, RTGCPTR GCPtr)
1117
const unsigned iPd = (GCPtr >> X86_PD_SHIFT) & X86_PD_MASK;
1119
PX86PD pShwPde = pgmShwGet32BitPDPtr(pPGM);
1122
X86PDE ZeroPde = {0};
1125
return pShwPde->a[iPd];
1130
* Gets the pointer to the shadow page directory entry for the specified
1133
* @returns Pointer to the shadow 32-bit PDE.
1134
* @param pPGM Pointer to the PGM instance data.
1135
* @param GCPtr The address.
1137
DECLINLINE(PX86PDE) pgmShwGet32BitPDEPtr(PPGMCPU pPGM, RTGCPTR GCPtr)
1139
const unsigned iPd = (GCPtr >> X86_PD_SHIFT) & X86_PD_MASK;
1141
PX86PD pPde = pgmShwGet32BitPDPtr(pPGM);
1142
AssertReturn(pPde, NULL);
1143
return &pPde->a[iPd];
1148
* Gets the shadow page pointer table, PAE.
1150
* @returns Pointer to the shadow PAE PDPT.
1151
* @param pPGM Pointer to the PGM instance data.
1153
DECLINLINE(PX86PDPT) pgmShwGetPaePDPTPtr(PPGMCPU pPGM)
1155
return (PX86PDPT)PGMPOOL_PAGE_2_PTR_BY_PGMCPU(pPGM, pPGM->CTX_SUFF(pShwPageCR3));
1160
* Gets the shadow page directory for the specified address, PAE.
1162
* @returns Pointer to the shadow PD.
1163
* @param pPGM Pointer to the PGM instance data.
1164
* @param GCPtr The address.
1166
DECLINLINE(PX86PDPAE) pgmShwGetPaePDPtr(PPGMCPU pPGM, RTGCPTR GCPtr)
1168
const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE;
1169
PX86PDPT pPdpt = pgmShwGetPaePDPTPtr(pPGM);
1171
if (!pPdpt->a[iPdpt].n.u1Present)
1174
/* Fetch the pgm pool shadow descriptor. */
1175
PPGMPOOLPAGE pShwPde = pgmPoolGetPage(PGMCPU2PGM(pPGM)->CTX_SUFF(pPool), pPdpt->a[iPdpt].u & X86_PDPE_PG_MASK);
1176
AssertReturn(pShwPde, NULL);
1178
return (PX86PDPAE)PGMPOOL_PAGE_2_PTR_BY_PGMCPU(pPGM, pShwPde);
1183
* Gets the shadow page directory for the specified address, PAE.
1185
* @returns Pointer to the shadow PD.
1186
* @param pPGM Pointer to the PGM instance data.
1187
* @param GCPtr The address.
1189
DECLINLINE(PX86PDPAE) pgmShwGetPaePDPtr(PPGMCPU pPGM, PX86PDPT pPdpt, RTGCPTR GCPtr)
1191
const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE;
1193
if (!pPdpt->a[iPdpt].n.u1Present)
1196
/* Fetch the pgm pool shadow descriptor. */
1197
PPGMPOOLPAGE pShwPde = pgmPoolGetPage(PGMCPU2PGM(pPGM)->CTX_SUFF(pPool), pPdpt->a[iPdpt].u & X86_PDPE_PG_MASK);
1198
AssertReturn(pShwPde, NULL);
1200
return (PX86PDPAE)PGMPOOL_PAGE_2_PTR_BY_PGMCPU(pPGM, pShwPde);
1205
* Gets the shadow page directory entry, PAE.
1208
* @param pPGM Pointer to the PGM instance data.
1209
* @param GCPtr The address.
1211
DECLINLINE(X86PDEPAE) pgmShwGetPaePDE(PPGMCPU pPGM, RTGCPTR GCPtr)
1213
const unsigned iPd = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
1215
PX86PDPAE pShwPde = pgmShwGetPaePDPtr(pPGM, GCPtr);
1218
X86PDEPAE ZeroPde = {0};
1221
return pShwPde->a[iPd];
1226
* Gets the pointer to the shadow page directory entry for an address, PAE.
1228
* @returns Pointer to the PDE.
1229
* @param pPGM Pointer to the PGM instance data.
1230
* @param GCPtr The address.
1232
DECLINLINE(PX86PDEPAE) pgmShwGetPaePDEPtr(PPGMCPU pPGM, RTGCPTR GCPtr)
1234
const unsigned iPd = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
1236
PX86PDPAE pPde = pgmShwGetPaePDPtr(pPGM, GCPtr);
1237
AssertReturn(pPde, NULL);
1238
return &pPde->a[iPd];
1244
* Gets the shadow page map level-4 pointer.
1246
* @returns Pointer to the shadow PML4.
1247
* @param pPGM Pointer to the PGM instance data.
1249
DECLINLINE(PX86PML4) pgmShwGetLongModePML4Ptr(PPGMCPU pPGM)
1251
return (PX86PML4)PGMPOOL_PAGE_2_PTR_BY_PGMCPU(pPGM, pPGM->CTX_SUFF(pShwPageCR3));
1256
* Gets the shadow page map level-4 entry for the specified address.
1258
* @returns The entry.
1259
* @param pPGM Pointer to the PGM instance data.
1260
* @param GCPtr The address.
1262
DECLINLINE(X86PML4E) pgmShwGetLongModePML4E(PPGMCPU pPGM, RTGCPTR GCPtr)
1264
const unsigned iPml4 = ((RTGCUINTPTR64)GCPtr >> X86_PML4_SHIFT) & X86_PML4_MASK;
1265
PX86PML4 pShwPml4 = pgmShwGetLongModePML4Ptr(pPGM);
1269
X86PML4E ZeroPml4e = {0};
1272
return pShwPml4->a[iPml4];
1277
* Gets the pointer to the specified shadow page map level-4 entry.
1279
* @returns The entry.
1280
* @param pPGM Pointer to the PGM instance data.
1281
* @param iPml4 The PML4 index.
1283
DECLINLINE(PX86PML4E) pgmShwGetLongModePML4EPtr(PPGMCPU pPGM, unsigned int iPml4)
1285
PX86PML4 pShwPml4 = pgmShwGetLongModePML4Ptr(pPGM);
1288
return &pShwPml4->a[iPml4];
1293
* Gets the GUEST page directory pointer for the specified address.
1295
* @returns The page directory in question.
1296
* @returns NULL if the page directory is not present or on an invalid page.
1297
* @param pPGM Pointer to the PGM instance data.
1298
* @param GCPtr The address.
1299
* @param piPD Receives the index into the returned page directory
1301
DECLINLINE(PX86PDPAE) pgmGstGetLongModePDPtr(PPGMCPU pPGM, RTGCPTR64 GCPtr, unsigned *piPD)
1303
PCX86PML4 pGuestPml4 = pgmGstGetLongModePML4Ptr(pPGM);
1304
const unsigned iPml4 = (GCPtr >> X86_PML4_SHIFT) & X86_PML4_MASK;
1305
if (pGuestPml4->a[iPml4].n.u1Present)
1307
PCX86PDPT pPdptTemp;
1308
int rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pGuestPml4->a[iPml4].u & X86_PML4E_PG_MASK, &pPdptTemp);
1309
AssertRCReturn(rc, NULL);
1311
const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64;
1312
if (pPdptTemp->a[iPdpt].n.u1Present)
1315
rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pPdptTemp->a[iPdpt].u & X86_PDPE_PG_MASK, &pPD);
1316
AssertRCReturn(rc, NULL);
1318
*piPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
1328
* Gets the page state for a physical handler.
1330
* @returns The physical handler page state.
1331
* @param pCur The physical handler in question.
1333
DECLINLINE(unsigned) pgmHandlerPhysicalCalcState(PPGMPHYSHANDLER pCur)
1335
switch (pCur->enmType)
1337
case PGMPHYSHANDLERTYPE_PHYSICAL_WRITE:
1338
return PGM_PAGE_HNDL_PHYS_STATE_WRITE;
1340
case PGMPHYSHANDLERTYPE_MMIO:
1341
case PGMPHYSHANDLERTYPE_PHYSICAL_ALL:
1342
return PGM_PAGE_HNDL_PHYS_STATE_ALL;
1345
AssertFatalMsgFailed(("Invalid type %d\n", pCur->enmType));
1351
* Gets the page state for a virtual handler.
1353
* @returns The virtual handler page state.
1354
* @param pCur The virtual handler in question.
1355
* @remarks This should never be used on a hypervisor access handler.
1357
DECLINLINE(unsigned) pgmHandlerVirtualCalcState(PPGMVIRTHANDLER pCur)
1359
switch (pCur->enmType)
1361
case PGMVIRTHANDLERTYPE_WRITE:
1362
return PGM_PAGE_HNDL_VIRT_STATE_WRITE;
1363
case PGMVIRTHANDLERTYPE_ALL:
1364
return PGM_PAGE_HNDL_VIRT_STATE_ALL;
1366
AssertFatalMsgFailed(("Invalid type %d\n", pCur->enmType));
1372
* Clears one physical page of a virtual handler
1374
* @param pPGM Pointer to the PGM instance.
1375
* @param pCur Virtual handler structure
1376
* @param iPage Physical page index
1378
* @remark Only used when PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL is being set, so no
1379
* need to care about other handlers in the same page.
1381
DECLINLINE(void) pgmHandlerVirtualClearPage(PPGM pPGM, PPGMVIRTHANDLER pCur, unsigned iPage)
1383
const PPGMPHYS2VIRTHANDLER pPhys2Virt = &pCur->aPhysToVirt[iPage];
1386
* Remove the node from the tree (it's supposed to be in the tree if we get here!).
1388
#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
1389
AssertReleaseMsg(pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_IN_TREE,
1390
("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
1391
pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias));
1393
if (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_IS_HEAD)
1395
/* We're the head of the alias chain. */
1396
PPGMPHYS2VIRTHANDLER pRemove = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysRemove(&pPGM->CTX_SUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key); NOREF(pRemove);
1397
#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
1398
AssertReleaseMsg(pRemove != NULL,
1399
("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
1400
pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias));
1401
AssertReleaseMsg(pRemove == pPhys2Virt,
1402
("wanted: pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n"
1403
" got: pRemove=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
1404
pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias,
1405
pRemove, pRemove->Core.Key, pRemove->Core.KeyLast, pRemove->offVirtHandler, pRemove->offNextAlias));
1407
if (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK)
1409
/* Insert the next list in the alias chain into the tree. */
1410
PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
1411
#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
1412
AssertReleaseMsg(pNext->offNextAlias & PGMPHYS2VIRTHANDLER_IN_TREE,
1413
("pNext=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
1414
pNext, pNext->Core.Key, pNext->Core.KeyLast, pNext->offVirtHandler, pNext->offNextAlias));
1416
pNext->offNextAlias |= PGMPHYS2VIRTHANDLER_IS_HEAD;
1417
bool fRc = RTAvlroGCPhysInsert(&pPGM->CTX_SUFF(pTrees)->PhysToVirtHandlers, &pNext->Core);
1423
/* Locate the previous node in the alias chain. */
1424
PPGMPHYS2VIRTHANDLER pPrev = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGet(&pPGM->CTX_SUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key);
1425
#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
1426
AssertReleaseMsg(pPrev != pPhys2Virt,
1427
("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} pPrev=%p\n",
1428
pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias, pPrev));
1432
PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPrev + (pPrev->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
1433
if (pNext == pPhys2Virt)
1436
LogFlow(("pgmHandlerVirtualClearPage: removed %p:{.offNextAlias=%#RX32} from alias chain. prev %p:{.offNextAlias=%#RX32} [%RGp-%RGp]\n",
1437
pPhys2Virt, pPhys2Virt->offNextAlias, pPrev, pPrev->offNextAlias, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast));
1438
if (!(pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK))
1439
pPrev->offNextAlias &= ~PGMPHYS2VIRTHANDLER_OFF_MASK;
1442
PPGMPHYS2VIRTHANDLER pNewNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
1443
pPrev->offNextAlias = ((intptr_t)pNewNext - (intptr_t)pPrev)
1444
| (pPrev->offNextAlias & ~PGMPHYS2VIRTHANDLER_OFF_MASK);
1452
#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
1453
AssertReleaseMsg(pNext != pPrev,
1454
("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} pPrev=%p\n",
1455
pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias, pPrev));
1462
Log2(("PHYS2VIRT: Removing %RGp-%RGp %#RX32 %s\n",
1463
pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offNextAlias, R3STRING(pCur->pszDesc)));
1464
pPhys2Virt->offNextAlias = 0;
1465
pPhys2Virt->Core.KeyLast = NIL_RTGCPHYS; /* require reinsert */
1468
* Clear the ram flags for this page.
1470
PPGMPAGE pPage = pgmPhysGetPage(pPGM, pPhys2Virt->Core.Key);
1471
AssertReturnVoid(pPage);
1472
PGM_PAGE_SET_HNDL_VIRT_STATE(pPage, PGM_PAGE_HNDL_VIRT_STATE_NONE);
1477
* Internal worker for finding a 'in-use' shadow page give by it's physical address.
1479
* @returns Pointer to the shadow page structure.
1480
* @param pPool The pool.
1481
* @param idx The pool page index.
1483
DECLINLINE(PPGMPOOLPAGE) pgmPoolGetPageByIdx(PPGMPOOL pPool, unsigned idx)
1485
AssertFatalMsg(idx >= PGMPOOL_IDX_FIRST && idx < pPool->cCurPages, ("idx=%d\n", idx));
1486
return &pPool->aPages[idx];
1491
* Clear references to guest physical memory.
1493
* @param pPool The pool.
1494
* @param pPoolPage The pool page.
1495
* @param pPhysPage The physical guest page tracking structure.
1496
* @param iPte Shadow PTE index
1498
DECLINLINE(void) pgmTrackDerefGCPhys(PPGMPOOL pPool, PPGMPOOLPAGE pPoolPage, PPGMPAGE pPhysPage, uint16_t iPte)
1501
* Just deal with the simple case here.
1504
const unsigned uOrg = PGM_PAGE_GET_TRACKING(pPhysPage);
1506
const unsigned cRefs = PGM_PAGE_GET_TD_CREFS(pPhysPage);
1509
Assert(pPoolPage->idx == PGM_PAGE_GET_TD_IDX(pPhysPage));
1510
Assert(iPte == PGM_PAGE_GET_PTE_INDEX(pPhysPage));
1511
/* Invalidate the tracking data. */
1512
PGM_PAGE_SET_TRACKING(pPhysPage, 0);
1515
pgmPoolTrackPhysExtDerefGCPhys(pPool, pPoolPage, pPhysPage, iPte);
1516
Log2(("pgmTrackDerefGCPhys: %x -> %x pPhysPage=%R[pgmpage]\n", uOrg, PGM_PAGE_GET_TRACKING(pPhysPage), pPhysPage ));
1521
* Moves the page to the head of the age list.
1523
* This is done when the cached page is used in one way or another.
1525
* @param pPool The pool.
1526
* @param pPage The cached page.
1528
DECLINLINE(void) pgmPoolCacheUsed(PPGMPOOL pPool, PPGMPOOLPAGE pPage)
1530
PVM pVM = pPool->CTX_SUFF(pVM);
1534
* Move to the head of the age list.
1536
if (pPage->iAgePrev != NIL_PGMPOOL_IDX)
1539
pPool->aPages[pPage->iAgePrev].iAgeNext = pPage->iAgeNext;
1540
if (pPage->iAgeNext != NIL_PGMPOOL_IDX)
1541
pPool->aPages[pPage->iAgeNext].iAgePrev = pPage->iAgePrev;
1543
pPool->iAgeTail = pPage->iAgePrev;
1545
/* insert at head */
1546
pPage->iAgePrev = NIL_PGMPOOL_IDX;
1547
pPage->iAgeNext = pPool->iAgeHead;
1548
Assert(pPage->iAgeNext != NIL_PGMPOOL_IDX); /* we would've already been head then */
1549
pPool->iAgeHead = pPage->idx;
1550
pPool->aPages[pPage->iAgeNext].iAgePrev = pPage->idx;
1556
* Locks a page to prevent flushing (important for cr3 root pages or shadow pae pd pages).
1558
* @param pVM VM Handle.
1559
* @param pPage PGM pool page
1561
DECLINLINE(void) pgmPoolLockPage(PPGMPOOL pPool, PPGMPOOLPAGE pPage)
1563
Assert(PGMIsLockOwner(pPool->CTX_SUFF(pVM)));
1564
ASMAtomicIncU32(&pPage->cLocked);
1569
* Unlocks a page to allow flushing again
1571
* @param pVM VM Handle.
1572
* @param pPage PGM pool page
1574
DECLINLINE(void) pgmPoolUnlockPage(PPGMPOOL pPool, PPGMPOOLPAGE pPage)
1576
Assert(PGMIsLockOwner(pPool->CTX_SUFF(pVM)));
1577
Assert(pPage->cLocked);
1578
ASMAtomicDecU32(&pPage->cLocked);
1583
* Checks if the page is locked (e.g. the active CR3 or one of the four PDs of a PAE PDPT)
1585
* @returns VBox status code.
1586
* @param pPage PGM pool page
1588
DECLINLINE(bool) pgmPoolIsPageLocked(PPGM pPGM, PPGMPOOLPAGE pPage)
1592
LogFlow(("pgmPoolIsPageLocked found root page %d\n", pPage->enmKind));
1593
if (pPage->cModifications)
1594
pPage->cModifications = 1; /* reset counter (can't use 0, or else it will be reinserted in the modified list) */
1602
* Tells if mappings are to be put into the shadow page table or not.
1604
* @returns boolean result
1605
* @param pVM VM handle.
1607
DECL_FORCE_INLINE(bool) pgmMapAreMappingsEnabled(PPGM pPGM)
1609
#ifdef PGM_WITHOUT_MAPPINGS
1610
/* There are no mappings in VT-x and AMD-V mode. */
1611
Assert(pPGM->fMappingsDisabled);
1614
return !pPGM->fMappingsDisabled;
1620
* Checks if the mappings are floating and enabled.
1622
* @returns true / false.
1623
* @param pVM The VM handle.
1625
DECL_FORCE_INLINE(bool) pgmMapAreMappingsFloating(PPGM pPGM)
1627
#ifdef PGM_WITHOUT_MAPPINGS
1628
/* There are no mappings in VT-x and AMD-V mode. */
1629
Assert(pPGM->fMappingsDisabled);
1632
return !pPGM->fMappingsDisabled
1633
&& !pPGM->fMappingsFixed;