VirtualBox

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

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

#1865: MM - docs and 4 new ring-3 heap APIs for string formatting.

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