VirtualBox

Changeset 14494 in vbox for trunk/src


Ignore:
Timestamp:
Nov 23, 2008 10:49:36 PM (16 years ago)
Author:
vboxsync
Message:

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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;
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