MMPagePool.cpp revision 37eb780874007e6c73f493edcfd7a1e498a6a2ef
/* $Id$ */
/** @file
* MM - Memory Monitor(/Manager) - Page Pool.
*/
/*
* Copyright (C) 2006 InnoTek Systemberatung GmbH
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License as published by the Free Software Foundation,
* in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
* distribution. VirtualBox OSE is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY of any kind.
*
* If you received this file as part of a commercial VirtualBox
* distribution, then only the terms of your commercial VirtualBox
* license agreement apply instead of the previous paragraph.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#define LOG_GROUP LOG_GROUP_MM_POOL
#include "MMInternal.h"
#define USE_INLINE_ASM_BIT_OPS
#ifdef USE_INLINE_ASM_BIT_OPS
#endif
/*******************************************************************************
* Internal Functions *
*******************************************************************************/
#ifdef IN_RING3
#endif
/**
* Initializes the page pool
*
* @return VBox status.
* @param pVM VM handle.
* @thread The Emulation Thread.
*/
{
/*
* Allocate the pool structures.
*/
return VERR_NO_MEMORY;
STAM_REG(pVM, &pVM->mm.s.pPagePool->cPages, STAMTYPE_U32, "/MM/Page/Def/cPages", STAMUNIT_PAGES, "Number of pages in the default pool.");
STAM_REG(pVM, &pVM->mm.s.pPagePool->cFreePages, STAMTYPE_U32, "/MM/Page/Def/cFreePages", STAMUNIT_PAGES, "Number of free pages in the default pool.");
STAM_REG(pVM, &pVM->mm.s.pPagePool->cSubPools, STAMTYPE_U32, "/MM/Page/Def/cSubPools", STAMUNIT_COUNT, "Number of sub pools in the default pool.");
STAM_REG(pVM, &pVM->mm.s.pPagePool->cAllocCalls, STAMTYPE_COUNTER, "/MM/Page/Def/cAllocCalls", STAMUNIT_CALLS, "Number of MMR3PageAlloc() calls for the default pool.");
STAM_REG(pVM, &pVM->mm.s.pPagePool->cFreeCalls, STAMTYPE_COUNTER, "/MM/Page/Def/cFreeCalls", STAMUNIT_CALLS, "Number of MMR3PageFree()+MMR3PageFreeByPhys() calls for the default pool.");
STAM_REG(pVM, &pVM->mm.s.pPagePool->cToPhysCalls, STAMTYPE_COUNTER, "/MM/Page/Def/cToPhysCalls", STAMUNIT_CALLS, "Number of MMR3Page2Phys() calls for this pool.");
STAM_REG(pVM, &pVM->mm.s.pPagePool->cToVirtCalls, STAMTYPE_COUNTER, "/MM/Page/Def/cToVirtCalls", STAMUNIT_CALLS, "Number of MMR3PagePhys2Page()+MMR3PageFreeByPhys() calls for the default pool.");
STAM_REG(pVM, &pVM->mm.s.pPagePool->cErrors, STAMTYPE_COUNTER, "/MM/Page/Def/cErrors", STAMUNIT_ERRORS,"Number of errors for the default pool.");
return VERR_NO_MEMORY;
STAM_REG(pVM, &pVM->mm.s.pPagePoolLow->cPages, STAMTYPE_U32, "/MM/Page/Low/cPages", STAMUNIT_PAGES, "Number of pages in the <4GB pool.");
STAM_REG(pVM, &pVM->mm.s.pPagePoolLow->cFreePages, STAMTYPE_U32, "/MM/Page/Low/cFreePages", STAMUNIT_PAGES, "Number of free pages in the <4GB pool.");
STAM_REG(pVM, &pVM->mm.s.pPagePoolLow->cSubPools, STAMTYPE_U32, "/MM/Page/Low/cSubPools", STAMUNIT_COUNT, "Number of sub pools in the <4GB pool.");
STAM_REG(pVM, &pVM->mm.s.pPagePoolLow->cAllocCalls, STAMTYPE_COUNTER, "/MM/Page/Low/cAllocCalls", STAMUNIT_CALLS, "Number of MMR3PageAllocLow() calls for the <4GB pool.");
STAM_REG(pVM, &pVM->mm.s.pPagePoolLow->cFreeCalls, STAMTYPE_COUNTER, "/MM/Page/Low/cFreeCalls", STAMUNIT_CALLS, "Number of MMR3PageFreeLow()+MMR3PageFreeByPhys() calls for the <4GB pool.");
STAM_REG(pVM, &pVM->mm.s.pPagePoolLow->cToPhysCalls,STAMTYPE_COUNTER, "/MM/Page/Low/cToPhysCalls", STAMUNIT_CALLS, "Number of MMR3Page2Phys() calls for the <4GB pool.");
STAM_REG(pVM, &pVM->mm.s.pPagePoolLow->cToVirtCalls,STAMTYPE_COUNTER, "/MM/Page/Low/cToVirtCalls", STAMUNIT_CALLS, "Number of MMR3PagePhys2Page()+MMR3PageFreeByPhys() calls for the <4GB pool.");
STAM_REG(pVM, &pVM->mm.s.pPagePoolLow->cErrors, STAMTYPE_COUNTER, "/MM/Page/Low/cErrors", STAMUNIT_ERRORS,"Number of errors for the <4GB pool.");
/** @todo init a mutex? */
return VINF_SUCCESS;
}
/**
* Release all locks and free the allocated memory.
*
* @param pVM VM handle.
* @thread The Emulation Thread.
*/
{
{
/*
* Unlock all memory held by subpools and free the memory.
* (The MM Heap will free the memory used for internal stuff.)
*/
while (pSubPool)
{
/* next */
}
}
{
/*
* Free the memory.
*/
while (pSubPool)
{
/* next */
}
}
}
/**
* Allocates a page from the page pool.
*
* @returns Pointer to allocated page(s).
* @returns NULL on failure.
* @param pPool Pointer to the page pool.
* @thread The Emulation Thread.
*/
{
/*
* Walk free list.
*/
{
/* decrement free count and unlink if no more free entries. */
if (!--pSub->cPagesFree)
#ifdef VBOX_WITH_STATISTICS
pPool->cFreePages--;
#endif
/* find free spot in bitmap. */
#ifdef USE_INLINE_ASM_BIT_OPS
if (iPage >= 0)
{
}
#else
{
unsigned u;
if ((u = *pu) != ~0U)
{
unsigned iBit = 0;
unsigned uMask = 1;
{
if (!(u & uMask))
{
}
iBit++;
uMask <<= 1;
}
AssertMsgFailed(("how odd, expected to find a free bit in %#x, but didn't\n", u));
}
/* next */
pu++;
}
#endif
#ifdef VBOX_WITH_STATISTICS
pPool->cFreePages++;
#endif
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));
}
/*
* Allocate new subpool.
*/
+ sizeof(MMPPLOOKUPHCPTR));
if (!pSub)
return NULL;
int rc;
{
/*
* Allocate and lock the pages.
*/
if (VBOX_SUCCESS(rc))
{
if (VBOX_FAILURE(rc))
{
}
}
}
else
if (VBOX_SUCCESS(rc))
{
/*
* Setup the sub structure and allocate the requested page.
*/
/* allocate first page. */
/* link into free chain. */
/* link into main chain. */
/* update pool statistics. */
#ifdef VBOX_WITH_STATISTICS
#endif
/*
* Initialize the physical pages with backpointer to subpool.
*/
unsigned i = cPages;
while (i-- > 0)
{
}
/*
* Initialize the physical lookup record with backpointers to the physical pages.
*/
i = cPages;
while (i-- > 0)
{
}
/*
* And the one record for virtual memory lookup.
*/
/* return allocated page (first). */
}
N_("Failed to expand page pool for memory below 4GB. current size: %d pages\n"),
AssertMsgFailed(("Failed to expand pool%s. rc=%Vrc poolsize=%d\n",
return NULL;
}
/**
* Frees a page from the page pool.
*
* @param pPool Pointer to the page pool.
* @param pv Pointer to the page to free.
* I.e. pointer returned by mmr3PagePoolAlloc().
* @thread The Emulation Thread.
*/
{
/*
* Lookup the virtual address.
*/
if ( !pLookup
)
{
return;
}
/*
* Free the page.
*/
/* clear bitmap bit */
#ifdef USE_INLINE_ASM_BIT_OPS
#else
#endif
/* update stats. */
pSubPool->cPagesFree++;
#ifdef VBOX_WITH_STATISTICS
pPool->cFreePages++;
#endif
{
}
}
/**
* Allocates a page from the page pool.
*
* This function may returns pages which has physical addresses any
* where. If you require a page to be within the first 4GB of physical
* memory, use MMR3PageAllocLow().
*
* @returns Pointer to the allocated page page.
* @returns NULL on failure.
* @param pVM VM handle.
* @thread The Emulation Thread.
*/
{
}
/**
* Allocates a page from the page pool and return its physical address.
*
* This function may returns pages which has physical addresses any
* where. If you require a page to be within the first 4GB of physical
* memory, use MMR3PageAllocLow().
*
* @returns Pointer to the allocated page page.
* @returns NIL_RTHCPHYS on failure.
* @param pVM VM handle.
* @thread The Emulation Thread.
*/
{
/** @todo optimize this, it's the most common case now. */
if (pv)
return NIL_RTHCPHYS;
}
/**
* Frees a page allocated from the page pool by MMR3PageAlloc() or
* MMR3PageAllocPhys().
*
* @param pVM VM handle.
* @param pvPage Pointer to the page.
* @thread The Emulation Thread.
*/
{
}
/**
* Allocates a page from the low page pool.
*
* @returns Pointer to the allocated page.
* @returns NULL on failure.
* @param pVM VM handle.
* @thread The Emulation Thread.
*/
{
}
/**
* Frees a page allocated from the page pool by MMR3PageAllocLow().
*
* @param pVM VM handle.
* @param pvPage Pointer to the page.
* @thread The Emulation Thread.
*/
{
}
/**
* Free a page allocated from the page pool by physical address.
* This works for pages allocated by MMR3PageAlloc(), MMR3PageAllocPhys()
* and MMR3PageAllocLow().
*
* @param pVM VM handle.
* @param HCPhysPage The physical address of the page to be freed.
* @thread The Emulation Thread.
*/
{
if (!pvPage)
if (pvPage)
else
}
/**
* Gets the HC pointer to the dummy page.
*
* The dummy page is used as a place holder to prevent potential bugs
* from doing really bad things to the system.
*
* @returns Pointer to the dummy page.
* @param pVM VM handle.
* @thread The Emulation Thread.
*/
{
{
}
}
/**
* Gets the HC Phys to the dummy page.
*
* The dummy page is used as a place holder to prevent potential bugs
* from doing really bad things to the system.
*
* @returns Pointer to the dummy page.
* @param pVM VM handle.
* @thread The Emulation Thread.
*/
{
}