VirtualBox

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

Last change on this file since 14584 was 14157, checked in by vboxsync, 16 years ago

mac build fixes.

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