VirtualBox

Changeset 14494

Show
Ignore:
Timestamp:
11/23/08 23:49:36 (2 months ago)
Author:
vboxsync
Message:

#1865: PGMR0DynMap - retry with smaller segments if one big one is rejected.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/include/VBox/err.h

    r14363 r14494  
    419419/** The auto usage cache for the dynamic mapping set is full. */ 
    420420#define VERR_PGM_DYNMAP_FULL_SET                (-1630) 
     421/** The initialization of the dynamic mapping cache failed. */ 
     422#define VERR_PGM_DYNMAP_SETUP_ERROR             (-1631) 
     423/** The expanding of the dynamic mapping cache failed. */ 
     424#define VERR_PGM_DYNMAP_EXPAND_ERROR            (-1632) 
    421425 
    422426/** @} */ 
  • trunk/include/iprt/err.h

    r14006 r14494  
    409409/** Retry the operation. */ 
    410410#define VERR_TRY_AGAIN                      (-52) 
     411/** Retry the operation. */ 
     412#define VINF_TRY_AGAIN                      52 
    411413/** Generic parse error. */ 
    412414#define VERR_PARSE_ERROR                    (-53) 
  • trunk/src/VBox/VMM/VMMR0/PGMR0DynMap.cpp

    r14493 r14494  
    4444/** The max size of the mapping cache (in pages). */ 
    4545#define PGMR0DYNMAP_MAX_PAGES               ((8*_1M) >> PAGE_SHIFT) 
    46 /* * The max segment size. */ 
    47 /** @todo #define PGMR0DYNMAP_SEG_MAX_PAGES           (_1M >> PAGE_SHIFT) */ 
     46/** The small segment size that is adopted on out-of-memory conditions with a 
     47 * single big segment. */ 
     48#define PGMR0DYNMAP_SMALL_SEG_PAGES         128 
    4849/** The number of pages we reserve per CPU. */ 
    4950#define PGMR0DYNMAP_PAGES_PER_CPU           64 
     
    140141    /** The current load. */ 
    141142    uint32_t                    cLoad; 
    142     /** The max load
     143    /** The max load ever
    143144     * This is maintained to get trigger adding of more mapping space. */ 
    144145    uint32_t                    cMaxLoad; 
     
    203204static void pgmR0DynMapReleasePage(PPGMR0DYNMAP pThis, uint32_t iPage, uint32_t cRefs); 
    204205static int  pgmR0DynMapSetup(PPGMR0DYNMAP pThis); 
    205 static int  pgmR0DynMapGrow(PPGMR0DYNMAP pThis); 
     206static int  pgmR0DynMapExpand(PPGMR0DYNMAP pThis); 
    206207static void pgmR0DynMapTearDown(PPGMR0DYNMAP pThis); 
    207208 
     
    320321     */ 
    321322    VMCPUID idCpu = pVM->cCPUs; 
     323    AssertReturn(idCpu > 0 && idCpu <= VMCPU_MAX_CPU_COUNT, VERR_INTERNAL_ERROR); 
    322324    while (idCpu-- > 0) 
    323325    { 
     
    341343 
    342344    /* 
    343      * Reference and if necessary setup or grow the cache. 
     345     * Reference and if necessary setup or expand the cache. 
    344346     */ 
    345347    PPGMR0DYNMAP pThis = g_pPGMR0DynMap; 
     
    352354        rc = pgmR0DynMapSetup(pThis); 
    353355    else if (pThis->cMaxLoad > PGMR0DYNMAP_CALC_OVERLOAD(pThis->cPages)) 
    354         rc = pgmR0DynMapGrow(pThis); 
    355     if (RT_FAILURE(rc)) 
     356        rc = pgmR0DynMapExpand(pThis); 
     357    if (RT_SUCCESS(rc)) 
     358        pVM->pgm.s.pvR0DynMapUsed = pThis; 
     359    else 
    356360        pThis->cUsers--; 
    357361 
     
    402406                while (j-- > 0) 
    403407                { 
    404                     int32_t cRefs = pSet->aEntries[j].cRefs; 
     408                    int32_t cRefs = pSet->aEntries[j].cRefs; 
    405409                    uint32_t iPage = pSet->aEntries[j].iPage; 
    406410                    LogRel(("PGMR0DynMapTermVM: %d dangling refs to %#x\n", cRefs, iPage)); 
     
    408412                        pgmR0DynMapReleasePage(pThis, iPage, cRefs); 
    409413                    else 
    410                         AssertMsgFailed(("cRefs=%d iPage=%#x cPages=%u\n", cRefs, iPage, pThis->cPages)); 
     414                        AssertLogRelMsgFailed(("cRefs=%d iPage=%#x cPages=%u\n", cRefs, iPage, pThis->cPages)); 
    411415 
    412416                    pSet->aEntries[j].iPage = UINT16_MAX; 
     
    415419                pSet->cEntries = PGMMAPSET_CLOSED; 
    416420            } 
     421            else 
     422                AssertMsg(j == PGMMAPSET_CLOSED, ("cEntries=%#x\n", j)); 
    417423 
    418424            j = RT_ELEMENTS(pSet->aEntries); 
     
    433439    } 
    434440    else 
    435         AssertMsgFailed(("pvR0DynMapUsed=%p pThis=%p\n", pVM->pgm.s.pvR0DynMapUsed, pThis)); 
     441        AssertLogRelMsgFailed(("pvR0DynMapUsed=%p pThis=%p\n", pVM->pgm.s.pvR0DynMapUsed, pThis)); 
    436442 
    437443    RTSemFastMutexRelease(pThis->hInitLock); 
     
    445451 * @returns Number of pages. 
    446452 * @param   pThis       The dynamic mapping cache instance. 
    447  */ 
    448 static uint32_t pgmR0DynMapCalcNewSize(PPGMR0DYNMAP pThis) 
    449 
    450     /* 
    451      * cCpus * PGMR0DYNMAP_PAGES_PER_CPU. 
    452      */ 
    453     RTCPUID     cCpus = RTMpGetCount(); 
    454     uint32_t    cPages = cCpus * PGMR0DYNMAP_PAGES_PER_CPU; 
     453 * @param   pcMinPages  The minimal size in pages. 
     454 */ 
     455static uint32_t pgmR0DynMapCalcNewSize(PPGMR0DYNMAP pThis, uint32_t *pcMinPages) 
     456
     457    Assert(pThis->cPages <= PGMR0DYNMAP_MAX_PAGES); 
     458 
     459    /* cCpus * PGMR0DYNMAP_PAGES_PER_CPU (/2). */ 
     460    RTCPUID     cCpus     = RTMpGetCount(); 
     461    uint32_t    cPages    = cCpus * PGMR0DYNMAP_PAGES_PER_CPU; 
     462    uint32_t    cMinPages = cCpus * (PGMR0DYNMAP_PAGES_PER_CPU / 2); 
    455463 
    456464    /* adjust against cMaxLoad. */ 
     
    462470        cPages += PGMR0DYNMAP_PAGES_PER_CPU; 
    463471 
    464     /* adjust against max size. */ 
     472    if (pThis->cMaxLoad > cMinPages) 
     473        cMinPages = pThis->cMaxLoad; 
     474 
     475    /* adjust against max and current size. */ 
     476    if (cPages < pThis->cPages) 
     477        cPages = pThis->cPages; 
    465478    if (cPages > PGMR0DYNMAP_MAX_PAGES) 
    466479        cPages = PGMR0DYNMAP_MAX_PAGES; 
    467480 
     481    if (cMinPages < pThis->cPages) 
     482        cMinPages = pThis->cPages; 
     483    if (cMinPages > PGMR0DYNMAP_MAX_PAGES) 
     484        cMinPages = PGMR0DYNMAP_MAX_PAGES; 
     485 
     486    *pcMinPages = cMinPages; 
    468487    return cPages; 
    469488} 
     
    577596 * and restarting from CR3 for every change. 
    578597 * 
    579  * @returns VBox status code, VERR_TRY_AGAIN if we changed any mappings and had 
     598 * @returns VBox status code, VINF_TRY_AGAIN if we changed any mappings and had 
    580599 *          to re-enable interrupts. 
    581600 * @param   pThis       The dynamic mapping cache instance. 
     
    589608                                        PPGMR0DYNMAPSEG pSeg, uint32_t cMaxPTs, void **ppvPTE) 
    590609{ 
     610    Assert(!(ASMGetFlags() & X86_EFL_IF)); 
     611 
    591612    void           *pvEntry = NULL; 
    592613    X86PGPAEUINT    uEntry = ASMGetCR3(); 
     
    612633            if (RT_SUCCESS(rc)) 
    613634            { 
    614                 rc = RTR0MemObjMapKernel(&pPgLvl->a[i].hMapObj, pPgLvl->a[i].hMemObj, &pPgLvl->a[i].u.pv, 0, RTMEM_PROT_WRITE | RTMEM_PROT_READ); 
     635                rc = RTR0MemObjMapKernel(&pPgLvl->a[i].hMapObj, pPgLvl->a[i].hMemObj, &pPgLvl->a[i].u.pv, 0 /* cbAlignment */, 
     636                                         RTMEM_PROT_WRITE | RTMEM_PROT_READ); 
    615637                if (RT_SUCCESS(rc)) 
    616638                { 
     
    619641                        pSeg->ahMemObjPTs[pSeg->cPTs++] = pPgLvl->a[i].hMemObj; 
    620642                    ASMIntDisable(); 
    621                     return VERR_TRY_AGAIN; 
     643                    return VINF_TRY_AGAIN; 
    622644                } 
    623645 
     
    627649                pPgLvl->a[i].hMemObj = NIL_RTR0MEMOBJ; 
    628650            pPgLvl->a[i].HCPhys = NIL_RTHCPHYS; 
    629             AssertReturn(rc != VERR_TRY_AGAIN, VERR_INTERNAL_ERROR); 
    630651            return rc; 
    631652        } 
     
    739760                rc = pgmR0DynMapPagingArrayMapPte(pThis, &PgLvl, pbPage, pSeg, cMaxPTs, 
    740761                                                  &pThis->paPages[iPage].uPte.pv); 
    741             while (rc == VERR_TRY_AGAIN); 
     762            while (rc == VINF_TRY_AGAIN); 
    742763            if (RT_FAILURE(rc)) 
    743764                break; 
    744             rc = VINF_SUCCESS; 
    745765 
    746766            /* Save the PTE. */ 
     
    802822     * Calc the size and add a segment of that size. 
    803823     */ 
    804     uint32_t cPages = pgmR0DynMapCalcNewSize(pThis); 
     824    uint32_t cMinPages; 
     825    uint32_t cPages = pgmR0DynMapCalcNewSize(pThis, &cMinPages); 
    805826    AssertReturn(cPages, VERR_INTERNAL_ERROR); 
    806     return pgmR0DynMapAddSeg(pThis, cPages); 
     827    int rc = pgmR0DynMapAddSeg(pThis, cPages); 
     828    if (rc == VERR_NO_MEMORY) 
     829    { 
     830        /* 
     831         * Try adding smaller segments. 
     832         */ 
     833        do 
     834            rc = pgmR0DynMapAddSeg(pThis, PGMR0DYNMAP_SMALL_SEG_PAGES); 
     835        while (RT_SUCCESS(rc) && pThis->cPages < cPages); 
     836        if (rc == VERR_NO_MEMORY && pThis->cPages >= cMinPages) 
     837            rc = VINF_SUCCESS; 
     838        if (rc == VERR_NO_MEMORY) 
     839        { 
     840            if (pThis->cPages) 
     841                pgmR0DynMapTearDown(pThis); 
     842            rc = VERR_PGM_DYNMAP_SETUP_ERROR; 
     843        } 
     844    } 
     845    Assert(ASMGetFlags() & X86_EFL_IF); 
     846    return rc; 
    807847} 
    808848 
     
    814854 * @param   pThis       The dynamic mapping cache instance. 
    815855 */ 
    816 static int pgmR0DynMapGrow(PPGMR0DYNMAP pThis) 
     856static int pgmR0DynMapExpand(PPGMR0DYNMAP pThis) 
    817857{ 
    818858    /* 
    819859     * Calc the new target size and add a segment of the appropriate size. 
    820860     */ 
    821     uint32_t cPages = pgmR0DynMapCalcNewSize(pThis); 
     861    uint32_t cMinPages; 
     862    uint32_t cPages = pgmR0DynMapCalcNewSize(pThis, &cMinPages); 
    822863    if (pThis->cPages >= cPages) 
    823864        return VINF_SUCCESS; 
    824865 
    825866    uint32_t cAdd = cPages - pThis->cPages; 
    826     return pgmR0DynMapAddSeg(pThis, cAdd); 
     867    int rc = pgmR0DynMapAddSeg(pThis, cAdd); 
     868    if (rc == VERR_NO_MEMORY) 
     869    { 
     870        /* 
     871         * Try adding smaller segments. 
     872         */ 
     873        do 
     874            rc = pgmR0DynMapAddSeg(pThis, PGMR0DYNMAP_SMALL_SEG_PAGES); 
     875        while (RT_SUCCESS(rc) && pThis->cPages < cPages); 
     876        if (rc == VERR_NO_MEMORY && pThis->cPages >= cMinPages) 
     877            rc = VINF_SUCCESS; 
     878        if (rc == VERR_NO_MEMORY) 
     879            rc = VERR_PGM_DYNMAP_EXPAND_ERROR; 
     880    } 
     881    Assert(ASMGetFlags() & X86_EFL_IF); 
     882    return rc; 
    827883} 
    828884 
     
    912968            pSeg->ahMemObjPTs[iPT] = NIL_RTR0MEMOBJ; 
    913969        } 
    914         rc = RTR0MemObjFree(pSeg->hMemObj,   true /* fFreeMappings */); AssertRC(rc); 
     970        rc = RTR0MemObjFree(pSeg->hMemObj, true /* fFreeMappings */); AssertRC(rc); 
    915971        pSeg->hMemObj   = NIL_RTR0MEMOBJ; 
    916972        pSeg->pNext     = NULL; 

© 2008 Sun Microsystems, Inc.
ContactPrivacy policy