VirtualBox

Changeset 5033

Show
Ignore:
Timestamp:
09/26/07 06:48:51 (1 year ago)
Author:
vboxsync
Message:

GMM...

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • 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 

© 2008 Sun Microsystems, Inc.
ContactPrivacy policy