VirtualBox

Changeset 18617 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Apr 1, 2009 10:11:29 PM (16 years ago)
Author:
vboxsync
Message:

PGM,EM: Handle out of memory situations more gracefully - part 1. New debugger commands: .pgmerror and .pgmerroroff.

Location:
trunk/src/VBox/VMM/VMMAll
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/PGMAllBth.h

    r18330 r18617  
    7575 *
    7676 * @returns VBox status code (appropriate for trap handling and GC return).
     77 *
    7778 * @param   pVM         VM Handle.
    7879 * @param   uErr        The trap error code.
     
    764765                            return rc;
    765766                        }
     767                        if (RT_UNLIKELY(VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY)))
     768                            return VINF_EM_NO_MEMORY;
    766769                    }
    767770                    /// @todo count the above case; else
     
    17151718# ifdef PGM_SYNC_N_PAGES
    17161719                    Assert(cPages == 1 || !(uErr & X86_TRAP_PF_P));
    1717                     if (cPages > 1 && !(uErr & X86_TRAP_PF_P))
     1720                    if (    cPages > 1
     1721                        &&  !(uErr & X86_TRAP_PF_P)
     1722                        &&  !VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY))
    17181723                    {
    17191724                        /*
     
    19531958
    19541959    Assert(cPages == 1 || !(uErr & X86_TRAP_PF_P));
    1955     if (cPages > 1 && !(uErr & X86_TRAP_PF_P))
     1960    if (    cPages > 1
     1961        &&  !(uErr & X86_TRAP_PF_P)
     1962        &&  !VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY))
    19561963    {
    19571964        /*
     
    19932000                      (uint64_t)pPTDst->a[iPTDst].u,
    19942001                      pPTDst->a[iPTDst].u & PGM_PTFLAGS_TRACK_DIRTY ? " Track-Dirty" : ""));
     2002
     2003                if (RT_UNLIKELY(VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY)))
     2004                    break;
    19952005            }
    19962006            else
     
    26772687            PPGMRAMRANGE    pRam   = pVM->pgm.s.CTX_SUFF(pRamRanges);
    26782688            unsigned        iPTDst = 0;
    2679             while (iPTDst < RT_ELEMENTS(pPTDst->a))
     2689            while (     iPTDst < RT_ELEMENTS(pPTDst->a)
     2690                   &&   !VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY))
    26802691            {
    26812692                /* Advance ram range list. */
     
    27002711                            rc = pgmPhysPageMakeWritableUnlocked(pVM, pPage, GCPhys);
    27012712                            AssertRCReturn(rc, rc);
     2713                            if (VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY))
     2714                                break;
    27022715                        }
    27032716#  endif
  • trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp

    r18345 r18617  
    262262 * This will also take the appropriate actions when reaching water-marks.
    263263 *
    264  * @returns The following VBox status codes.
     264 * @returns VBox status code.
    265265 * @retval  VINF_SUCCESS on success.
    266266 * @retval  VERR_EM_NO_MEMORY if we're really out of memory.
     
    273273static int pgmPhysEnsureHandyPage(PVM pVM)
    274274{
    275     /** @remarks
    276      * low-water mark logic for R0 & GC:
    277      *      - 75%: Set FF.
    278      *      - 50%: Force return to ring-3 ASAP.
    279      *
    280      * For ring-3 there is a little problem wrt to the recompiler, so:
    281      *      - 75%: Set FF.
    282      *      - 50%: Try allocate pages; on failure we'll force REM to quite ASAP.
    283      *
    284      * The basic idea is that we should be able to get out of any situation with
    285      * only 50% of handy pages remaining.
    286      *
    287      * At the moment we'll not adjust the number of handy pages relative to the
    288      * actual VM RAM committment, that's too much work for now.
    289      */
    290     Assert(PDMCritSectIsOwner(&pVM->pgm.s.CritSect));
    291275    AssertMsg(pVM->pgm.s.cHandyPages <= RT_ELEMENTS(pVM->pgm.s.aHandyPages), ("%d\n", pVM->pgm.s.cHandyPages));
    292     if (    !pVM->pgm.s.cHandyPages
     276
     277    /*
     278     * Do we need to do anything special?
     279     */
    293280#ifdef IN_RING3
    294         ||   pVM->pgm.s.cHandyPages - 1 <= RT_ELEMENTS(pVM->pgm.s.aHandyPages) / 2 /* 50% */
    295 #endif
    296        )
    297     {
    298         Log(("PGM: cHandyPages=%u out of %u -> allocate more\n", pVM->pgm.s.cHandyPages, RT_ELEMENTS(pVM->pgm.s.aHandyPages)));
     281    if (pVM->pgm.s.cHandyPages <= RT_MAX(PGM_HANDY_PAGES_SET_FF, PGM_HANDY_PAGES_R3_ALLOC))
     282#else
     283    if (pVM->pgm.s.cHandyPages <= RT_MAX(PGM_HANDY_PAGES_SET_FF, PGM_HANDY_PAGES_RZ_TO_R3))
     284#endif
     285    {
     286        /*
     287         * Allocate pages only if we're out of them, or in ring-3, almost out.
     288         */
    299289#ifdef IN_RING3
    300         int rc = PGMR3PhysAllocateHandyPages(pVM);
     290        if (pVM->pgm.s.cHandyPages <= PGM_HANDY_PAGES_R3_ALLOC)
     291#else
     292        if (pVM->pgm.s.cHandyPages <= PGM_HANDY_PAGES_RZ_ALLOC)
     293#endif
     294        {
     295            Log(("PGM: cHandyPages=%u out of %u -> allocate more; VM_FF_PGM_NO_MEMORY=%RTbool\n",
     296                 pVM->pgm.s.cHandyPages, RT_ELEMENTS(pVM->pgm.s.aHandyPages), VM_FF_ISSET(pVM, VM_FF_PGM_NO_MEMORY) ));
     297#ifdef IN_RING3
     298            int rc = PGMR3PhysAllocateHandyPages(pVM);
    301299#elif defined(IN_RING0)
    302         int rc = VMMR0CallHost(pVM, VMMCALLHOST_PGM_ALLOCATE_HANDY_PAGES, 0);
     300            int rc = VMMR0CallHost(pVM, VMMCALLHOST_PGM_ALLOCATE_HANDY_PAGES, 0);
    303301#else
    304         int rc = VMMGCCallHost(pVM, VMMCALLHOST_PGM_ALLOCATE_HANDY_PAGES, 0);
    305 #endif
    306         if (RT_UNLIKELY(rc != VINF_SUCCESS))
    307         {
    308             AssertMsg(rc == VINF_EM_NO_MEMORY || rc == VERR_EM_NO_MEMORY, ("%Rrc\n", rc));
    309             if (!pVM->pgm.s.cHandyPages)
     302            int rc = VMMGCCallHost(pVM, VMMCALLHOST_PGM_ALLOCATE_HANDY_PAGES, 0);
     303#endif
     304            if (RT_UNLIKELY(rc != VINF_SUCCESS))
    310305            {
    311                 LogRel(("PGM: no more handy pages!\n"));
    312                 return VERR_EM_NO_MEMORY;
     306                if (RT_FAILURE(rc))
     307                    return rc;
     308                AssertMsgReturn(rc == VINF_EM_NO_MEMORY, ("%Rrc\n", rc), VERR_IPE_UNEXPECTED_INFO_STATUS);
     309                if (!pVM->pgm.s.cHandyPages)
     310                {
     311                    LogRel(("PGM: no more handy pages!\n"));
     312                    return VERR_EM_NO_MEMORY;
     313                }
     314                Assert(VM_FF_ISSET(pVM, VM_FF_PGM_NEED_HANDY_PAGES));
     315                Assert(VM_FF_ISSET(pVM, VM_FF_PGM_NO_MEMORY));
     316#ifdef IN_RING3
     317                REMR3NotifyFF(pVM);
     318#else
     319                VM_FF_SET(pVM, VM_FF_TO_R3); /* paranoia */
     320#endif
    313321            }
    314             Assert(VM_FF_ISSET(pVM, VM_FF_PGM_NEED_HANDY_PAGES));
    315 #ifdef IN_RING3
    316             REMR3NotifyFF(pVM);
    317 #else
    318             VM_FF_SET(pVM, VM_FF_TO_R3);
    319 #endif
    320         }
    321         AssertMsgReturn(    pVM->pgm.s.cHandyPages > 0
    322                         &&  pVM->pgm.s.cHandyPages <= RT_ELEMENTS(pVM->pgm.s.aHandyPages),
    323                         ("%u\n", pVM->pgm.s.cHandyPages),
    324                         VERR_INTERNAL_ERROR);
    325     }
    326     else if (pVM->pgm.s.cHandyPages - 1 <= (RT_ELEMENTS(pVM->pgm.s.aHandyPages) / 4) * 3) /* 75% */
    327     {
    328         VM_FF_SET(pVM, VM_FF_PGM_NEED_HANDY_PAGES);
     322            AssertMsgReturn(    pVM->pgm.s.cHandyPages > 0
     323                            &&  pVM->pgm.s.cHandyPages <= RT_ELEMENTS(pVM->pgm.s.aHandyPages),
     324                            ("%u\n", pVM->pgm.s.cHandyPages),
     325                            VERR_INTERNAL_ERROR);
     326        }
     327        else
     328        {
     329            if (pVM->pgm.s.cHandyPages <= PGM_HANDY_PAGES_SET_FF)
     330                VM_FF_SET(pVM, VM_FF_PGM_NEED_HANDY_PAGES);
    329331#ifndef IN_RING3
    330         if (pVM->pgm.s.cHandyPages - 1 <= RT_ELEMENTS(pVM->pgm.s.aHandyPages) / 2)
    331         {
    332             Log(("PGM: VM_FF_TO_R3 - cHandyPages=%u out of %u\n", pVM->pgm.s.cHandyPages - 1, RT_ELEMENTS(pVM->pgm.s.aHandyPages)));
    333             VM_FF_SET(pVM, VM_FF_TO_R3);
    334         }
    335 #endif
     332            if (pVM->pgm.s.cHandyPages <= PGM_HANDY_PAGES_RZ_TO_R3)
     333            {
     334                Log(("PGM: VM_FF_TO_R3 - cHandyPages=%u out of %u\n", pVM->pgm.s.cHandyPages, RT_ELEMENTS(pVM->pgm.s.aHandyPages)));
     335                VM_FF_SET(pVM, VM_FF_TO_R3);
     336            }
     337#endif
     338        }
    336339    }
    337340
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