VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/MMPagePool.cpp@ 61566

Last change on this file since 61566 was 58170, checked in by vboxsync, 9 years ago

doxygen: fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 19.0 KB
Line 
1/* $Id: MMPagePool.cpp 58170 2015-10-12 09:27:14Z vboxsync $ */
2/** @file
3 * MM - Memory Manager - Page Pool.
4 */
5
6/*
7 * Copyright (C) 2006-2015 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_MM_POOL
23#include <VBox/vmm/mm.h>
24#include <VBox/vmm/pgm.h>
25#include <VBox/vmm/stam.h>
26#include "MMInternal.h"
27#include <VBox/vmm/vm.h>
28#include <VBox/param.h>
29#include <VBox/err.h>
30#include <VBox/log.h>
31#include "internal/pgm.h"
32#include <iprt/alloc.h>
33#include <iprt/assert.h>
34#define USE_INLINE_ASM_BIT_OPS
35#ifdef USE_INLINE_ASM_BIT_OPS
36# include <iprt/asm.h>
37#endif
38#include <iprt/string.h>
39
40
41
42/*********************************************************************************************************************************
43* Internal Functions *
44*********************************************************************************************************************************/
45#ifdef IN_RING3
46static void * mmR3PagePoolAlloc(PMMPAGEPOOL pPool);
47static void mmR3PagePoolFree(PMMPAGEPOOL pPool, void *pv);
48#endif
49
50
51/**
52 * Initializes the page pool
53 *
54 * @return VBox status code.
55 * @param pVM The cross context VM structure.
56 * @thread The Emulation Thread.
57 */
58int mmR3PagePoolInit(PVM pVM)
59{
60 AssertMsg(!pVM->mm.s.pPagePoolR3, ("Already initialized!\n"));
61
62 /*
63 * Allocate the pool structures.
64 */
65 /** @todo @bugref{1865},@bugref{3202}: mapping the page pool page into ring-0.
66 * Need to change the ways we allocate it... */
67 AssertReleaseReturn(sizeof(*pVM->mm.s.pPagePoolR3) + sizeof(*pVM->mm.s.pPagePoolLowR3) < PAGE_SIZE, VERR_INTERNAL_ERROR);
68 int rc = SUPR3PageAllocEx(1, 0 /*fFlags*/, (void **)&pVM->mm.s.pPagePoolR3, NULL /*pR0Ptr*/, NULL /*paPages*/);
69 if (RT_FAILURE(rc))
70 return rc;
71 memset(pVM->mm.s.pPagePoolR3, 0, PAGE_SIZE);
72 pVM->mm.s.pPagePoolR3->pVM = pVM;
73 STAM_REG(pVM, &pVM->mm.s.pPagePoolR3->cPages, STAMTYPE_U32, "/MM/Page/Def/cPages", STAMUNIT_PAGES, "Number of pages in the default pool.");
74 STAM_REG(pVM, &pVM->mm.s.pPagePoolR3->cFreePages, STAMTYPE_U32, "/MM/Page/Def/cFreePages", STAMUNIT_PAGES, "Number of free pages in the default pool.");
75 STAM_REG(pVM, &pVM->mm.s.pPagePoolR3->cSubPools, STAMTYPE_U32, "/MM/Page/Def/cSubPools", STAMUNIT_COUNT, "Number of sub pools in the default pool.");
76 STAM_REG(pVM, &pVM->mm.s.pPagePoolR3->cAllocCalls, STAMTYPE_COUNTER, "/MM/Page/Def/cAllocCalls", STAMUNIT_CALLS, "Number of MMR3PageAlloc() calls for the default pool.");
77 STAM_REG(pVM, &pVM->mm.s.pPagePoolR3->cFreeCalls, STAMTYPE_COUNTER, "/MM/Page/Def/cFreeCalls", STAMUNIT_CALLS, "Number of MMR3PageFree()+MMR3PageFreeByPhys() calls for the default pool.");
78 STAM_REG(pVM, &pVM->mm.s.pPagePoolR3->cToPhysCalls, STAMTYPE_COUNTER, "/MM/Page/Def/cToPhysCalls", STAMUNIT_CALLS, "Number of MMR3Page2Phys() calls for this pool.");
79 STAM_REG(pVM, &pVM->mm.s.pPagePoolR3->cToVirtCalls, STAMTYPE_COUNTER, "/MM/Page/Def/cToVirtCalls", STAMUNIT_CALLS, "Number of MMR3PagePhys2Page()+MMR3PageFreeByPhys() calls for the default pool.");
80 STAM_REG(pVM, &pVM->mm.s.pPagePoolR3->cErrors, STAMTYPE_COUNTER, "/MM/Page/Def/cErrors", STAMUNIT_ERRORS,"Number of errors for the default pool.");
81
82 pVM->mm.s.pPagePoolLowR3 = pVM->mm.s.pPagePoolR3 + 1;
83 pVM->mm.s.pPagePoolLowR3->pVM = pVM;
84 pVM->mm.s.pPagePoolLowR3->fLow = true;
85 STAM_REG(pVM, &pVM->mm.s.pPagePoolLowR3->cPages, STAMTYPE_U32, "/MM/Page/Low/cPages", STAMUNIT_PAGES, "Number of pages in the <4GB pool.");
86 STAM_REG(pVM, &pVM->mm.s.pPagePoolLowR3->cFreePages, STAMTYPE_U32, "/MM/Page/Low/cFreePages", STAMUNIT_PAGES, "Number of free pages in the <4GB pool.");
87 STAM_REG(pVM, &pVM->mm.s.pPagePoolLowR3->cSubPools, STAMTYPE_U32, "/MM/Page/Low/cSubPools", STAMUNIT_COUNT, "Number of sub pools in the <4GB pool.");
88 STAM_REG(pVM, &pVM->mm.s.pPagePoolLowR3->cAllocCalls, STAMTYPE_COUNTER, "/MM/Page/Low/cAllocCalls", STAMUNIT_CALLS, "Number of MMR3PageAllocLow() calls for the <4GB pool.");
89 STAM_REG(pVM, &pVM->mm.s.pPagePoolLowR3->cFreeCalls, STAMTYPE_COUNTER, "/MM/Page/Low/cFreeCalls", STAMUNIT_CALLS, "Number of MMR3PageFreeLow()+MMR3PageFreeByPhys() calls for the <4GB pool.");
90 STAM_REG(pVM, &pVM->mm.s.pPagePoolLowR3->cToPhysCalls,STAMTYPE_COUNTER, "/MM/Page/Low/cToPhysCalls", STAMUNIT_CALLS, "Number of MMR3Page2Phys() calls for the <4GB pool.");
91 STAM_REG(pVM, &pVM->mm.s.pPagePoolLowR3->cToVirtCalls,STAMTYPE_COUNTER, "/MM/Page/Low/cToVirtCalls", STAMUNIT_CALLS, "Number of MMR3PagePhys2Page()+MMR3PageFreeByPhys() calls for the <4GB pool.");
92 STAM_REG(pVM, &pVM->mm.s.pPagePoolLowR3->cErrors, STAMTYPE_COUNTER, "/MM/Page/Low/cErrors", STAMUNIT_ERRORS,"Number of errors for the <4GB pool.");
93
94#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
95 pVM->mm.s.pPagePoolR0 = (uintptr_t)pVM->mm.s.pPagePoolR3;
96 pVM->mm.s.pPagePoolLowR0 = (uintptr_t)pVM->mm.s.pPagePoolLowR3;
97#endif
98
99 /** @todo init a mutex? */
100 return VINF_SUCCESS;
101}
102
103
104/**
105 * Release all locks and free the allocated memory.
106 *
107 * @param pVM The cross context VM structure.
108 * @thread The Emulation Thread.
109 */
110void mmR3PagePoolTerm(PVM pVM)
111{
112 if (pVM->mm.s.pPagePoolR3)
113 {
114 /*
115 * Unlock all memory held by subpools and free the memory.
116 * (The MM Heap will free the memory used for internal stuff.)
117 */
118 Assert(!pVM->mm.s.pPagePoolR3->fLow);
119 PMMPAGESUBPOOL pSubPool = pVM->mm.s.pPagePoolR3->pHead;
120 while (pSubPool)
121 {
122 int rc = SUPR3PageFreeEx(pSubPool->pvPages, pSubPool->cPages);
123 AssertMsgRC(rc, ("SUPR3PageFreeEx(%p) failed with rc=%Rrc\n", pSubPool->pvPages, rc));
124 pSubPool->pvPages = NULL;
125
126 /* next */
127 pSubPool = pSubPool->pNext;
128 }
129 pVM->mm.s.pPagePoolR3 = NULL;
130#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
131 pVM->mm.s.pPagePoolR0 = NIL_RTR0PTR;
132#endif
133 }
134
135 if (pVM->mm.s.pPagePoolLowR3)
136 {
137 /*
138 * Free the memory.
139 */
140 Assert(pVM->mm.s.pPagePoolLowR3->fLow);
141 PMMPAGESUBPOOL pSubPool = pVM->mm.s.pPagePoolLowR3->pHead;
142 while (pSubPool)
143 {
144 int rc = SUPR3LowFree(pSubPool->pvPages, pSubPool->cPages);
145 AssertMsgRC(rc, ("SUPR3LowFree(%p) failed with rc=%d\n", pSubPool->pvPages, rc));
146 pSubPool->pvPages = NULL;
147
148 /* next */
149 pSubPool = pSubPool->pNext;
150 }
151 pVM->mm.s.pPagePoolLowR3 = NULL;
152#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
153 pVM->mm.s.pPagePoolLowR0 = NIL_RTR0PTR;
154#endif
155 }
156}
157
158
159/**
160 * Allocates a page from the page pool.
161 *
162 * @returns Pointer to allocated page(s).
163 * @returns NULL on failure.
164 * @param pPool Pointer to the page pool.
165 * @thread The Emulation Thread.
166 */
167DECLINLINE(void *) mmR3PagePoolAlloc(PMMPAGEPOOL pPool)
168{
169 VM_ASSERT_EMT(pPool->pVM);
170 STAM_COUNTER_INC(&pPool->cAllocCalls);
171
172 /*
173 * Walk free list.
174 */
175 if (pPool->pHeadFree)
176 {
177 PMMPAGESUBPOOL pSub = pPool->pHeadFree;
178 /* decrement free count and unlink if no more free entries. */
179 if (!--pSub->cPagesFree)
180 pPool->pHeadFree = pSub->pNextFree;
181#ifdef VBOX_WITH_STATISTICS
182 pPool->cFreePages--;
183#endif
184
185 /* find free spot in bitmap. */
186#ifdef USE_INLINE_ASM_BIT_OPS
187 const int iPage = ASMBitFirstClear(pSub->auBitmap, pSub->cPages);
188 if (iPage >= 0)
189 {
190 Assert(!ASMBitTest(pSub->auBitmap, iPage));
191 ASMBitSet(pSub->auBitmap, iPage);
192 return (uint8_t *)pSub->pvPages + PAGE_SIZE * iPage;
193 }
194#else
195 unsigned *pu = &pSub->auBitmap[0];
196 unsigned *puEnd = &pSub->auBitmap[pSub->cPages / (sizeof(pSub->auBitmap) * 8)];
197 while (pu < puEnd)
198 {
199 unsigned u;
200 if ((u = *pu) != ~0U)
201 {
202 unsigned iBit = 0;
203 unsigned uMask = 1;
204 while (iBit < sizeof(pSub->auBitmap[0]) * 8)
205 {
206 if (!(u & uMask))
207 {
208 *pu |= uMask;
209 return (uint8_t *)pSub->pvPages
210 + PAGE_SIZE * (iBit + ((uint8_t *)pu - (uint8_t *)&pSub->auBitmap[0]) * 8);
211 }
212 iBit++;
213 uMask <<= 1;
214 }
215 STAM_COUNTER_INC(&pPool->cErrors);
216 AssertMsgFailed(("how odd, expected to find a free bit in %#x, but didn't\n", u));
217 }
218 /* next */
219 pu++;
220 }
221#endif
222 STAM_COUNTER_INC(&pPool->cErrors);
223#ifdef VBOX_WITH_STATISTICS
224 pPool->cFreePages++;
225#endif
226 AssertMsgFailed(("how strange, expected to find a free bit in %p, but didn't (%d pages supposed to be free!)\n", pSub, pSub->cPagesFree + 1));
227 }
228
229 /*
230 * Allocate new subpool.
231 */
232 unsigned cPages = !pPool->fLow ? 128 : 32;
233 PMMPAGESUBPOOL pSub;
234 int rc = MMHyperAlloc(pPool->pVM,
235 RT_OFFSETOF(MMPAGESUBPOOL, auBitmap[cPages / (sizeof(pSub->auBitmap[0]) * 8)])
236 + (sizeof(SUPPAGE) + sizeof(MMPPLOOKUPHCPHYS)) * cPages
237 + sizeof(MMPPLOOKUPHCPTR),
238 0,
239 MM_TAG_MM_PAGE,
240 (void **)&pSub);
241 if (RT_FAILURE(rc))
242 return NULL;
243
244 PSUPPAGE paPhysPages = (PSUPPAGE)&pSub->auBitmap[cPages / (sizeof(pSub->auBitmap[0]) * 8)];
245 Assert((uintptr_t)paPhysPages >= (uintptr_t)&pSub->auBitmap[1]);
246 if (!pPool->fLow)
247 {
248 rc = SUPR3PageAllocEx(cPages,
249 0 /* fFlags */,
250 &pSub->pvPages,
251 NULL,
252 paPhysPages);
253 if (RT_FAILURE(rc))
254 rc = VMSetError(pPool->pVM, rc, RT_SRC_POS,
255 N_("Failed to lock host %zd bytes of memory (out of memory)"), (size_t)cPages << PAGE_SHIFT);
256 }
257 else
258 rc = SUPR3LowAlloc(cPages, &pSub->pvPages, NULL, paPhysPages);
259 if (RT_SUCCESS(rc))
260 {
261 /*
262 * Setup the sub structure and allocate the requested page.
263 */
264 pSub->cPages = cPages;
265 pSub->cPagesFree= cPages - 1;
266 pSub->paPhysPages = paPhysPages;
267 memset(pSub->auBitmap, 0, cPages / 8);
268 /* allocate first page. */
269 pSub->auBitmap[0] |= 1;
270 /* link into free chain. */
271 pSub->pNextFree = pPool->pHeadFree;
272 pPool->pHeadFree= pSub;
273 /* link into main chain. */
274 pSub->pNext = pPool->pHead;
275 pPool->pHead = pSub;
276 /* update pool statistics. */
277 pPool->cSubPools++;
278 pPool->cPages += cPages;
279#ifdef VBOX_WITH_STATISTICS
280 pPool->cFreePages += cPages - 1;
281#endif
282
283 /*
284 * Initialize the physical pages with backpointer to subpool.
285 */
286 unsigned i = cPages;
287 while (i-- > 0)
288 {
289 AssertMsg(paPhysPages[i].Phys && !(paPhysPages[i].Phys & PAGE_OFFSET_MASK),
290 ("i=%d Phys=%d\n", i, paPhysPages[i].Phys));
291 paPhysPages[i].uReserved = (RTHCUINTPTR)pSub;
292 }
293
294 /*
295 * Initialize the physical lookup record with backpointers to the physical pages.
296 */
297 PMMPPLOOKUPHCPHYS paLookupPhys = (PMMPPLOOKUPHCPHYS)&paPhysPages[cPages];
298 i = cPages;
299 while (i-- > 0)
300 {
301 paLookupPhys[i].pPhysPage = &paPhysPages[i];
302 paLookupPhys[i].Core.Key = paPhysPages[i].Phys;
303 RTAvlHCPhysInsert(&pPool->pLookupPhys, &paLookupPhys[i].Core);
304 }
305
306 /*
307 * And the one record for virtual memory lookup.
308 */
309 PMMPPLOOKUPHCPTR pLookupVirt = (PMMPPLOOKUPHCPTR)&paLookupPhys[cPages];
310 pLookupVirt->pSubPool = pSub;
311 pLookupVirt->Core.Key = pSub->pvPages;
312 RTAvlPVInsert(&pPool->pLookupVirt, &pLookupVirt->Core);
313
314 /* return allocated page (first). */
315 return pSub->pvPages;
316 }
317
318 MMHyperFree(pPool->pVM, pSub);
319 STAM_COUNTER_INC(&pPool->cErrors);
320 if (pPool->fLow)
321 VMSetError(pPool->pVM, rc, RT_SRC_POS,
322 N_("Failed to expand page pool for memory below 4GB. Current size: %d pages"),
323 pPool->cPages);
324 AssertMsgFailed(("Failed to expand pool%s. rc=%Rrc poolsize=%d\n",
325 pPool->fLow ? " (<4GB)" : "", rc, pPool->cPages));
326 return NULL;
327}
328
329
330/**
331 * Frees a page from the page pool.
332 *
333 * @param pPool Pointer to the page pool.
334 * @param pv Pointer to the page to free.
335 * I.e. pointer returned by mmR3PagePoolAlloc().
336 * @thread The Emulation Thread.
337 */
338DECLINLINE(void) mmR3PagePoolFree(PMMPAGEPOOL pPool, void *pv)
339{
340 VM_ASSERT_EMT(pPool->pVM);
341 STAM_COUNTER_INC(&pPool->cFreeCalls);
342
343 /*
344 * Lookup the virtual address.
345 */
346 PMMPPLOOKUPHCPTR pLookup = (PMMPPLOOKUPHCPTR)RTAvlPVGetBestFit(&pPool->pLookupVirt, pv, false);
347 if ( !pLookup
348 || (uint8_t *)pv >= (uint8_t *)pLookup->pSubPool->pvPages + (pLookup->pSubPool->cPages << PAGE_SHIFT)
349 )
350 {
351 STAM_COUNTER_INC(&pPool->cErrors);
352 AssertMsgFailed(("invalid pointer %p\n", pv));
353 return;
354 }
355
356 /*
357 * Free the page.
358 */
359 PMMPAGESUBPOOL pSubPool = pLookup->pSubPool;
360 /* clear bitmap bit */
361 const unsigned iPage = ((uint8_t *)pv - (uint8_t *)pSubPool->pvPages) >> PAGE_SHIFT;
362#ifdef USE_INLINE_ASM_BIT_OPS
363 Assert(ASMBitTest(pSubPool->auBitmap, iPage));
364 ASMBitClear(pSubPool->auBitmap, iPage);
365#else
366 unsigned iBit = iPage % (sizeof(pSubPool->auBitmap[0]) * 8);
367 unsigned iIndex = iPage / (sizeof(pSubPool->auBitmap[0]) * 8);
368 pSubPool->auBitmap[iIndex] &= ~(1 << iBit);
369#endif
370 /* update stats. */
371 pSubPool->cPagesFree++;
372#ifdef VBOX_WITH_STATISTICS
373 pPool->cFreePages++;
374#endif
375 if (pSubPool->cPagesFree == 1)
376 {
377 pSubPool->pNextFree = pPool->pHeadFree;
378 pPool->pHeadFree = pSubPool;
379 }
380}
381
382
383/**
384 * Allocates a page from the page pool.
385 *
386 * This function may returns pages which has physical addresses any
387 * where. If you require a page to be within the first 4GB of physical
388 * memory, use MMR3PageAllocLow().
389 *
390 * @returns Pointer to the allocated page page.
391 * @returns NULL on failure.
392 * @param pVM The cross context VM structure.
393 * @thread The Emulation Thread.
394 */
395VMMR3DECL(void *) MMR3PageAlloc(PVM pVM)
396{
397 /* Note: unprotected by locks; currently fine as it's used during init or under the PGM lock */
398 return mmR3PagePoolAlloc(pVM->mm.s.pPagePoolR3);
399}
400
401
402/**
403 * Allocates a page from the page pool and return its physical address.
404 *
405 * This function may returns pages which has physical addresses any
406 * where. If you require a page to be within the first 4GB of physical
407 * memory, use MMR3PageAllocLow().
408 *
409 * @returns Pointer to the allocated page page.
410 * @returns NIL_RTHCPHYS on failure.
411 * @param pVM The cross context VM structure.
412 * @thread The Emulation Thread.
413 */
414VMMR3DECL(RTHCPHYS) MMR3PageAllocPhys(PVM pVM)
415{
416 /* Note: unprotected by locks; currently fine as it's used during init or under the PGM lock */
417 /** @todo optimize this, it's the most common case now. */
418 void *pv = mmR3PagePoolAlloc(pVM->mm.s.pPagePoolR3);
419 if (pv)
420 return mmPagePoolPtr2Phys(pVM->mm.s.pPagePoolR3, pv);
421 return NIL_RTHCPHYS;
422}
423
424
425/**
426 * Frees a page allocated from the page pool by MMR3PageAlloc() or
427 * MMR3PageAllocPhys().
428 *
429 * @param pVM The cross context VM structure.
430 * @param pvPage Pointer to the page.
431 * @thread The Emulation Thread.
432 */
433VMMR3DECL(void) MMR3PageFree(PVM pVM, void *pvPage)
434{
435 mmR3PagePoolFree(pVM->mm.s.pPagePoolR3, pvPage);
436}
437
438
439/**
440 * Allocates a page from the low page pool.
441 *
442 * @returns Pointer to the allocated page.
443 * @returns NULL on failure.
444 * @param pVM The cross context VM structure.
445 * @thread The Emulation Thread.
446 */
447VMMR3DECL(void *) MMR3PageAllocLow(PVM pVM)
448{
449 return mmR3PagePoolAlloc(pVM->mm.s.pPagePoolLowR3);
450}
451
452
453/**
454 * Frees a page allocated from the page pool by MMR3PageAllocLow().
455 *
456 * @param pVM The cross context VM structure.
457 * @param pvPage Pointer to the page.
458 * @thread The Emulation Thread.
459 */
460VMMR3DECL(void) MMR3PageFreeLow(PVM pVM, void *pvPage)
461{
462 mmR3PagePoolFree(pVM->mm.s.pPagePoolLowR3, pvPage);
463}
464
465
466/**
467 * Free a page allocated from the page pool by physical address.
468 * This works for pages allocated by MMR3PageAlloc(), MMR3PageAllocPhys()
469 * and MMR3PageAllocLow().
470 *
471 * @param pVM The cross context VM structure.
472 * @param HCPhysPage The physical address of the page to be freed.
473 * @thread The Emulation Thread.
474 */
475VMMR3DECL(void) MMR3PageFreeByPhys(PVM pVM, RTHCPHYS HCPhysPage)
476{
477 void *pvPage = mmPagePoolPhys2Ptr(pVM->mm.s.pPagePoolR3, HCPhysPage);
478 if (!pvPage)
479 pvPage = mmPagePoolPhys2Ptr(pVM->mm.s.pPagePoolLowR3, HCPhysPage);
480 if (pvPage)
481 mmR3PagePoolFree(pVM->mm.s.pPagePoolR3, pvPage);
482 else
483 AssertMsgFailed(("Invalid address HCPhysPT=%#x\n", HCPhysPage));
484}
485
486
487/**
488 * Gets the HC pointer to the dummy page.
489 *
490 * The dummy page is used as a place holder to prevent potential bugs
491 * from doing really bad things to the system.
492 *
493 * @returns Pointer to the dummy page.
494 * @param pVM The cross context VM structure.
495 * @thread The Emulation Thread.
496 */
497VMMR3DECL(void *) MMR3PageDummyHCPtr(PVM pVM)
498{
499 VM_ASSERT_EMT(pVM);
500 if (!pVM->mm.s.pvDummyPage)
501 {
502 pVM->mm.s.pvDummyPage = mmR3PagePoolAlloc(pVM->mm.s.pPagePoolR3);
503 AssertRelease(pVM->mm.s.pvDummyPage);
504 pVM->mm.s.HCPhysDummyPage = mmPagePoolPtr2Phys(pVM->mm.s.pPagePoolR3, pVM->mm.s.pvDummyPage);
505 AssertRelease(!(pVM->mm.s.HCPhysDummyPage & ~X86_PTE_PAE_PG_MASK));
506 }
507 return pVM->mm.s.pvDummyPage;
508}
509
510
511/**
512 * Gets the HC Phys to the dummy page.
513 *
514 * The dummy page is used as a place holder to prevent potential bugs
515 * from doing really bad things to the system.
516 *
517 * @returns Pointer to the dummy page.
518 * @param pVM The cross context VM structure.
519 * @thread The Emulation Thread.
520 */
521VMMR3DECL(RTHCPHYS) MMR3PageDummyHCPhys(PVM pVM)
522{
523 VM_ASSERT_EMT(pVM);
524 if (!pVM->mm.s.pvDummyPage)
525 MMR3PageDummyHCPtr(pVM);
526 return pVM->mm.s.HCPhysDummyPage;
527}
528
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