VirtualBox

source: vbox/trunk/src/VBox/VMM/PGMInline.h@ 28639

Last change on this file since 28639 was 28639, checked in by vboxsync, 15 years ago

Keep track of page table entry indices and deal with multiple physical page references in one page table.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 52.9 KB
Line 
1/* $Id: PGMInline.h 28639 2010-04-23 12:46:38Z vboxsync $ */
2/** @file
3 * PGM - Inlined functions.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#ifndef ___PGMInline_h
23#define ___PGMInline_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/pdmcritsect.h>
33#include <VBox/pdmapi.h>
34#include <VBox/dis.h>
35#include <VBox/dbgf.h>
36#include <VBox/log.h>
37#include <VBox/gmm.h>
38#include <VBox/hwaccm.h>
39#include <iprt/asm.h>
40#include <iprt/assert.h>
41#include <iprt/avl.h>
42#include <iprt/critsect.h>
43#include <iprt/sha.h>
44
45
46
47/** @addtogroup grp_pgm_int Internals
48 * @internal
49 * @{
50 */
51
52/** @todo Split out all the inline stuff into a separate file. Then we can
53 * include it later when VM and VMCPU are defined and so avoid all that
54 * &pVM->pgm.s and &pVCpu->pgm.s stuff. It also chops ~1600 lines off
55 * this file and will make it somewhat easier to navigate... */
56
57/**
58 * Gets the PGMRAMRANGE structure for a guest page.
59 *
60 * @returns Pointer to the RAM range on success.
61 * @returns NULL on a VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS condition.
62 *
63 * @param pPGM PGM handle.
64 * @param GCPhys The GC physical address.
65 */
66DECLINLINE(PPGMRAMRANGE) pgmPhysGetRange(PPGM pPGM, RTGCPHYS GCPhys)
67{
68 /*
69 * Optimize for the first range.
70 */
71 PPGMRAMRANGE pRam = pPGM->CTX_SUFF(pRamRanges);
72 RTGCPHYS off = GCPhys - pRam->GCPhys;
73 if (RT_UNLIKELY(off >= pRam->cb))
74 {
75 do
76 {
77 pRam = pRam->CTX_SUFF(pNext);
78 if (RT_UNLIKELY(!pRam))
79 break;
80 off = GCPhys - pRam->GCPhys;
81 } while (off >= pRam->cb);
82 }
83 return pRam;
84}
85
86
87/**
88 * Gets the PGMPAGE structure for a guest page.
89 *
90 * @returns Pointer to the page on success.
91 * @returns NULL on a VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS condition.
92 *
93 * @param pPGM PGM handle.
94 * @param GCPhys The GC physical address.
95 */
96DECLINLINE(PPGMPAGE) pgmPhysGetPage(PPGM pPGM, RTGCPHYS GCPhys)
97{
98 /*
99 * Optimize for the first range.
100 */
101 PPGMRAMRANGE pRam = pPGM->CTX_SUFF(pRamRanges);
102 RTGCPHYS off = GCPhys - pRam->GCPhys;
103 if (RT_UNLIKELY(off >= pRam->cb))
104 {
105 do
106 {
107 pRam = pRam->CTX_SUFF(pNext);
108 if (RT_UNLIKELY(!pRam))
109 return NULL;
110 off = GCPhys - pRam->GCPhys;
111 } while (off >= pRam->cb);
112 }
113 return &pRam->aPages[off >> PAGE_SHIFT];
114}
115
116
117/**
118 * Gets the PGMPAGE structure for a guest page.
119 *
120 * Old Phys code: Will make sure the page is present.
121 *
122 * @returns VBox status code.
123 * @retval VINF_SUCCESS and a valid *ppPage on success.
124 * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if the address isn't valid.
125 *
126 * @param pPGM PGM handle.
127 * @param GCPhys The GC physical address.
128 * @param ppPage Where to store the page pointer on success.
129 */
130DECLINLINE(int) pgmPhysGetPageEx(PPGM pPGM, RTGCPHYS GCPhys, PPPGMPAGE ppPage)
131{
132 /*
133 * Optimize for the first range.
134 */
135 PPGMRAMRANGE pRam = pPGM->CTX_SUFF(pRamRanges);
136 RTGCPHYS off = GCPhys - pRam->GCPhys;
137 if (RT_UNLIKELY(off >= pRam->cb))
138 {
139 do
140 {
141 pRam = pRam->CTX_SUFF(pNext);
142 if (RT_UNLIKELY(!pRam))
143 {
144 *ppPage = NULL; /* avoid incorrect and very annoying GCC warnings */
145 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
146 }
147 off = GCPhys - pRam->GCPhys;
148 } while (off >= pRam->cb);
149 }
150 *ppPage = &pRam->aPages[off >> PAGE_SHIFT];
151 return VINF_SUCCESS;
152}
153
154
155
156
157/**
158 * Gets the PGMPAGE structure for a guest page.
159 *
160 * Old Phys code: Will make sure the page is present.
161 *
162 * @returns VBox status code.
163 * @retval VINF_SUCCESS and a valid *ppPage on success.
164 * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if the address isn't valid.
165 *
166 * @param pPGM PGM handle.
167 * @param GCPhys The GC physical address.
168 * @param ppPage Where to store the page pointer on success.
169 * @param ppRamHint Where to read and store the ram list hint.
170 * The caller initializes this to NULL before the call.
171 */
172DECLINLINE(int) pgmPhysGetPageWithHintEx(PPGM pPGM, RTGCPHYS GCPhys, PPPGMPAGE ppPage, PPGMRAMRANGE *ppRamHint)
173{
174 RTGCPHYS off;
175 PPGMRAMRANGE pRam = *ppRamHint;
176 if ( !pRam
177 || RT_UNLIKELY((off = GCPhys - pRam->GCPhys) >= pRam->cb))
178 {
179 pRam = pPGM->CTX_SUFF(pRamRanges);
180 off = GCPhys - pRam->GCPhys;
181 if (RT_UNLIKELY(off >= pRam->cb))
182 {
183 do
184 {
185 pRam = pRam->CTX_SUFF(pNext);
186 if (RT_UNLIKELY(!pRam))
187 {
188 *ppPage = NULL; /* Kill the incorrect and extremely annoying GCC warnings. */
189 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
190 }
191 off = GCPhys - pRam->GCPhys;
192 } while (off >= pRam->cb);
193 }
194 *ppRamHint = pRam;
195 }
196 *ppPage = &pRam->aPages[off >> PAGE_SHIFT];
197 return VINF_SUCCESS;
198}
199
200
201/**
202 * Gets the PGMPAGE structure for a guest page together with the PGMRAMRANGE.
203 *
204 * @returns Pointer to the page on success.
205 * @returns NULL on a VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS condition.
206 *
207 * @param pPGM PGM handle.
208 * @param GCPhys The GC physical address.
209 * @param ppRam Where to store the pointer to the PGMRAMRANGE.
210 */
211DECLINLINE(PPGMPAGE) pgmPhysGetPageAndRange(PPGM pPGM, RTGCPHYS GCPhys, PPGMRAMRANGE *ppRam)
212{
213 /*
214 * Optimize for the first range.
215 */
216 PPGMRAMRANGE pRam = pPGM->CTX_SUFF(pRamRanges);
217 RTGCPHYS off = GCPhys - pRam->GCPhys;
218 if (RT_UNLIKELY(off >= pRam->cb))
219 {
220 do
221 {
222 pRam = pRam->CTX_SUFF(pNext);
223 if (RT_UNLIKELY(!pRam))
224 return NULL;
225 off = GCPhys - pRam->GCPhys;
226 } while (off >= pRam->cb);
227 }
228 *ppRam = pRam;
229 return &pRam->aPages[off >> PAGE_SHIFT];
230}
231
232
233/**
234 * Gets the PGMPAGE structure for a guest page together with the PGMRAMRANGE.
235 *
236 * @returns Pointer to the page on success.
237 * @returns NULL on a VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS condition.
238 *
239 * @param pPGM PGM handle.
240 * @param GCPhys The GC physical address.
241 * @param ppPage Where to store the pointer to the PGMPAGE structure.
242 * @param ppRam Where to store the pointer to the PGMRAMRANGE structure.
243 */
244DECLINLINE(int) pgmPhysGetPageAndRangeEx(PPGM pPGM, RTGCPHYS GCPhys, PPPGMPAGE ppPage, PPGMRAMRANGE *ppRam)
245{
246 /*
247 * Optimize for the first range.
248 */
249 PPGMRAMRANGE pRam = pPGM->CTX_SUFF(pRamRanges);
250 RTGCPHYS off = GCPhys - pRam->GCPhys;
251 if (RT_UNLIKELY(off >= pRam->cb))
252 {
253 do
254 {
255 pRam = pRam->CTX_SUFF(pNext);
256 if (RT_UNLIKELY(!pRam))
257 {
258 *ppRam = NULL; /* Shut up silly GCC warnings. */
259 *ppPage = NULL; /* ditto */
260 return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
261 }
262 off = GCPhys - pRam->GCPhys;
263 } while (off >= pRam->cb);
264 }
265 *ppRam = pRam;
266 *ppPage = &pRam->aPages[off >> PAGE_SHIFT];
267 return VINF_SUCCESS;
268}
269
270
271/**
272 * Convert GC Phys to HC Phys.
273 *
274 * @returns VBox status.
275 * @param pPGM PGM handle.
276 * @param GCPhys The GC physical address.
277 * @param pHCPhys Where to store the corresponding HC physical address.
278 *
279 * @deprecated Doesn't deal with zero, shared or write monitored pages.
280 * Avoid when writing new code!
281 */
282DECLINLINE(int) pgmRamGCPhys2HCPhys(PPGM pPGM, RTGCPHYS GCPhys, PRTHCPHYS pHCPhys)
283{
284 PPGMPAGE pPage;
285 int rc = pgmPhysGetPageEx(pPGM, GCPhys, &pPage);
286 if (RT_FAILURE(rc))
287 return rc;
288 *pHCPhys = PGM_PAGE_GET_HCPHYS(pPage) | (GCPhys & PAGE_OFFSET_MASK);
289 return VINF_SUCCESS;
290}
291
292#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
293
294/**
295 * Inlined version of the ring-0 version of PGMDynMapHCPage that
296 * optimizes access to pages already in the set.
297 *
298 * @returns VINF_SUCCESS. Will bail out to ring-3 on failure.
299 * @param pPGM Pointer to the PVM instance data.
300 * @param HCPhys The physical address of the page.
301 * @param ppv Where to store the mapping address.
302 */
303DECLINLINE(int) pgmR0DynMapHCPageInlined(PPGM pPGM, RTHCPHYS HCPhys, void **ppv)
304{
305 PVM pVM = PGM2VM(pPGM);
306 PPGMCPU pPGMCPU = (PPGMCPU)((uint8_t *)VMMGetCpu(pVM) + pPGM->offVCpuPGM); /* very pretty ;-) */
307 PPGMMAPSET pSet = &pPGMCPU->AutoSet;
308
309 STAM_PROFILE_START(&pPGMCPU->StatR0DynMapHCPageInl, a);
310 Assert(!(HCPhys & PAGE_OFFSET_MASK));
311 Assert(pSet->cEntries <= RT_ELEMENTS(pSet->aEntries));
312
313 unsigned iHash = PGMMAPSET_HASH(HCPhys);
314 unsigned iEntry = pSet->aiHashTable[iHash];
315 if ( iEntry < pSet->cEntries
316 && pSet->aEntries[iEntry].HCPhys == HCPhys)
317 {
318 *ppv = pSet->aEntries[iEntry].pvPage;
319 STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapHCPageInlHits);
320 }
321 else
322 {
323 STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapHCPageInlMisses);
324 pgmR0DynMapHCPageCommon(pVM, pSet, HCPhys, ppv);
325 }
326
327 STAM_PROFILE_STOP(&pPGMCPU->StatR0DynMapHCPageInl, a);
328 return VINF_SUCCESS;
329}
330
331
332/**
333 * Inlined version of the ring-0 version of PGMDynMapGCPage that optimizes
334 * access to pages already in the set.
335 *
336 * @returns See PGMDynMapGCPage.
337 * @param pPGM Pointer to the PVM instance data.
338 * @param GCPhys The guest physical address of the page.
339 * @param ppv Where to store the mapping address.
340 */
341DECLINLINE(int) pgmR0DynMapGCPageInlined(PPGM pPGM, RTGCPHYS GCPhys, void **ppv)
342{
343 PVM pVM = PGM2VM(pPGM);
344 PPGMCPU pPGMCPU = (PPGMCPU)((uint8_t *)VMMGetCpu(pVM) + pPGM->offVCpuPGM); /* very pretty ;-) */
345
346 STAM_PROFILE_START(&pPGMCPU->StatR0DynMapGCPageInl, a);
347 AssertMsg(!(GCPhys & PAGE_OFFSET_MASK), ("%RGp\n", GCPhys));
348
349 /*
350 * Get the ram range.
351 */
352 PPGMRAMRANGE pRam = pPGM->CTX_SUFF(pRamRanges);
353 RTGCPHYS off = GCPhys - pRam->GCPhys;
354 if (RT_UNLIKELY(off >= pRam->cb
355 /** @todo || page state stuff */))
356 {
357 /* This case is not counted into StatR0DynMapGCPageInl. */
358 STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapGCPageInlRamMisses);
359 return PGMDynMapGCPage(pVM, GCPhys, ppv);
360 }
361
362 RTHCPHYS HCPhys = PGM_PAGE_GET_HCPHYS(&pRam->aPages[off >> PAGE_SHIFT]);
363 STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapGCPageInlRamHits);
364
365 /*
366 * pgmR0DynMapHCPageInlined with out stats.
367 */
368 PPGMMAPSET pSet = &pPGMCPU->AutoSet;
369 Assert(!(HCPhys & PAGE_OFFSET_MASK));
370 Assert(pSet->cEntries <= RT_ELEMENTS(pSet->aEntries));
371
372 unsigned iHash = PGMMAPSET_HASH(HCPhys);
373 unsigned iEntry = pSet->aiHashTable[iHash];
374 if ( iEntry < pSet->cEntries
375 && pSet->aEntries[iEntry].HCPhys == HCPhys)
376 {
377 *ppv = pSet->aEntries[iEntry].pvPage;
378 STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapGCPageInlHits);
379 }
380 else
381 {
382 STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapGCPageInlMisses);
383 pgmR0DynMapHCPageCommon(pVM, pSet, HCPhys, ppv);
384 }
385
386 STAM_PROFILE_STOP(&pPGMCPU->StatR0DynMapGCPageInl, a);
387 return VINF_SUCCESS;
388}
389
390
391/**
392 * Inlined version of the ring-0 version of PGMDynMapGCPageOff that optimizes
393 * access to pages already in the set.
394 *
395 * @returns See PGMDynMapGCPage.
396 * @param pPGM Pointer to the PVM instance data.
397 * @param HCPhys The physical address of the page.
398 * @param ppv Where to store the mapping address.
399 */
400DECLINLINE(int) pgmR0DynMapGCPageOffInlined(PPGM pPGM, RTGCPHYS GCPhys, void **ppv)
401{
402 PVM pVM = PGM2VM(pPGM);
403 PPGMCPU pPGMCPU = (PPGMCPU)((uint8_t *)VMMGetCpu(pVM) + pPGM->offVCpuPGM); /* very pretty ;-) */
404
405 STAM_PROFILE_START(&pPGMCPU->StatR0DynMapGCPageInl, a);
406
407 /*
408 * Get the ram range.
409 */
410 PPGMRAMRANGE pRam = pPGM->CTX_SUFF(pRamRanges);
411 RTGCPHYS off = GCPhys - pRam->GCPhys;
412 if (RT_UNLIKELY(off >= pRam->cb
413 /** @todo || page state stuff */))
414 {
415 /* This case is not counted into StatR0DynMapGCPageInl. */
416 STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapGCPageInlRamMisses);
417 return PGMDynMapGCPageOff(pVM, GCPhys, ppv);
418 }
419
420 RTHCPHYS HCPhys = PGM_PAGE_GET_HCPHYS(&pRam->aPages[off >> PAGE_SHIFT]);
421 STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapGCPageInlRamHits);
422
423 /*
424 * pgmR0DynMapHCPageInlined with out stats.
425 */
426 PPGMMAPSET pSet = &pPGMCPU->AutoSet;
427 Assert(!(HCPhys & PAGE_OFFSET_MASK));
428 Assert(pSet->cEntries <= RT_ELEMENTS(pSet->aEntries));
429
430 unsigned iHash = PGMMAPSET_HASH(HCPhys);
431 unsigned iEntry = pSet->aiHashTable[iHash];
432 if ( iEntry < pSet->cEntries
433 && pSet->aEntries[iEntry].HCPhys == HCPhys)
434 {
435 *ppv = (void *)((uintptr_t)pSet->aEntries[iEntry].pvPage | (PAGE_OFFSET_MASK & (uintptr_t)GCPhys));
436 STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapGCPageInlHits);
437 }
438 else
439 {
440 STAM_COUNTER_INC(&pPGMCPU->StatR0DynMapGCPageInlMisses);
441 pgmR0DynMapHCPageCommon(pVM, pSet, HCPhys, ppv);
442 *ppv = (void *)((uintptr_t)*ppv | (PAGE_OFFSET_MASK & (uintptr_t)GCPhys));
443 }
444
445 STAM_PROFILE_STOP(&pPGMCPU->StatR0DynMapGCPageInl, a);
446 return VINF_SUCCESS;
447}
448
449#endif /* VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0 */
450#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
451
452/**
453 * Maps the page into current context (RC and maybe R0).
454 *
455 * @returns pointer to the mapping.
456 * @param pVM Pointer to the PGM instance data.
457 * @param pPage The page.
458 */
459DECLINLINE(void *) pgmPoolMapPageInlined(PPGM pPGM, PPGMPOOLPAGE pPage)
460{
461 if (pPage->idx >= PGMPOOL_IDX_FIRST)
462 {
463 Assert(pPage->idx < pPGM->CTX_SUFF(pPool)->cCurPages);
464 void *pv;
465# ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
466 pgmR0DynMapHCPageInlined(pPGM, pPage->Core.Key, &pv);
467# else
468 PGMDynMapHCPage(PGM2VM(pPGM), pPage->Core.Key, &pv);
469# endif
470 return pv;
471 }
472 AssertFatalMsgFailed(("pgmPoolMapPageInlined invalid page index %x\n", pPage->idx));
473}
474
475/**
476 * Temporarily maps one host page specified by HC physical address, returning
477 * pointer within the page.
478 *
479 * Be WARNED that the dynamic page mapping area is small, 8 pages, thus the space is
480 * reused after 8 mappings (or perhaps a few more if you score with the cache).
481 *
482 * @returns The address corresponding to HCPhys.
483 * @param pPGM Pointer to the PVM instance data.
484 * @param HCPhys HC Physical address of the page.
485 */
486DECLINLINE(void *) pgmDynMapHCPageOff(PPGM pPGM, RTHCPHYS HCPhys)
487{
488 void *pv;
489# ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
490 pgmR0DynMapHCPageInlined(pPGM, HCPhys & ~(RTHCPHYS)PAGE_OFFSET_MASK, &pv);
491# else
492 PGMDynMapHCPage(PGM2VM(pPGM), HCPhys & ~(RTHCPHYS)PAGE_OFFSET_MASK, &pv);
493# endif
494 pv = (void *)((uintptr_t)pv | ((uintptr_t)HCPhys & PAGE_OFFSET_MASK));
495 return pv;
496}
497
498#endif /* VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0 || IN_RC */
499#ifndef IN_RC
500
501/**
502 * Queries the Physical TLB entry for a physical guest page,
503 * attempting to load the TLB entry if necessary.
504 *
505 * @returns VBox status code.
506 * @retval VINF_SUCCESS on success
507 * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if it's not a valid physical address.
508 *
509 * @param pPGM The PGM instance handle.
510 * @param GCPhys The address of the guest page.
511 * @param ppTlbe Where to store the pointer to the TLB entry.
512 */
513DECLINLINE(int) pgmPhysPageQueryTlbe(PPGM pPGM, RTGCPHYS GCPhys, PPPGMPAGEMAPTLBE ppTlbe)
514{
515 int rc;
516 PPGMPAGEMAPTLBE pTlbe = &pPGM->CTXSUFF(PhysTlb).aEntries[PGM_PAGEMAPTLB_IDX(GCPhys)];
517 if (pTlbe->GCPhys == (GCPhys & X86_PTE_PAE_PG_MASK))
518 {
519 STAM_COUNTER_INC(&pPGM->CTX_MID_Z(Stat,PageMapTlbHits));
520 rc = VINF_SUCCESS;
521 }
522 else
523 rc = pgmPhysPageLoadIntoTlb(pPGM, GCPhys);
524 *ppTlbe = pTlbe;
525 return rc;
526}
527
528
529/**
530 * Queries the Physical TLB entry for a physical guest page,
531 * attempting to load the TLB entry if necessary.
532 *
533 * @returns VBox status code.
534 * @retval VINF_SUCCESS on success
535 * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if it's not a valid physical address.
536 *
537 * @param pPGM The PGM instance handle.
538 * @param pPage Pointer to the PGMPAGE structure corresponding to
539 * GCPhys.
540 * @param GCPhys The address of the guest page.
541 * @param ppTlbe Where to store the pointer to the TLB entry.
542 */
543DECLINLINE(int) pgmPhysPageQueryTlbeWithPage(PPGM pPGM, PPGMPAGE pPage, RTGCPHYS GCPhys, PPPGMPAGEMAPTLBE ppTlbe)
544{
545 int rc;
546 PPGMPAGEMAPTLBE pTlbe = &pPGM->CTXSUFF(PhysTlb).aEntries[PGM_PAGEMAPTLB_IDX(GCPhys)];
547 if (pTlbe->GCPhys == (GCPhys & X86_PTE_PAE_PG_MASK))
548 {
549 STAM_COUNTER_INC(&pPGM->CTX_MID_Z(Stat,PageMapTlbHits));
550 rc = VINF_SUCCESS;
551 }
552 else
553 rc = pgmPhysPageLoadIntoTlbWithPage(pPGM, pPage, GCPhys);
554 *ppTlbe = pTlbe;
555 return rc;
556}
557
558#endif /* !IN_RC */
559
560/**
561 * Calculated the guest physical address of the large (4 MB) page in 32 bits paging mode.
562 * Takes PSE-36 into account.
563 *
564 * @returns guest physical address
565 * @param pPGM Pointer to the PGM instance data.
566 * @param Pde Guest Pde
567 */
568DECLINLINE(RTGCPHYS) pgmGstGet4MBPhysPage(PPGM pPGM, X86PDE Pde)
569{
570 RTGCPHYS GCPhys = Pde.u & X86_PDE4M_PG_MASK;
571 GCPhys |= (RTGCPHYS)Pde.b.u8PageNoHigh << 32;
572
573 return GCPhys & pPGM->GCPhys4MBPSEMask;
574}
575
576
577/**
578 * Gets the page directory entry for the specified address (32-bit paging).
579 *
580 * @returns The page directory entry in question.
581 * @param pPGM Pointer to the PGM instance data.
582 * @param GCPtr The address.
583 */
584DECLINLINE(X86PDE) pgmGstGet32bitPDE(PPGMCPU pPGM, RTGCPTR GCPtr)
585{
586#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
587 PCX86PD pGuestPD = NULL;
588 int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pPGM->GCPhysCR3, (void **)&pGuestPD);
589 if (RT_FAILURE(rc))
590 {
591 X86PDE ZeroPde = {0};
592 AssertMsgFailedReturn(("%Rrc\n", rc), ZeroPde);
593 }
594#else
595 PX86PD pGuestPD = pPGM->CTX_SUFF(pGst32BitPd);
596# ifdef IN_RING3
597 if (!pGuestPD)
598 pGuestPD = pgmGstLazyMap32BitPD(pPGM);
599# endif
600#endif
601 return pGuestPD->a[GCPtr >> X86_PD_SHIFT];
602}
603
604
605/**
606 * Gets the address of a specific page directory entry (32-bit paging).
607 *
608 * @returns Pointer the page directory entry in question.
609 * @param pPGM Pointer to the PGM instance data.
610 * @param GCPtr The address.
611 */
612DECLINLINE(PX86PDE) pgmGstGet32bitPDEPtr(PPGMCPU pPGM, RTGCPTR GCPtr)
613{
614#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
615 PX86PD pGuestPD = NULL;
616 int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pPGM->GCPhysCR3, (void **)&pGuestPD);
617 AssertRCReturn(rc, NULL);
618#else
619 PX86PD pGuestPD = pPGM->CTX_SUFF(pGst32BitPd);
620# ifdef IN_RING3
621 if (!pGuestPD)
622 pGuestPD = pgmGstLazyMap32BitPD(pPGM);
623# endif
624#endif
625 return &pGuestPD->a[GCPtr >> X86_PD_SHIFT];
626}
627
628
629/**
630 * Gets the address the guest page directory (32-bit paging).
631 *
632 * @returns Pointer the page directory entry in question.
633 * @param pPGM Pointer to the PGM instance data.
634 */
635DECLINLINE(PX86PD) pgmGstGet32bitPDPtr(PPGMCPU pPGM)
636{
637#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
638 PX86PD pGuestPD = NULL;
639 int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pPGM->GCPhysCR3, (void **)&pGuestPD);
640 AssertRCReturn(rc, NULL);
641#else
642 PX86PD pGuestPD = pPGM->CTX_SUFF(pGst32BitPd);
643# ifdef IN_RING3
644 if (!pGuestPD)
645 pGuestPD = pgmGstLazyMap32BitPD(pPGM);
646# endif
647#endif
648 return pGuestPD;
649}
650
651
652/**
653 * Gets the guest page directory pointer table.
654 *
655 * @returns Pointer to the page directory in question.
656 * @returns NULL if the page directory is not present or on an invalid page.
657 * @param pPGM Pointer to the PGM instance data.
658 */
659DECLINLINE(PX86PDPT) pgmGstGetPaePDPTPtr(PPGMCPU pPGM)
660{
661#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
662 PX86PDPT pGuestPDPT = NULL;
663 int rc = pgmR0DynMapGCPageOffInlined(PGMCPU2PGM(pPGM), pPGM->GCPhysCR3, (void **)&pGuestPDPT);
664 AssertRCReturn(rc, NULL);
665#else
666 PX86PDPT pGuestPDPT = pPGM->CTX_SUFF(pGstPaePdpt);
667# ifdef IN_RING3
668 if (!pGuestPDPT)
669 pGuestPDPT = pgmGstLazyMapPaePDPT(pPGM);
670# endif
671#endif
672 return pGuestPDPT;
673}
674
675
676/**
677 * Gets the guest page directory pointer table entry for the specified address.
678 *
679 * @returns Pointer to the page directory in question.
680 * @returns NULL if the page directory is not present or on an invalid page.
681 * @param pPGM Pointer to the PGM instance data.
682 * @param GCPtr The address.
683 */
684DECLINLINE(PX86PDPE) pgmGstGetPaePDPEPtr(PPGMCPU pPGM, RTGCPTR GCPtr)
685{
686 AssertGCPtr32(GCPtr);
687
688#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
689 PX86PDPT pGuestPDPT = 0;
690 int rc = pgmR0DynMapGCPageOffInlined(PGMCPU2PGM(pPGM), pPGM->GCPhysCR3, (void **)&pGuestPDPT);
691 AssertRCReturn(rc, 0);
692#else
693 PX86PDPT pGuestPDPT = pPGM->CTX_SUFF(pGstPaePdpt);
694# ifdef IN_RING3
695 if (!pGuestPDPT)
696 pGuestPDPT = pgmGstLazyMapPaePDPT(pPGM);
697# endif
698#endif
699 return &pGuestPDPT->a[(GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE];
700}
701
702
703/**
704 * Gets the page directory for the specified address.
705 *
706 * @returns Pointer to the page directory in question.
707 * @returns NULL if the page directory is not present or on an invalid page.
708 * @param pPGM Pointer to the PGM instance data.
709 * @param GCPtr The address.
710 */
711DECLINLINE(PX86PDPAE) pgmGstGetPaePD(PPGMCPU pPGM, RTGCPTR GCPtr)
712{
713 AssertGCPtr32(GCPtr);
714
715 PX86PDPT pGuestPDPT = pgmGstGetPaePDPTPtr(pPGM);
716 AssertReturn(pGuestPDPT, NULL);
717 const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE;
718 if (pGuestPDPT->a[iPdpt].n.u1Present)
719 {
720#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
721 PX86PDPAE pGuestPD = NULL;
722 int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pGuestPDPT->a[iPdpt].u & X86_PDPE_PG_MASK, (void **)&pGuestPD);
723 AssertRCReturn(rc, NULL);
724#else
725 PX86PDPAE pGuestPD = pPGM->CTX_SUFF(apGstPaePDs)[iPdpt];
726 if ( !pGuestPD
727 || (pGuestPDPT->a[iPdpt].u & X86_PDPE_PG_MASK) != pPGM->aGCPhysGstPaePDs[iPdpt])
728 pGuestPD = pgmGstLazyMapPaePD(pPGM, iPdpt);
729#endif
730 return pGuestPD;
731 /* returning NULL is ok if we assume it's just an invalid page of some kind emulated as all 0s. (not quite true) */
732 }
733 return NULL;
734}
735
736
737/**
738 * Gets the page directory entry for the specified address.
739 *
740 * @returns Pointer to the page directory entry in question.
741 * @returns NULL if the page directory is not present or on an invalid page.
742 * @param pPGM Pointer to the PGM instance data.
743 * @param GCPtr The address.
744 */
745DECLINLINE(PX86PDEPAE) pgmGstGetPaePDEPtr(PPGMCPU pPGM, RTGCPTR GCPtr)
746{
747 AssertGCPtr32(GCPtr);
748
749 PX86PDPT pGuestPDPT = pgmGstGetPaePDPTPtr(pPGM);
750 AssertReturn(pGuestPDPT, NULL);
751 const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE;
752 if (pGuestPDPT->a[iPdpt].n.u1Present)
753 {
754 const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
755#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
756 PX86PDPAE pGuestPD = NULL;
757 int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pGuestPDPT->a[iPdpt].u & X86_PDPE_PG_MASK, (void **)&pGuestPD);
758 AssertRCReturn(rc, NULL);
759#else
760 PX86PDPAE pGuestPD = pPGM->CTX_SUFF(apGstPaePDs)[iPdpt];
761 if ( !pGuestPD
762 || (pGuestPDPT->a[iPdpt].u & X86_PDPE_PG_MASK) != pPGM->aGCPhysGstPaePDs[iPdpt])
763 pGuestPD = pgmGstLazyMapPaePD(pPGM, iPdpt);
764#endif
765 return &pGuestPD->a[iPD];
766 /* 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) */
767 }
768 return NULL;
769}
770
771
772/**
773 * Gets the page directory entry for the specified address.
774 *
775 * @returns The page directory entry in question.
776 * @returns A non-present entry if the page directory is not present or on an invalid page.
777 * @param pPGM Pointer to the PGM instance data.
778 * @param GCPtr The address.
779 */
780DECLINLINE(X86PDEPAE) pgmGstGetPaePDE(PPGMCPU pPGM, RTGCPTR GCPtr)
781{
782 AssertGCPtr32(GCPtr);
783 X86PDEPAE ZeroPde = {0};
784 PX86PDPT pGuestPDPT = pgmGstGetPaePDPTPtr(pPGM);
785 if (RT_LIKELY(pGuestPDPT))
786 {
787 const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE;
788 if (pGuestPDPT->a[iPdpt].n.u1Present)
789 {
790 const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
791#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
792 PX86PDPAE pGuestPD = NULL;
793 int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pGuestPDPT->a[iPdpt].u & X86_PDPE_PG_MASK, (void **)&pGuestPD);
794 AssertRCReturn(rc, ZeroPde);
795#else
796 PX86PDPAE pGuestPD = pPGM->CTX_SUFF(apGstPaePDs)[iPdpt];
797 if ( !pGuestPD
798 || (pGuestPDPT->a[iPdpt].u & X86_PDPE_PG_MASK) != pPGM->aGCPhysGstPaePDs[iPdpt])
799 pGuestPD = pgmGstLazyMapPaePD(pPGM, iPdpt);
800#endif
801 return pGuestPD->a[iPD];
802 }
803 }
804 return ZeroPde;
805}
806
807
808/**
809 * Gets the page directory pointer table entry for the specified address
810 * and returns the index into the page directory
811 *
812 * @returns Pointer to the page directory in question.
813 * @returns NULL if the page directory is not present or on an invalid page.
814 * @param pPGM Pointer to the PGM instance data.
815 * @param GCPtr The address.
816 * @param piPD Receives the index into the returned page directory
817 * @param pPdpe Receives the page directory pointer entry. Optional.
818 */
819DECLINLINE(PX86PDPAE) pgmGstGetPaePDPtr(PPGMCPU pPGM, RTGCPTR GCPtr, unsigned *piPD, PX86PDPE pPdpe)
820{
821 AssertGCPtr32(GCPtr);
822
823 PX86PDPT pGuestPDPT = pgmGstGetPaePDPTPtr(pPGM);
824 AssertReturn(pGuestPDPT, NULL);
825 const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE;
826 if (pPdpe)
827 *pPdpe = pGuestPDPT->a[iPdpt];
828 if (pGuestPDPT->a[iPdpt].n.u1Present)
829 {
830 const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
831#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
832 PX86PDPAE pGuestPD = NULL;
833 int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pGuestPDPT->a[iPdpt].u & X86_PDPE_PG_MASK, (void **)&pGuestPD);
834 AssertRCReturn(rc, NULL);
835#else
836 PX86PDPAE pGuestPD = pPGM->CTX_SUFF(apGstPaePDs)[iPdpt];
837 if ( !pGuestPD
838 || (pGuestPDPT->a[iPdpt].u & X86_PDPE_PG_MASK) != pPGM->aGCPhysGstPaePDs[iPdpt])
839 pGuestPD = pgmGstLazyMapPaePD(pPGM, iPdpt);
840#endif
841 *piPD = iPD;
842 return pGuestPD;
843 /* returning NIL_RTGCPHYS is ok if we assume it's just an invalid page of some kind emulated as all 0s. */
844 }
845 return NULL;
846}
847
848#ifndef IN_RC
849
850/**
851 * Gets the page map level-4 pointer for the guest.
852 *
853 * @returns Pointer to the PML4 page.
854 * @param pPGM Pointer to the PGM instance data.
855 */
856DECLINLINE(PX86PML4) pgmGstGetLongModePML4Ptr(PPGMCPU pPGM)
857{
858#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
859 PX86PML4 pGuestPml4;
860 int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pPGM->GCPhysCR3, (void **)&pGuestPml4);
861 AssertRCReturn(rc, NULL);
862#else
863 PX86PML4 pGuestPml4 = pPGM->CTX_SUFF(pGstAmd64Pml4);
864# ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R3
865 if (!pGuestPml4)
866 pGuestPml4 = pgmGstLazyMapPml4(pPGM);
867# endif
868 Assert(pGuestPml4);
869#endif
870 return pGuestPml4;
871}
872
873
874/**
875 * Gets the pointer to a page map level-4 entry.
876 *
877 * @returns Pointer to the PML4 entry.
878 * @param pPGM Pointer to the PGM instance data.
879 * @param iPml4 The index.
880 */
881DECLINLINE(PX86PML4E) pgmGstGetLongModePML4EPtr(PPGMCPU pPGM, unsigned int iPml4)
882{
883#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
884 PX86PML4 pGuestPml4;
885 int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pPGM->GCPhysCR3, (void **)&pGuestPml4);
886 AssertRCReturn(rc, NULL);
887#else
888 PX86PML4 pGuestPml4 = pPGM->CTX_SUFF(pGstAmd64Pml4);
889# ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R3
890 if (!pGuestPml4)
891 pGuestPml4 = pgmGstLazyMapPml4(pPGM);
892# endif
893 Assert(pGuestPml4);
894#endif
895 return &pGuestPml4->a[iPml4];
896}
897
898
899/**
900 * Gets a page map level-4 entry.
901 *
902 * @returns The PML4 entry.
903 * @param pPGM Pointer to the PGM instance data.
904 * @param iPml4 The index.
905 */
906DECLINLINE(X86PML4E) pgmGstGetLongModePML4E(PPGMCPU pPGM, unsigned int iPml4)
907{
908#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
909 PX86PML4 pGuestPml4;
910 int rc = pgmR0DynMapGCPageInlined(PGMCPU2PGM(pPGM), pPGM->GCPhysCR3, (void **)&pGuestPml4);
911 if (RT_FAILURE(rc))
912 {
913 X86PML4E ZeroPml4e = {0};
914 AssertMsgFailedReturn(("%Rrc\n", rc), ZeroPml4e);
915 }
916#else
917 PX86PML4 pGuestPml4 = pPGM->CTX_SUFF(pGstAmd64Pml4);
918# ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R3
919 if (!pGuestPml4)
920 pGuestPml4 = pgmGstLazyMapPml4(pPGM);
921# endif
922 Assert(pGuestPml4);
923#endif
924 return pGuestPml4->a[iPml4];
925}
926
927
928/**
929 * Gets the page directory pointer entry for the specified address.
930 *
931 * @returns Pointer to the page directory pointer entry in question.
932 * @returns NULL if the page directory is not present or on an invalid page.
933 * @param pPGM Pointer to the PGM instance data.
934 * @param GCPtr The address.
935 * @param ppPml4e Page Map Level-4 Entry (out)
936 */
937DECLINLINE(PX86PDPE) pgmGstGetLongModePDPTPtr(PPGMCPU pPGM, RTGCPTR64 GCPtr, PX86PML4E *ppPml4e)
938{
939 PX86PML4 pGuestPml4 = pgmGstGetLongModePML4Ptr(pPGM);
940 const unsigned iPml4 = (GCPtr >> X86_PML4_SHIFT) & X86_PML4_MASK;
941 PCX86PML4E pPml4e = *ppPml4e = &pGuestPml4->a[iPml4];
942 if (pPml4e->n.u1Present)
943 {
944 PX86PDPT pPdpt;
945 int rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pPml4e->u & X86_PML4E_PG_MASK, &pPdpt);
946 AssertRCReturn(rc, NULL);
947
948 const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64;
949 return &pPdpt->a[iPdpt];
950 }
951 return NULL;
952}
953
954
955/**
956 * Gets the page directory entry for the specified address.
957 *
958 * @returns The page directory entry in question.
959 * @returns A non-present entry if the page directory is not present or on an invalid page.
960 * @param pPGM Pointer to the PGM instance data.
961 * @param GCPtr The address.
962 * @param ppPml4e Page Map Level-4 Entry (out)
963 * @param pPdpe Page directory pointer table entry (out)
964 */
965DECLINLINE(X86PDEPAE) pgmGstGetLongModePDEEx(PPGMCPU pPGM, RTGCPTR64 GCPtr, PX86PML4E *ppPml4e, PX86PDPE pPdpe)
966{
967 X86PDEPAE ZeroPde = {0};
968 PX86PML4 pGuestPml4 = pgmGstGetLongModePML4Ptr(pPGM);
969 const unsigned iPml4 = (GCPtr >> X86_PML4_SHIFT) & X86_PML4_MASK;
970 PCX86PML4E pPml4e = *ppPml4e = &pGuestPml4->a[iPml4];
971 if (pPml4e->n.u1Present)
972 {
973 PCX86PDPT pPdptTemp;
974 int rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pPml4e->u & X86_PML4E_PG_MASK, &pPdptTemp);
975 AssertRCReturn(rc, ZeroPde);
976
977 const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64;
978 *pPdpe = pPdptTemp->a[iPdpt];
979 if (pPdptTemp->a[iPdpt].n.u1Present)
980 {
981 PCX86PDPAE pPD;
982 rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pPdptTemp->a[iPdpt].u & X86_PDPE_PG_MASK, &pPD);
983 AssertRCReturn(rc, ZeroPde);
984
985 const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
986 return pPD->a[iPD];
987 }
988 }
989
990 return ZeroPde;
991}
992
993
994/**
995 * Gets the page directory entry for the specified address.
996 *
997 * @returns The page directory entry in question.
998 * @returns A non-present entry if the page directory is not present or on an invalid page.
999 * @param pPGM Pointer to the PGM instance data.
1000 * @param GCPtr The address.
1001 */
1002DECLINLINE(X86PDEPAE) pgmGstGetLongModePDE(PPGMCPU pPGM, RTGCPTR64 GCPtr)
1003{
1004 X86PDEPAE ZeroPde = {0};
1005 PCX86PML4 pGuestPml4 = pgmGstGetLongModePML4Ptr(pPGM);
1006 const unsigned iPml4 = (GCPtr >> X86_PML4_SHIFT) & X86_PML4_MASK;
1007 if (pGuestPml4->a[iPml4].n.u1Present)
1008 {
1009 PCX86PDPT pPdptTemp;
1010 int rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pGuestPml4->a[iPml4].u & X86_PML4E_PG_MASK, &pPdptTemp);
1011 AssertRCReturn(rc, ZeroPde);
1012
1013 const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64;
1014 if (pPdptTemp->a[iPdpt].n.u1Present)
1015 {
1016 PCX86PDPAE pPD;
1017 rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pPdptTemp->a[iPdpt].u & X86_PDPE_PG_MASK, &pPD);
1018 AssertRCReturn(rc, ZeroPde);
1019
1020 const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
1021 return pPD->a[iPD];
1022 }
1023 }
1024 return ZeroPde;
1025}
1026
1027
1028/**
1029 * Gets the page directory entry for the specified address.
1030 *
1031 * @returns Pointer to the page directory entry in question.
1032 * @returns NULL if the page directory is not present or on an invalid page.
1033 * @param pPGM Pointer to the PGM instance data.
1034 * @param GCPtr The address.
1035 */
1036DECLINLINE(PX86PDEPAE) pgmGstGetLongModePDEPtr(PPGMCPU pPGM, RTGCPTR64 GCPtr)
1037{
1038 PCX86PML4 pGuestPml4 = pgmGstGetLongModePML4Ptr(pPGM);
1039 const unsigned iPml4 = (GCPtr >> X86_PML4_SHIFT) & X86_PML4_MASK;
1040 if (pGuestPml4->a[iPml4].n.u1Present)
1041 {
1042 PCX86PDPT pPdptTemp;
1043 int rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pGuestPml4->a[iPml4].u & X86_PML4E_PG_MASK, &pPdptTemp);
1044 AssertRCReturn(rc, NULL);
1045
1046 const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64;
1047 if (pPdptTemp->a[iPdpt].n.u1Present)
1048 {
1049 PX86PDPAE pPD;
1050 rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pPdptTemp->a[iPdpt].u & X86_PDPE_PG_MASK, &pPD);
1051 AssertRCReturn(rc, NULL);
1052
1053 const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
1054 return &pPD->a[iPD];
1055 }
1056 }
1057 return NULL;
1058}
1059
1060
1061/**
1062 * Gets the GUEST page directory pointer for the specified address.
1063 *
1064 * @returns The page directory in question.
1065 * @returns NULL if the page directory is not present or on an invalid page.
1066 * @param pPGM Pointer to the PGM instance data.
1067 * @param GCPtr The address.
1068 * @param ppPml4e Page Map Level-4 Entry (out)
1069 * @param pPdpe Page directory pointer table entry (out)
1070 * @param piPD Receives the index into the returned page directory
1071 */
1072DECLINLINE(PX86PDPAE) pgmGstGetLongModePDPtr(PPGMCPU pPGM, RTGCPTR64 GCPtr, PX86PML4E *ppPml4e, PX86PDPE pPdpe, unsigned *piPD)
1073{
1074 PX86PML4 pGuestPml4 = pgmGstGetLongModePML4Ptr(pPGM);
1075 const unsigned iPml4 = (GCPtr >> X86_PML4_SHIFT) & X86_PML4_MASK;
1076 PCX86PML4E pPml4e = *ppPml4e = &pGuestPml4->a[iPml4];
1077 if (pPml4e->n.u1Present)
1078 {
1079 PCX86PDPT pPdptTemp;
1080 int rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pPml4e->u & X86_PML4E_PG_MASK, &pPdptTemp);
1081 AssertRCReturn(rc, NULL);
1082
1083 const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64;
1084 *pPdpe = pPdptTemp->a[iPdpt];
1085 if (pPdptTemp->a[iPdpt].n.u1Present)
1086 {
1087 PX86PDPAE pPD;
1088 rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pPdptTemp->a[iPdpt].u & X86_PDPE_PG_MASK, &pPD);
1089 AssertRCReturn(rc, NULL);
1090
1091 *piPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
1092 return pPD;
1093 }
1094 }
1095 return 0;
1096}
1097
1098#endif /* !IN_RC */
1099
1100/**
1101 * Gets the shadow page directory, 32-bit.
1102 *
1103 * @returns Pointer to the shadow 32-bit PD.
1104 * @param pPGM Pointer to the PGM instance data.
1105 */
1106DECLINLINE(PX86PD) pgmShwGet32BitPDPtr(PPGMCPU pPGM)
1107{
1108 return (PX86PD)PGMPOOL_PAGE_2_PTR_BY_PGMCPU(pPGM, pPGM->CTX_SUFF(pShwPageCR3));
1109}
1110
1111
1112/**
1113 * Gets the shadow page directory entry for the specified address, 32-bit.
1114 *
1115 * @returns Shadow 32-bit PDE.
1116 * @param pPGM Pointer to the PGM instance data.
1117 * @param GCPtr The address.
1118 */
1119DECLINLINE(X86PDE) pgmShwGet32BitPDE(PPGMCPU pPGM, RTGCPTR GCPtr)
1120{
1121 const unsigned iPd = (GCPtr >> X86_PD_SHIFT) & X86_PD_MASK;
1122
1123 PX86PD pShwPde = pgmShwGet32BitPDPtr(pPGM);
1124 if (!pShwPde)
1125 {
1126 X86PDE ZeroPde = {0};
1127 return ZeroPde;
1128 }
1129 return pShwPde->a[iPd];
1130}
1131
1132
1133/**
1134 * Gets the pointer to the shadow page directory entry for the specified
1135 * address, 32-bit.
1136 *
1137 * @returns Pointer to the shadow 32-bit PDE.
1138 * @param pPGM Pointer to the PGM instance data.
1139 * @param GCPtr The address.
1140 */
1141DECLINLINE(PX86PDE) pgmShwGet32BitPDEPtr(PPGMCPU pPGM, RTGCPTR GCPtr)
1142{
1143 const unsigned iPd = (GCPtr >> X86_PD_SHIFT) & X86_PD_MASK;
1144
1145 PX86PD pPde = pgmShwGet32BitPDPtr(pPGM);
1146 AssertReturn(pPde, NULL);
1147 return &pPde->a[iPd];
1148}
1149
1150
1151/**
1152 * Gets the shadow page pointer table, PAE.
1153 *
1154 * @returns Pointer to the shadow PAE PDPT.
1155 * @param pPGM Pointer to the PGM instance data.
1156 */
1157DECLINLINE(PX86PDPT) pgmShwGetPaePDPTPtr(PPGMCPU pPGM)
1158{
1159 return (PX86PDPT)PGMPOOL_PAGE_2_PTR_BY_PGMCPU(pPGM, pPGM->CTX_SUFF(pShwPageCR3));
1160}
1161
1162
1163/**
1164 * Gets the shadow page directory for the specified address, PAE.
1165 *
1166 * @returns Pointer to the shadow PD.
1167 * @param pPGM Pointer to the PGM instance data.
1168 * @param GCPtr The address.
1169 */
1170DECLINLINE(PX86PDPAE) pgmShwGetPaePDPtr(PPGMCPU pPGM, RTGCPTR GCPtr)
1171{
1172 const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE;
1173 PX86PDPT pPdpt = pgmShwGetPaePDPTPtr(pPGM);
1174
1175 if (!pPdpt->a[iPdpt].n.u1Present)
1176 return NULL;
1177
1178 /* Fetch the pgm pool shadow descriptor. */
1179 PPGMPOOLPAGE pShwPde = pgmPoolGetPage(PGMCPU2PGM(pPGM)->CTX_SUFF(pPool), pPdpt->a[iPdpt].u & X86_PDPE_PG_MASK);
1180 AssertReturn(pShwPde, NULL);
1181
1182 return (PX86PDPAE)PGMPOOL_PAGE_2_PTR_BY_PGMCPU(pPGM, pShwPde);
1183}
1184
1185
1186/**
1187 * Gets the shadow page directory for the specified address, PAE.
1188 *
1189 * @returns Pointer to the shadow PD.
1190 * @param pPGM Pointer to the PGM instance data.
1191 * @param GCPtr The address.
1192 */
1193DECLINLINE(PX86PDPAE) pgmShwGetPaePDPtr(PPGMCPU pPGM, PX86PDPT pPdpt, RTGCPTR GCPtr)
1194{
1195 const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE;
1196
1197 if (!pPdpt->a[iPdpt].n.u1Present)
1198 return NULL;
1199
1200 /* Fetch the pgm pool shadow descriptor. */
1201 PPGMPOOLPAGE pShwPde = pgmPoolGetPage(PGMCPU2PGM(pPGM)->CTX_SUFF(pPool), pPdpt->a[iPdpt].u & X86_PDPE_PG_MASK);
1202 AssertReturn(pShwPde, NULL);
1203
1204 return (PX86PDPAE)PGMPOOL_PAGE_2_PTR_BY_PGMCPU(pPGM, pShwPde);
1205}
1206
1207
1208/**
1209 * Gets the shadow page directory entry, PAE.
1210 *
1211 * @returns PDE.
1212 * @param pPGM Pointer to the PGM instance data.
1213 * @param GCPtr The address.
1214 */
1215DECLINLINE(X86PDEPAE) pgmShwGetPaePDE(PPGMCPU pPGM, RTGCPTR GCPtr)
1216{
1217 const unsigned iPd = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
1218
1219 PX86PDPAE pShwPde = pgmShwGetPaePDPtr(pPGM, GCPtr);
1220 if (!pShwPde)
1221 {
1222 X86PDEPAE ZeroPde = {0};
1223 return ZeroPde;
1224 }
1225 return pShwPde->a[iPd];
1226}
1227
1228
1229/**
1230 * Gets the pointer to the shadow page directory entry for an address, PAE.
1231 *
1232 * @returns Pointer to the PDE.
1233 * @param pPGM Pointer to the PGM instance data.
1234 * @param GCPtr The address.
1235 */
1236DECLINLINE(PX86PDEPAE) pgmShwGetPaePDEPtr(PPGMCPU pPGM, RTGCPTR GCPtr)
1237{
1238 const unsigned iPd = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
1239
1240 PX86PDPAE pPde = pgmShwGetPaePDPtr(pPGM, GCPtr);
1241 AssertReturn(pPde, NULL);
1242 return &pPde->a[iPd];
1243}
1244
1245#ifndef IN_RC
1246
1247/**
1248 * Gets the shadow page map level-4 pointer.
1249 *
1250 * @returns Pointer to the shadow PML4.
1251 * @param pPGM Pointer to the PGM instance data.
1252 */
1253DECLINLINE(PX86PML4) pgmShwGetLongModePML4Ptr(PPGMCPU pPGM)
1254{
1255 return (PX86PML4)PGMPOOL_PAGE_2_PTR_BY_PGMCPU(pPGM, pPGM->CTX_SUFF(pShwPageCR3));
1256}
1257
1258
1259/**
1260 * Gets the shadow page map level-4 entry for the specified address.
1261 *
1262 * @returns The entry.
1263 * @param pPGM Pointer to the PGM instance data.
1264 * @param GCPtr The address.
1265 */
1266DECLINLINE(X86PML4E) pgmShwGetLongModePML4E(PPGMCPU pPGM, RTGCPTR GCPtr)
1267{
1268 const unsigned iPml4 = ((RTGCUINTPTR64)GCPtr >> X86_PML4_SHIFT) & X86_PML4_MASK;
1269 PX86PML4 pShwPml4 = pgmShwGetLongModePML4Ptr(pPGM);
1270
1271 if (!pShwPml4)
1272 {
1273 X86PML4E ZeroPml4e = {0};
1274 return ZeroPml4e;
1275 }
1276 return pShwPml4->a[iPml4];
1277}
1278
1279
1280/**
1281 * Gets the pointer to the specified shadow page map level-4 entry.
1282 *
1283 * @returns The entry.
1284 * @param pPGM Pointer to the PGM instance data.
1285 * @param iPml4 The PML4 index.
1286 */
1287DECLINLINE(PX86PML4E) pgmShwGetLongModePML4EPtr(PPGMCPU pPGM, unsigned int iPml4)
1288{
1289 PX86PML4 pShwPml4 = pgmShwGetLongModePML4Ptr(pPGM);
1290 if (!pShwPml4)
1291 return NULL;
1292 return &pShwPml4->a[iPml4];
1293}
1294
1295
1296/**
1297 * Gets the GUEST page directory pointer for the specified address.
1298 *
1299 * @returns The page directory in question.
1300 * @returns NULL if the page directory is not present or on an invalid page.
1301 * @param pPGM Pointer to the PGM instance data.
1302 * @param GCPtr The address.
1303 * @param piPD Receives the index into the returned page directory
1304 */
1305DECLINLINE(PX86PDPAE) pgmGstGetLongModePDPtr(PPGMCPU pPGM, RTGCPTR64 GCPtr, unsigned *piPD)
1306{
1307 PCX86PML4 pGuestPml4 = pgmGstGetLongModePML4Ptr(pPGM);
1308 const unsigned iPml4 = (GCPtr >> X86_PML4_SHIFT) & X86_PML4_MASK;
1309 if (pGuestPml4->a[iPml4].n.u1Present)
1310 {
1311 PCX86PDPT pPdptTemp;
1312 int rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pGuestPml4->a[iPml4].u & X86_PML4E_PG_MASK, &pPdptTemp);
1313 AssertRCReturn(rc, NULL);
1314
1315 const unsigned iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64;
1316 if (pPdptTemp->a[iPdpt].n.u1Present)
1317 {
1318 PX86PDPAE pPD;
1319 rc = PGM_GCPHYS_2_PTR_BY_PGMCPU(pPGM, pPdptTemp->a[iPdpt].u & X86_PDPE_PG_MASK, &pPD);
1320 AssertRCReturn(rc, NULL);
1321
1322 *piPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
1323 return pPD;
1324 }
1325 }
1326 return NULL;
1327}
1328
1329#endif /* !IN_RC */
1330
1331/**
1332 * Gets the page state for a physical handler.
1333 *
1334 * @returns The physical handler page state.
1335 * @param pCur The physical handler in question.
1336 */
1337DECLINLINE(unsigned) pgmHandlerPhysicalCalcState(PPGMPHYSHANDLER pCur)
1338{
1339 switch (pCur->enmType)
1340 {
1341 case PGMPHYSHANDLERTYPE_PHYSICAL_WRITE:
1342 return PGM_PAGE_HNDL_PHYS_STATE_WRITE;
1343
1344 case PGMPHYSHANDLERTYPE_MMIO:
1345 case PGMPHYSHANDLERTYPE_PHYSICAL_ALL:
1346 return PGM_PAGE_HNDL_PHYS_STATE_ALL;
1347
1348 default:
1349 AssertFatalMsgFailed(("Invalid type %d\n", pCur->enmType));
1350 }
1351}
1352
1353
1354/**
1355 * Gets the page state for a virtual handler.
1356 *
1357 * @returns The virtual handler page state.
1358 * @param pCur The virtual handler in question.
1359 * @remarks This should never be used on a hypervisor access handler.
1360 */
1361DECLINLINE(unsigned) pgmHandlerVirtualCalcState(PPGMVIRTHANDLER pCur)
1362{
1363 switch (pCur->enmType)
1364 {
1365 case PGMVIRTHANDLERTYPE_WRITE:
1366 return PGM_PAGE_HNDL_VIRT_STATE_WRITE;
1367 case PGMVIRTHANDLERTYPE_ALL:
1368 return PGM_PAGE_HNDL_VIRT_STATE_ALL;
1369 default:
1370 AssertFatalMsgFailed(("Invalid type %d\n", pCur->enmType));
1371 }
1372}
1373
1374
1375/**
1376 * Clears one physical page of a virtual handler
1377 *
1378 * @param pPGM Pointer to the PGM instance.
1379 * @param pCur Virtual handler structure
1380 * @param iPage Physical page index
1381 *
1382 * @remark Only used when PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL is being set, so no
1383 * need to care about other handlers in the same page.
1384 */
1385DECLINLINE(void) pgmHandlerVirtualClearPage(PPGM pPGM, PPGMVIRTHANDLER pCur, unsigned iPage)
1386{
1387 const PPGMPHYS2VIRTHANDLER pPhys2Virt = &pCur->aPhysToVirt[iPage];
1388
1389 /*
1390 * Remove the node from the tree (it's supposed to be in the tree if we get here!).
1391 */
1392#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
1393 AssertReleaseMsg(pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_IN_TREE,
1394 ("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
1395 pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias));
1396#endif
1397 if (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_IS_HEAD)
1398 {
1399 /* We're the head of the alias chain. */
1400 PPGMPHYS2VIRTHANDLER pRemove = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysRemove(&pPGM->CTX_SUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key); NOREF(pRemove);
1401#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
1402 AssertReleaseMsg(pRemove != NULL,
1403 ("pPhys2Virt=%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 AssertReleaseMsg(pRemove == pPhys2Virt,
1406 ("wanted: pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n"
1407 " got: pRemove=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
1408 pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias,
1409 pRemove, pRemove->Core.Key, pRemove->Core.KeyLast, pRemove->offVirtHandler, pRemove->offNextAlias));
1410#endif
1411 if (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK)
1412 {
1413 /* Insert the next list in the alias chain into the tree. */
1414 PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
1415#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
1416 AssertReleaseMsg(pNext->offNextAlias & PGMPHYS2VIRTHANDLER_IN_TREE,
1417 ("pNext=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
1418 pNext, pNext->Core.Key, pNext->Core.KeyLast, pNext->offVirtHandler, pNext->offNextAlias));
1419#endif
1420 pNext->offNextAlias |= PGMPHYS2VIRTHANDLER_IS_HEAD;
1421 bool fRc = RTAvlroGCPhysInsert(&pPGM->CTX_SUFF(pTrees)->PhysToVirtHandlers, &pNext->Core);
1422 AssertRelease(fRc);
1423 }
1424 }
1425 else
1426 {
1427 /* Locate the previous node in the alias chain. */
1428 PPGMPHYS2VIRTHANDLER pPrev = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGet(&pPGM->CTX_SUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key);
1429#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
1430 AssertReleaseMsg(pPrev != pPhys2Virt,
1431 ("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} pPrev=%p\n",
1432 pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias, pPrev));
1433#endif
1434 for (;;)
1435 {
1436 PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPrev + (pPrev->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
1437 if (pNext == pPhys2Virt)
1438 {
1439 /* unlink. */
1440 LogFlow(("pgmHandlerVirtualClearPage: removed %p:{.offNextAlias=%#RX32} from alias chain. prev %p:{.offNextAlias=%#RX32} [%RGp-%RGp]\n",
1441 pPhys2Virt, pPhys2Virt->offNextAlias, pPrev, pPrev->offNextAlias, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast));
1442 if (!(pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK))
1443 pPrev->offNextAlias &= ~PGMPHYS2VIRTHANDLER_OFF_MASK;
1444 else
1445 {
1446 PPGMPHYS2VIRTHANDLER pNewNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
1447 pPrev->offNextAlias = ((intptr_t)pNewNext - (intptr_t)pPrev)
1448 | (pPrev->offNextAlias & ~PGMPHYS2VIRTHANDLER_OFF_MASK);
1449 }
1450 break;
1451 }
1452
1453 /* next */
1454 if (pNext == pPrev)
1455 {
1456#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
1457 AssertReleaseMsg(pNext != pPrev,
1458 ("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} pPrev=%p\n",
1459 pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias, pPrev));
1460#endif
1461 break;
1462 }
1463 pPrev = pNext;
1464 }
1465 }
1466 Log2(("PHYS2VIRT: Removing %RGp-%RGp %#RX32 %s\n",
1467 pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offNextAlias, R3STRING(pCur->pszDesc)));
1468 pPhys2Virt->offNextAlias = 0;
1469 pPhys2Virt->Core.KeyLast = NIL_RTGCPHYS; /* require reinsert */
1470
1471 /*
1472 * Clear the ram flags for this page.
1473 */
1474 PPGMPAGE pPage = pgmPhysGetPage(pPGM, pPhys2Virt->Core.Key);
1475 AssertReturnVoid(pPage);
1476 PGM_PAGE_SET_HNDL_VIRT_STATE(pPage, PGM_PAGE_HNDL_VIRT_STATE_NONE);
1477}
1478
1479
1480/**
1481 * Internal worker for finding a 'in-use' shadow page give by it's physical address.
1482 *
1483 * @returns Pointer to the shadow page structure.
1484 * @param pPool The pool.
1485 * @param idx The pool page index.
1486 */
1487DECLINLINE(PPGMPOOLPAGE) pgmPoolGetPageByIdx(PPGMPOOL pPool, unsigned idx)
1488{
1489 AssertFatalMsg(idx >= PGMPOOL_IDX_FIRST && idx < pPool->cCurPages, ("idx=%d\n", idx));
1490 return &pPool->aPages[idx];
1491}
1492
1493
1494/**
1495 * Clear references to guest physical memory.
1496 *
1497 * @param pPool The pool.
1498 * @param pPoolPage The pool page.
1499 * @param pPhysPage The physical guest page tracking structure.
1500 */
1501DECLINLINE(void) pgmTrackDerefGCPhys(PPGMPOOL pPool, PPGMPOOLPAGE pPoolPage, PPGMPAGE pPhysPage)
1502{
1503 /*
1504 * Just deal with the simple case here.
1505 */
1506# ifdef LOG_ENABLED
1507 const unsigned uOrg = PGM_PAGE_GET_TRACKING(pPhysPage);
1508# endif
1509 const unsigned cRefs = PGM_PAGE_GET_TD_CREFS(pPhysPage);
1510 if (cRefs == 1)
1511 {
1512 Assert(pPoolPage->idx == PGM_PAGE_GET_TD_IDX(pPhysPage));
1513 /* Invalidate the tracking data. */
1514 PGM_PAGE_SET_TRACKING(pPhysPage, 0);
1515 }
1516 else
1517 pgmPoolTrackPhysExtDerefGCPhys(pPool, pPoolPage, pPhysPage);
1518 Log2(("pgmTrackDerefGCPhys: %x -> %x pPhysPage=%R[pgmpage]\n", uOrg, PGM_PAGE_GET_TRACKING(pPhysPage), pPhysPage ));
1519}
1520
1521
1522/**
1523 * Moves the page to the head of the age list.
1524 *
1525 * This is done when the cached page is used in one way or another.
1526 *
1527 * @param pPool The pool.
1528 * @param pPage The cached page.
1529 */
1530DECLINLINE(void) pgmPoolCacheUsed(PPGMPOOL pPool, PPGMPOOLPAGE pPage)
1531{
1532 PVM pVM = pPool->CTX_SUFF(pVM);
1533 pgmLock(pVM);
1534
1535 /*
1536 * Move to the head of the age list.
1537 */
1538 if (pPage->iAgePrev != NIL_PGMPOOL_IDX)
1539 {
1540 /* unlink */
1541 pPool->aPages[pPage->iAgePrev].iAgeNext = pPage->iAgeNext;
1542 if (pPage->iAgeNext != NIL_PGMPOOL_IDX)
1543 pPool->aPages[pPage->iAgeNext].iAgePrev = pPage->iAgePrev;
1544 else
1545 pPool->iAgeTail = pPage->iAgePrev;
1546
1547 /* insert at head */
1548 pPage->iAgePrev = NIL_PGMPOOL_IDX;
1549 pPage->iAgeNext = pPool->iAgeHead;
1550 Assert(pPage->iAgeNext != NIL_PGMPOOL_IDX); /* we would've already been head then */
1551 pPool->iAgeHead = pPage->idx;
1552 pPool->aPages[pPage->iAgeNext].iAgePrev = pPage->idx;
1553 }
1554 pgmUnlock(pVM);
1555}
1556
1557/**
1558 * Locks a page to prevent flushing (important for cr3 root pages or shadow pae pd pages).
1559 *
1560 * @param pVM VM Handle.
1561 * @param pPage PGM pool page
1562 */
1563DECLINLINE(void) pgmPoolLockPage(PPGMPOOL pPool, PPGMPOOLPAGE pPage)
1564{
1565 Assert(PGMIsLockOwner(pPool->CTX_SUFF(pVM)));
1566 ASMAtomicIncU32(&pPage->cLocked);
1567}
1568
1569
1570/**
1571 * Unlocks a page to allow flushing again
1572 *
1573 * @param pVM VM Handle.
1574 * @param pPage PGM pool page
1575 */
1576DECLINLINE(void) pgmPoolUnlockPage(PPGMPOOL pPool, PPGMPOOLPAGE pPage)
1577{
1578 Assert(PGMIsLockOwner(pPool->CTX_SUFF(pVM)));
1579 Assert(pPage->cLocked);
1580 ASMAtomicDecU32(&pPage->cLocked);
1581}
1582
1583
1584/**
1585 * Checks if the page is locked (e.g. the active CR3 or one of the four PDs of a PAE PDPT)
1586 *
1587 * @returns VBox status code.
1588 * @param pPage PGM pool page
1589 */
1590DECLINLINE(bool) pgmPoolIsPageLocked(PPGM pPGM, PPGMPOOLPAGE pPage)
1591{
1592 if (pPage->cLocked)
1593 {
1594 LogFlow(("pgmPoolIsPageLocked found root page %d\n", pPage->enmKind));
1595 if (pPage->cModifications)
1596 pPage->cModifications = 1; /* reset counter (can't use 0, or else it will be reinserted in the modified list) */
1597 return true;
1598 }
1599 return false;
1600}
1601
1602
1603/**
1604 * Tells if mappings are to be put into the shadow page table or not.
1605 *
1606 * @returns boolean result
1607 * @param pVM VM handle.
1608 */
1609DECL_FORCE_INLINE(bool) pgmMapAreMappingsEnabled(PPGM pPGM)
1610{
1611#ifdef PGM_WITHOUT_MAPPINGS
1612 /* There are no mappings in VT-x and AMD-V mode. */
1613 Assert(pPGM->fMappingsDisabled);
1614 return false;
1615#else
1616 return !pPGM->fMappingsDisabled;
1617#endif
1618}
1619
1620
1621/**
1622 * Checks if the mappings are floating and enabled.
1623 *
1624 * @returns true / false.
1625 * @param pVM The VM handle.
1626 */
1627DECL_FORCE_INLINE(bool) pgmMapAreMappingsFloating(PPGM pPGM)
1628{
1629#ifdef PGM_WITHOUT_MAPPINGS
1630 /* There are no mappings in VT-x and AMD-V mode. */
1631 Assert(pPGM->fMappingsDisabled);
1632 return false;
1633#else
1634 return !pPGM->fMappingsDisabled
1635 && !pPGM->fMappingsFixed;
1636#endif
1637}
1638
1639/** @} */
1640
1641#endif
1642
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