VirtualBox

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

Last change on this file since 76553 was 76553, checked in by vboxsync, 5 years ago

scm --update-copyright-year

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

© 2023 Oracle
ContactPrivacy policyTerms of Use