VirtualBox

Changeset 5033 in vbox


Ignore:
Timestamp:
Sep 26, 2007 4:48:51 AM (17 years ago)
Author:
vboxsync
Message:

GMM...

Location:
trunk
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/gmm.h

    r5026 r5033  
    2020
    2121#include <VBox/types.h>
     22#include <VBox/gvmm.h>
    2223
    23 #include "gvmm.h"
    2424
    2525/** @defgroup   grp_gmm     GMM - The Global Memory Manager
     
    5454
    5555
     56/**
     57 * Over-commitment policy.
     58 */
     59typedef enum GMMOCPOLICY
     60{
     61    /** The usual invalid 0 value. */
     62    GMMOCPOLICY_INVALID = 0,
     63    /** No over-commitment, fully backed.
     64     * The GMM guarantees that it will be able to allocate all of the
     65     * guest RAM for a VM with OC policy. */
     66    GMMOCPOLICY_NO_OC,
     67    /** to-be-determined. */
     68    GMMOCPOLICY_TBD,
     69    /** The end of the valid policy range. */
     70    GMMOCPOLICY_END,
     71    /** The usual 32-bit hack. */
     72    GMMOCPOLICY_32BIT_HACK = 0x7fffffff
     73} GMMOCPOLICY;
     74
     75/**
     76 * VM / Memory priority.
     77 */
     78typedef enum GMMPRORITY
     79{
     80    /** The usual invalid 0 value. */
     81    GMMPRORITY_INVALID = 0,
     82    /** High - avoid interrupting it if at all possible */
     83    GMMPRORITY_HIGH,
     84    /** Normal - pause, save it or kill it. */
     85    GMMPRORITY_NORMAL,
     86    /** Low - save or kill it. */
     87    GMMPRORITY_LOW,
     88    /** The end of the valid priority range. */
     89    GMMPRORITY_END = 0,
     90    /** The custom 32-bit type blowup. */
     91    GMMPRORITY_32BIT_HACK = 0x7fffffff
     92} GMMPRIORITY;
     93
     94
    5695/** @} */
    5796
  • trunk/src/VBox/VMM/Makefile.kmk

    r5029 r5033  
    313313        $(PATH_SUB_CURRENT) \
    314314        PATM
    315 VMMR0_DEFS      = IN_VMM_R0 IN_RT_R0 IN_TRPM_R0 IN_CPUM_R0 IN_VM_R0 IN_TM_R0 IN_INTNET_R0 IN_HWACCM_R0 IN_EM_R0 IN_PDM_R0 IN_PGM_R0 IN_DIS_R0 IN_MM_R0 IN_SELM_R0 IN_CSAM_R0 IN_PATM_R0 IN_DBGF_R0 IN_REM_R0 IN_IOM_R0 IN_GVMM_R0 DIS_CORE_ONLY
     315VMMR0_DEFS      = IN_VMM_R0 IN_RT_R0 IN_TRPM_R0 IN_CPUM_R0 IN_VM_R0 IN_TM_R0 IN_INTNET_R0 IN_HWACCM_R0 IN_EM_R0 IN_PDM_R0 IN_PGM_R0 IN_DIS_R0 IN_MM_R0 IN_SELM_R0 IN_CSAM_R0 IN_PATM_R0 IN_DBGF_R0 IN_REM_R0 IN_IOM_R0 IN_GVMM_R0 IN_GMM_R0 DIS_CORE_ONLY
    316316ifdef VBOX_WITH_IDT_PATCHING
    317317VMMR0_DEFS     += VBOX_WITH_IDT_PATCHING
     
    327327        VMMR0/CPUMR0.cpp \
    328328        VMMR0/DBGFR0.cpp \
     329        VMMR0/GMMR0.cpp \
    329330        VMMR0/GVMMR0.cpp \
    330331        VMMR0/HWACCMR0.cpp \
     
    366367        VMMAll/VMAll.cpp \
    367368
     369
    368370ifeq ($(VBOX_LDR_FMT),pe)
    369371VMMR0_SOURCES += VMMR0/VMMR0.def
  • trunk/src/VBox/VMM/VMMR0/GMMR0.cpp

    r5018 r5033  
    1616 *
    1717 */
     18
    1819
    1920/** @page pg_gmm    GMM - The Global Memory Manager
     
    140141*   Header Files                                                               *
    141142*******************************************************************************/
    142 #include "../PGMInternal.h"
    143 
     143#define LOG_GROUP LOG_GROUP_GMM
     144#include <VBox/gmm.h>
     145#include "GMMR0Internal.h"
     146#include <VBox/gvm.h>
     147#include <VBox/log.h>
     148#include <VBox/param.h>
     149#include <iprt/avl.h>
     150#include <iprt/mem.h>
     151#include <iprt/memobj.h>
     152#include <iprt/semaphore.h>
     153#include <iprt/string.h>
    144154
    145155
     
    155165 *
    156166 * Because of the different layout on 32-bit and 64-bit hosts, macros
    157  * are used to set and get the data.
     167 * are used to get and set some of the data.
    158168 */
    159169typedef union GMMPAGE
     
    347357    uint16_t        au16Reserved;
    348358    /** The pages. */
    349     GMMPAGE         aPages[GMM_CHUNK_SIZE >> PAGE_SIZE];
     359    GMMPAGE         aPages[GMM_CHUNK_SIZE >> PAGE_SHIFT];
    350360} GMMCHUNK;
    351361
     
    359369    uint32_t        idChunk;
    360370    /** Pointer to the chunk. */
    361     PGGMCHUNK       pChunk;
     371    PGMMCHUNK       pChunk;
    362372} GMMCHUNKTLBE;
    363373/** Pointer to an allocation chunk TLB entry. */
     
    415425     * This is determined at initialization time. */
    416426    bool                fLegacyMode;
     427    /** The number of active VMs. */
     428    uint16_t            cActiveVMs;
    417429} GMM;
    418430/** Pointer to the GMM instance. */
     
    423435
    424436
     437/*******************************************************************************
     438*   Global Variables                                                           *
     439*******************************************************************************/
     440/** Pointer to the GMM instance data. */
     441static PGMM g_pGMM = NULL;
     442
     443/** Macro for obtaining and validating the g_pGMM pointer.
     444 * On failure it will return from the invoking function with the specified return value.
     445 *
     446 * @param   pGMM    The name of the pGMM variable.
     447 * @param   rc      The return value on failure. Use VERR_INTERNAL_ERROR for
     448 *                  VBox status codes.
     449 */
     450#define GMM_GET_VALID_INSTANCE(pGMM, rc) \
     451    do { \
     452        (pGMM) = g_pGMM; \
     453        AssertPtrReturn((pGMM), (rc)); \
     454        AssertMsgReturn((pGMM)->u32Magic == GMM_MAGIC, ("%p - %#x\n", (pGMM), (pGMM)->u32Magic), (rc)); \
     455    } while (0)
     456
     457/** Macro for obtaining and validating the g_pGMM pointer, void function variant.
     458 * On failure it will return from the invoking function.
     459 *
     460 * @param   pGMM    The name of the pGMM variable.
     461 */
     462#define GMM_GET_VALID_INSTANCE_VOID(pGMM) \
     463    do { \
     464        (pGMM) = g_pGMM; \
     465        AssertPtrReturnVoid((pGMM)); \
     466        AssertMsgReturnVoid((pGMM)->u32Magic == GMM_MAGIC, ("%p - %#x\n", (pGMM), (pGMM)->u32Magic)); \
     467    } while (0)
     468
    425469
    426470/*******************************************************************************
    427471*   Internal Functions                                                         *
    428472*******************************************************************************/
    429 static DECLCALLBACK int gmmR0TermDestroyChunk(PAVLU32NODECORE pNode, void *pvGMM);
     473static DECLCALLBACK(int) gmmR0TermDestroyChunk(PAVLU32NODECORE pNode, void *pvGMM);
     474static DECLCALLBACK(int) gmmR0FreeVMPagesInChunk(PAVLU32NODECORE pNode, void *pvhGVM);
    430475
    431476
     
    507552    g_pGMM = NULL;
    508553    pGMM->u32Magic++;
    509     RTSemEventDestroy(&pGMM->Mtx);
     554    RTSemFastMutexDestroy(pGMM->Mtx);
    510555    pGMM->Mtx = NIL_RTSEMFASTMUTEX;
    511556
    512557    /* free any chunks still hanging around. */
    513     RTAvlU32Destroy(pGMM->Chunks, gmmR0TermDestroyChunk, pGMM);
     558    RTAvlU32Destroy(&pGMM->pChunks, gmmR0TermDestroyChunk, pGMM);
    514559
    515560    /* finally the instance data itself. */
     
    526571 * @param   pvGMM   The GMM handle.
    527572 */
    528 static DECLCALLBACK int gmmR0TermDestroyChunk(PAVLU32NODECORE pNode, void *pvGMM)
    529 {
    530     PGMMCHUNK pChunk = (PGMMCHUNK) pNode;
     573static DECLCALLBACK(int) gmmR0TermDestroyChunk(PAVLU32NODECORE pNode, void *pvGMM)
     574{
     575    PGMMCHUNK pChunk = (PGMMCHUNK)pNode;
    531576
    532577    if (pChunk->cFree != (GMM_CHUNK_SIZE >> PAGE_SHIFT))
     
    553598
    554599/**
    555  * Cleans up when a VM is terminated.
    556  *
    557  * @param   pVM     The VM structure.
    558  * @param   hGVM    The global VM handle.
    559  */
    560 GMMR0DECL(void) GMMR0CleanupVM(PVM pVM, uint32_t hGVM)
    561 {
    562     LogFlow(("GMMR0CleanupVM: pVM=%p hGVM=%#x\n", pVM, hGVM));
    563 
    564     PGMM pGMM = g_pGMM;
    565     if (    !VALID_PTR(pGMM)
    566         ||  pGMM->u32Magic != GMM_MAGIC)
    567         return;
     600 * Initializes the per-VM data for the GMM.
     601 *
     602 * @param   pGVM    Pointer to the Global VM structure.
     603 */
     604GMMR0DECL(void) GMMR0InitPerVMData(PGVM pGVM)
     605{
     606    pGVM->gmm.s.cRAMPages = 0;
     607    pGVM->gmm.s.cPrivatePages = 0;
     608    pGVM->gmm.s.cSharedPages = 0;
     609    pGVM->gmm.s.enmPolicy = GMMOCPOLICY_TBD;
     610    pGVM->gmm.s.enmPriority = GMMPRORITY_NORMAL;
     611}
     612
     613
     614/**
     615 * Cleans up when a VM is terminating.
     616 *
     617 * @param   pGVM    Pointer to the Global VM structure.
     618 */
     619GMMR0DECL(void) GMMR0CleanupVM(PGVM pGVM)
     620{
     621    LogFlow(("GMMR0CleanupVM: pGVM=%p:{.pVM=%p, .hSelf=%#x}\n", pGVM, pGVM->pVM, pGVM->hSelf));
     622
     623    PGMM pGMM;
     624    GMM_GET_VALID_INSTANCE_VOID(pGMM);
    568625
    569626    int rc =  RTSemFastMutexRequest(pGMM->Mtx);
     
    571628
    572629    /*
    573      * Walk the entire pool looking for pages that belongs to this VM.
    574      * This is slow but necessary. Of course it won't work for shared
    575      * pages, but we'll deal with that later.
     630     * If it's the last VM around, we can skip walking all the chunk looking
     631     * for the pages owned by this VM and instead flush the whole shebang.
     632     *
     633     * This takes care of the eventuality that a VM has left shared page
     634     * references behind (shouldn't happen of course, but you never know).
    576635     */
    577 
    578 
    579     /*
    580      * Update over-commitment management and free chunks that are no
    581      * longer needed. If no VMs are around, free everything.
    582      */
    583 
     636    if (pGMM->cActiveVMs == 1)
     637    {
     638       
     639    }
     640    else if (pGVM->gmm.s.cPrivatePages)
     641    {
     642        /*
     643         * Walk the entire pool looking for pages that belongs to this VM.
     644         * This is slow but necessary. Of course it won't work for shared
     645         * pages, but we'll deal with that later.
     646         */
     647        RTAvlU32DoWithAll(&pGMM->pChunks, true /* fFromLeft */, gmmR0FreeVMPagesInChunk, (void *)pGVM->hSelf);
     648
     649        /*
     650         * Update over-commitment management and free chunks that are no
     651         * longer needed.
     652         */
     653       
     654    }
    584655
    585656    RTSemFastMutexRelease(pGMM->Mtx);
     657
     658    /* trash the data */
     659    pGVM->gmm.s.cRAMPages = 0;
     660    pGVM->gmm.s.cPrivatePages = 0;
     661    pGVM->gmm.s.cSharedPages = 0;
     662    pGVM->gmm.s.enmPolicy = GMMOCPOLICY_INVALID;
     663    pGVM->gmm.s.enmPriority = GMMPRORITY_INVALID;
     664
    586665    LogFlow(("GMMR0CleanupVM: returns\n"));
    587666}
    588667
    589668
     669/**
     670 * RTAvlU32DoWithAll callback.
     671 *
     672 * @returns 0
     673 * @param   pNode   The node to destroy.
     674 * @param   pvhGVM  The GVM::hSelf value.
     675 */
     676static DECLCALLBACK(int) gmmR0FreeVMPagesInChunk(PAVLU32NODECORE pNode, void *pvhGVM)
     677{
     678    PGMMCHUNK pChunk = (PGMMCHUNK)pNode;
     679    uint16_t hGVM = (uintptr_t)pvhGVM;
     680
     681#ifndef VBOx_STRICT
     682    if (pChunk->cFree != (GMM_CHUNK_SIZE >> PAGE_SHIFT))
     683#endif
     684    {
     685        /*
     686         * Perform some internal checks while we're scanning.
     687         */
     688        unsigned cPrivate = 0;
     689        unsigned cShared = 0;
     690        unsigned cFree = 0;
     691
     692        unsigned iPage = (GMM_CHUNK_SIZE >> PAGE_SHIFT);
     693        while (iPage-- > 0)
     694            if (GMM_PAGE_IS_PRIVATE(&pChunk->aPages[iPage]))
     695
     696            {
     697                if (pChunk->aPages[iPage].Private.hGVM == hGVM)
     698                {
     699                    /* Free it. */
     700                    pChunk->aPages[iPage].u = 0;
     701                    pChunk->aPages[iPage].Free.idNext = pChunk->idFreeHead;
     702                    pChunk->aPages[iPage].Free.u2State = GMM_PAGE_STATE_FREE;
     703                    pChunk->idFreeHead = iPage;
     704                    pChunk->cPrivate--;
     705                    pChunk->cFree++;
     706                    cFree++;
     707                }
     708                else
     709                    cPrivate++;
     710            }
     711            else if (GMM_PAGE_IS_FREE(&pChunk->aPages[iPage]))
     712                cFree++;
     713            else
     714                cShared++;
     715
     716        /*
     717         * Did it add up?
     718         */
     719        if (RT_UNLIKELY(    pChunk->cFree != cFree
     720                        ||  pChunk->cPrivate != cPrivate
     721                        ||  pChunk->cShared != cShared))
     722        {
     723            SUPR0Printf("GMM: Chunk %p/%#x has bogus stats - free=%d/%d private=%d/%d shared=%d/%d\n",
     724                        pChunk->cFree, cFree, pChunk->cPrivate, cPrivate, pChunk->cShared, cShared);
     725            pChunk->cFree = cFree;
     726            pChunk->cPrivate = cPrivate;
     727            pChunk->cShared = cShared;
     728        }
     729    }
     730
     731    return 0;
     732}
     733
     734
     735
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette