VirtualBox

Changeset 18617 in vbox


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

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

Location:
trunk
Files:
16 edited

Legend:

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

    r18263 r18617  
    4848 * @{
    4949 */
    50 
    5150/** Initial address of Hypervisor Memory Area.
    5251 * MUST BE PAGE TABLE ALIGNED! */
     
    7978/** The default size of the below 4GB RAM hole. */
    8079#define MM_RAM_HOLE_SIZE_DEFAULT    (512U * _1M)
     80/** @} */
    8181
     82
     83/** @defgroup   grp_vbox_param_pgm  Page Manager Parameters
     84 * @ingroup grp_vbox_param
     85 * @{
     86 */
     87/** The number of handy pages.
     88 * This should be a power of two. */
     89#define PGM_HANDY_PAGES             128
     90/** The threshold at which allocation of more handy pages is flagged. */
     91#define PGM_HANDY_PAGES_SET_FF      32
     92/** The threshold at which we will allocate more when in ring-3.
     93 * This is must be smaller than both PGM_HANDY_PAGES_SET_FF and
     94 * PGM_HANDY_PAGES_MIN. */
     95#define PGM_HANDY_PAGES_R3_ALLOC    8
     96/** The threshold at which we will allocate more when in ring-0 or raw mode.
     97 * The idea is that we should never go below this threshold while in ring-0 or
     98 * raw mode because of PGM_HANDY_PAGES_RZ_TO_R3. However, should this happen and
     99 * we are actually out of memory, we will have 8 page to get out of whatever
     100 * code we're executing.
     101 *
     102 * This is must be smaller than both PGM_HANDY_PAGES_SET_FF and
     103 * PGM_HANDY_PAGES_MIN. */
     104#define PGM_HANDY_PAGES_RZ_ALLOC    8
     105/** The threshold at which we force return to R3 ASAP.
     106 * The idea is that this should be large enough to get out of any code and up to
     107 * the main EM loop when we are out of memory.
     108 * This must be less or equal to PGM_HANDY_PAGES_MIN. */
     109#define PGM_HANDY_PAGES_RZ_TO_R3    24
     110/** The minimum number of handy pages (after allocation).
     111 * This must be greater or equal to PGM_HANDY_PAGES_SET_FF.
     112 * Another name would be PGM_HANDY_PAGES_EXTRA_RESERVATION or _PARANOIA. :-) */
     113#define PGM_HANDY_PAGES_MIN         32
    82114/** @} */
    83115
     
    87119 * @{
    88120 */
    89 
    90121/** VMM stack size. */
    91122#define VMM_STACK_SIZE              8192U
    92 
    93123/** @} */
    94124
  • trunk/include/VBox/vm.h

    r17546 r18617  
    211211/** PGM needs to allocate handy pages. */
    212212#define VM_FF_PGM_NEED_HANDY_PAGES      RT_BIT_32(18)
     213/** PGM is out of memory.
     214 * Abandon all loops and code paths which can be resumed and get up to the EM
     215 * loops. */
     216#define VM_FF_PGM_NO_MEMORY             RT_BIT_32(19)
    213217/** Check the interupt and trap gates */
    214 #define VM_FF_TRPM_SYNC_IDT             RT_BIT_32(19)
     218#define VM_FF_TRPM_SYNC_IDT             RT_BIT_32(20)
    215219/** Check Guest's TSS ring 0 stack */
    216 #define VM_FF_SELM_SYNC_TSS             RT_BIT_32(20)
     220#define VM_FF_SELM_SYNC_TSS             RT_BIT_32(21)
    217221/** Check Guest's GDT table */
    218 #define VM_FF_SELM_SYNC_GDT             RT_BIT_32(21)
     222#define VM_FF_SELM_SYNC_GDT             RT_BIT_32(22)
    219223/** Check Guest's LDT table */
    220 #define VM_FF_SELM_SYNC_LDT             RT_BIT_32(22)
     224#define VM_FF_SELM_SYNC_LDT             RT_BIT_32(23)
    221225/** Inhibit interrupts pending. See EMGetInhibitInterruptsPC(). */
    222 #define VM_FF_INHIBIT_INTERRUPTS        RT_BIT_32(23)
     226#define VM_FF_INHIBIT_INTERRUPTS        RT_BIT_32(24)
    223227
    224228/** CSAM needs to scan the page that's being executed */
    225 #define VM_FF_CSAM_SCAN_PAGE            RT_BIT_32(24)
     229#define VM_FF_CSAM_SCAN_PAGE            RT_BIT_32(26)
    226230/** CSAM needs to do some homework. */
    227 #define VM_FF_CSAM_PENDING_ACTION       RT_BIT_32(25)
     231#define VM_FF_CSAM_PENDING_ACTION       RT_BIT_32(27)
    228232
    229233/** Force return to Ring-3. */
     
    242246/** High priority pre-execution actions. */
    243247#define VM_FF_HIGH_PRIORITY_PRE_MASK    (VM_FF_TERMINATE | VM_FF_DBGF | VM_FF_INTERRUPT_APIC | VM_FF_INTERRUPT_PIC | VM_FF_TIMER | VM_FF_DEBUG_SUSPEND \
    244                                         | VM_FF_PGM_SYNC_CR3 | VM_FF_PGM_SYNC_CR3_NON_GLOBAL | VM_FF_SELM_SYNC_TSS | VM_FF_TRPM_SYNC_IDT | VM_FF_SELM_SYNC_GDT | VM_FF_SELM_SYNC_LDT | VM_FF_PGM_NEED_HANDY_PAGES)
     248                                        | VM_FF_PGM_SYNC_CR3 | VM_FF_PGM_SYNC_CR3_NON_GLOBAL | VM_FF_SELM_SYNC_TSS | VM_FF_TRPM_SYNC_IDT | VM_FF_SELM_SYNC_GDT | VM_FF_SELM_SYNC_LDT | VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_PGM_NO_MEMORY)
    245249/** High priority pre raw-mode execution mask. */
    246 #define VM_FF_HIGH_PRIORITY_PRE_RAW_MASK (VM_FF_PGM_SYNC_CR3 | VM_FF_PGM_SYNC_CR3_NON_GLOBAL | VM_FF_SELM_SYNC_TSS | VM_FF_TRPM_SYNC_IDT | VM_FF_SELM_SYNC_GDT | VM_FF_SELM_SYNC_LDT | VM_FF_PGM_NEED_HANDY_PAGES \
    247                                         | VM_FF_INHIBIT_INTERRUPTS)
     250#define VM_FF_HIGH_PRIORITY_PRE_RAW_MASK (VM_FF_PGM_SYNC_CR3 | VM_FF_PGM_SYNC_CR3_NON_GLOBAL | VM_FF_SELM_SYNC_TSS | VM_FF_TRPM_SYNC_IDT | VM_FF_SELM_SYNC_GDT | VM_FF_SELM_SYNC_LDT \
     251                                         | VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_INHIBIT_INTERRUPTS | VM_FF_PGM_NO_MEMORY)
    248252/** High priority post-execution actions. */
    249 #define VM_FF_HIGH_PRIORITY_POST_MASK   (VM_FF_PDM_CRITSECT | VM_FF_CSAM_PENDING_ACTION)
     253#define VM_FF_HIGH_PRIORITY_POST_MASK   (VM_FF_PDM_CRITSECT | VM_FF_CSAM_PENDING_ACTION | VM_FF_PGM_NO_MEMORY)
    250254/** Normal priority post-execution actions. */
    251 #define VM_FF_NORMAL_PRIORITY_POST_MASK (VM_FF_TERMINATE | VM_FF_DBGF | VM_FF_RESET | VM_FF_CSAM_SCAN_PAGE)
     255#define VM_FF_NORMAL_PRIORITY_POST_MASK (VM_FF_TERMINATE | VM_FF_DBGF | VM_FF_RESET | VM_FF_CSAM_SCAN_PAGE | VM_FF_PGM_NO_MEMORY)
    252256/** Normal priority actions. */
    253257#define VM_FF_NORMAL_PRIORITY_MASK      (VM_FF_REQUEST | VM_FF_PDM_QUEUES | VM_FF_PDM_DMA | VM_FF_REM_HANDLER_NOTIFY)
    254 /** Flags to check before resuming guest execution. */
     258/** Flags to clear before resuming guest execution. */
    255259#define VM_FF_RESUME_GUEST_MASK         (VM_FF_TO_R3)
     260/** Flags that causes the HWACCM loops to go back to ring-3. */
     261#define VM_FF_HWACCM_TO_R3_MASK         (VM_FF_TO_R3 | VM_FF_TIMER | VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_PGM_NO_MEMORY)
    256262/** All the forced flags. */
    257263#define VM_FF_ALL_MASK                  (~0U)
    258264/** All the forced flags. */
    259 #define VM_FF_ALL_BUT_RAW_MASK          (~(VM_FF_HIGH_PRIORITY_PRE_RAW_MASK | VM_FF_CSAM_PENDING_ACTION | VM_FF_PDM_CRITSECT))
     265#define VM_FF_ALL_BUT_RAW_MASK          (~(VM_FF_HIGH_PRIORITY_PRE_RAW_MASK | VM_FF_CSAM_PENDING_ACTION | VM_FF_PDM_CRITSECT) | VM_FF_PGM_NO_MEMORY)
    260266
    261267/** @} */
     
    357363#else
    358364# define VMCPU_FF_ISPENDING(pVM, idCpu, fFlags) VM_FF_ISPENDING(pVM, fFlags)
     365#endif
     366
     367/** @def VM_FF_ISPENDING
     368 * Checks if one or more force action in the specified set is pending while one
     369 * or more other ones are not.
     370 *
     371 * @param   pVM     VM Handle.
     372 * @param   fFlags  The flags to check for.
     373 * @param   fExcpt  The flags that should not be set.
     374 */
     375#define VM_FF_IS_PENDING_EXCEPT(pVM, fFlags, fExcpt)            ( ((pVM)->fForcedActions & (fFlags)) && !((pVM)->fForcedActions & (fExcpt)) )
     376
     377/** @def VMCPU_FF_IS_PENDING_EXCEPT
     378 * Checks if one or more force action in the specified set is pending for given
     379 * VCPU while one or more other ones are not.
     380 *
     381 * @param   pVM     VM Handle.
     382 * @param   idCpu   Virtual CPU ID.
     383 * @param   fFlags  The flags to check for.
     384 * @param   fExcpt  The flags that should not be set.
     385 */
     386#ifdef VBOX_WITH_SMP_GUESTS
     387# define VMCPU_FF_IS_PENDING_EXCEPT(pVM, idCpu, fFlags, fExcpt) ( ((pVM)->aCpu[idCpu].fForcedActions & (fFlags)) && !((pVM)->aCpu[idCpu].fForcedActions & (fExcpt)) )
     388#else
     389# define VMCPU_FF_IS_PENDING_EXCEPT(pVM, idCpu, fFlags, fExcpt) VM_FF_ISPENDING(pVM, fFlags, fExcpt)
    359390#endif
    360391
  • trunk/src/VBox/VMM/EM.cpp

    r18343 r18617  
    755755                case VINF_EM_OFF:
    756756                case VINF_EM_RESET:
     757                case VINF_EM_NO_MEMORY:
    757758                case VINF_EM_RAW_STALE_SELECTOR:
    758759                case VINF_EM_RAW_IRET_TRAP:
     
    10161017        {
    10171018            rc = emR3RawForcedActions(pVM, pCtx);
    1018             if (RT_FAILURE(rc))
     1019            if (rc != VINF_SUCCESS)
    10191020                return rc;
    10201021        }
     
    10901091    {
    10911092        rc = emR3RawForcedActions(pVM, pCtx);
    1092         if (RT_FAILURE(rc))
     1093        if (rc != VINF_SUCCESS)
    10931094            return rc;
    10941095    }
     
    11251126
    11261127
    1127 void emR3SingleStepExecRaw(PVM pVM, uint32_t cIterations)
     1128int emR3SingleStepExecRaw(PVM pVM, uint32_t cIterations)
    11281129{
    1129     EMSTATE  enmOldState = pVM->em.s.enmState;
    1130 
    1131     pVM->em.s.enmState = EMSTATE_DEBUG_GUEST_RAW;
     1130    int     rc          = VINF_SUCCESS;
     1131    EMSTATE enmOldState = pVM->em.s.enmState;
     1132    pVM->em.s.enmState  = EMSTATE_DEBUG_GUEST_RAW;
    11321133
    11331134    Log(("Single step BEGIN:\n"));
     
    11361137        DBGFR3PrgStep(pVM);
    11371138        DBGFR3DisasInstrCurrentLog(pVM, "RSS: ");
    1138         emR3RawStep(pVM);
    1139     }
    1140     Log(("Single step END:\n"));
     1139        rc = emR3RawStep(pVM);
     1140        if (rc != VINF_SUCCESS)
     1141            break;
     1142    }
     1143    Log(("Single step END: rc=%Rrc\n", rc));
    11411144    CPUMSetGuestEFlags(pVM, CPUMGetGuestEFlags(pVM) & ~X86_EFL_TF);
    11421145    pVM->em.s.enmState = enmOldState;
     1146    return rc;
    11431147}
    11441148
     
    11461150static int emR3SingleStepExecHwAcc(PVM pVM, RTCPUID idCpu, uint32_t cIterations)
    11471151{
    1148     EMSTATE  enmOldState = pVM->em.s.enmState;
    1149 
    1150     pVM->em.s.enmState = EMSTATE_DEBUG_GUEST_HWACC;
     1152    int     rc          = VINF_SUCCESS;
     1153    EMSTATE enmOldState = pVM->em.s.enmState;
     1154    pVM->em.s.enmState  = EMSTATE_DEBUG_GUEST_HWACC;
    11511155
    11521156    Log(("Single step BEGIN:\n"));
     
    11551159        DBGFR3PrgStep(pVM);
    11561160        DBGFR3DisasInstrCurrentLog(pVM, "RSS: ");
    1157         emR3HwAccStep(pVM, idCpu);
    1158         if (!HWACCMR3CanExecuteGuest(pVM, pVM->em.s.pCtx))
    1159             break;
    1160     }
    1161     Log(("Single step END:\n"));
     1161        rc = emR3HwAccStep(pVM, idCpu);
     1162        if (    rc != VINF_SUCCESS
     1163            ||  !HWACCMR3CanExecuteGuest(pVM, pVM->em.s.pCtx))
     1164            break;
     1165    }
     1166    Log(("Single step END: rc=%Rrc\n", rc));
    11621167    CPUMSetGuestEFlags(pVM, CPUMGetGuestEFlags(pVM) & ~X86_EFL_TF);
    11631168    pVM->em.s.enmState = enmOldState;
    1164     return VINF_EM_RESCHEDULE_REM;
     1169    return rc == VINF_SUCCESS ? VINF_EM_RESCHEDULE_REM : rc;
    11651170}
    11661171
     
    24262431        case VINF_EM_HALT:
    24272432        case VINF_EM_RESUME:
     2433        case VINF_EM_NO_MEMORY:
    24282434        case VINF_EM_RESCHEDULE:
    24292435        case VINF_EM_RESCHEDULE_REM:
     
    24792485 * Check for pending raw actions
    24802486 *
    2481  * @returns VBox status code.
     2487 * @returns VBox status code. May return VINF_EM_NO_MEMORY but none of the other
     2488 *          EM statuses.
    24822489 * @param   pVM         The VM to operate on.
    24832490 */
     
    24932500 * This function is called when any FFs in the VM_FF_HIGH_PRIORITY_PRE_RAW_MASK is pending.
    24942501 *
    2495  * @returns VBox status code.
    2496  *          Only the normal success/failure stuff, no VINF_EM_*.
     2502 * @returns VBox status code. May return VINF_EM_NO_MEMORY but none of the other
     2503 *          EM statuses.
    24972504 * @param   pVM         The VM handle.
    24982505 * @param   pCtx        The guest CPUM register context.
     
    25192526     * Sync IDT.
    25202527     */
    2521     if (VM_FF_ISSET(pVM, VM_FF_TRPM_SYNC_IDT))
     2528    if (VM_FF_ISPENDING(pVM, VM_FF_TRPM_SYNC_IDT))
    25222529    {
    25232530        int rc = TRPMR3SyncIDT(pVM);
     
    25292536     * Sync TSS.
    25302537     */
    2531     if (VM_FF_ISSET(pVM, VM_FF_SELM_SYNC_TSS))
     2538    if (VM_FF_ISPENDING(pVM, VM_FF_SELM_SYNC_TSS))
    25322539    {
    25332540        int rc = SELMR3SyncTSS(pVM);
     
    25552562        {
    25562563            if (rc != VINF_PGM_SYNC_CR3)
     2564            {
     2565                AssertLogRelMsgReturn(RT_FAILURE(rc), ("%Rrc\n", rc), VERR_IPE_UNEXPECTED_INFO_STATUS);
    25572566                return rc;
     2567            }
    25582568            rc = PGMSyncCR3(pVM, pCtx->cr0, pCtx->cr3, pCtx->cr4, VM_FF_ISSET(pVM, VM_FF_PGM_SYNC_CR3));
    25592569            if (RT_FAILURE(rc))
     
    25672577     * Allocate handy pages (just in case the above actions have consumed some pages).
    25682578     */
    2569     if (VM_FF_ISSET(pVM, VM_FF_PGM_NEED_HANDY_PAGES))
     2579    if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_PGM_NEED_HANDY_PAGES, VM_FF_PGM_NO_MEMORY))
    25702580    {
    25712581        int rc = PGMR3PhysAllocateHandyPages(pVM);
     
    25732583            return rc;
    25742584    }
     2585
     2586    /*
     2587     * Check whether we're out of memory now.
     2588     *
     2589     * This may stem from some of the above actions or operations that has been executed
     2590     * since we ran FFs. The allocate handy pages must for instance always be followed by
     2591     * this check.
     2592     */
     2593    if (VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY))
     2594        return VINF_EM_NO_MEMORY;
    25752595
    25762596    return VINF_SUCCESS;
     
    26362656        {
    26372657            rc = emR3RawForcedActions(pVM, pCtx);
    2638             if (RT_FAILURE(rc))
     2658            if (rc != VINF_SUCCESS)
    26392659                break;
    26402660        }
     
    26652685            {
    26662686                rc = emR3RawForcedActions(pVM, pCtx);
    2667                 if (RT_FAILURE(rc))
     2687                if (rc != VINF_SUCCESS)
    26682688                    break;
    26692689            }
     
    27762796#endif
    27772797        STAM_PROFILE_ADV_STOP(&pVM->em.s.StatRAWTail, d);
    2778         if (VM_FF_ISPENDING(pVM, ~VM_FF_HIGH_PRIORITY_PRE_RAW_MASK))
     2798        if (VM_FF_ISPENDING(pVM, ~VM_FF_HIGH_PRIORITY_PRE_RAW_MASK | VM_FF_PGM_NO_MEMORY))
    27792799        {
    27802800            Assert(pCtx->eflags.Bits.u1VM || (pCtx->ss & X86_SEL_RPL) != 1);
     
    28432863
    28442864        /*
    2845          * Check various preconditions.
    2846          */
    2847         VM_FF_CLEAR(pVM, (VM_FF_SELM_SYNC_GDT | VM_FF_SELM_SYNC_LDT | VM_FF_TRPM_SYNC_IDT | VM_FF_SELM_SYNC_TSS));
    2848 
    2849         /*
    28502865         * Process high priority pre-execution raw-mode FFs.
    28512866         */
     2867        VM_FF_CLEAR(pVM, (VM_FF_SELM_SYNC_GDT | VM_FF_SELM_SYNC_LDT | VM_FF_TRPM_SYNC_IDT | VM_FF_SELM_SYNC_TSS)); /* not relevant in HWACCM mode; shouldn't be set really. */
    28522868        if (VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_PRE_RAW_MASK))
    28532869        {
    28542870            rc = emR3RawForcedActions(pVM, pCtx);
    2855             if (RT_FAILURE(rc))
     2871            if (rc != VINF_SUCCESS)
    28562872                break;
    28572873        }
     
    30853101static int emR3HighPriorityPostForcedActions(PVM pVM, int rc)
    30863102{
    3087     if (VM_FF_ISSET(pVM, VM_FF_PDM_CRITSECT))
     3103    if (VM_FF_ISPENDING(pVM, VM_FF_PDM_CRITSECT))
    30883104        PDMR3CritSectFF(pVM);
    30893105
    3090     if (VM_FF_ISSET(pVM, VM_FF_CSAM_PENDING_ACTION))
     3106    if (VM_FF_ISPENDING(pVM, VM_FF_CSAM_PENDING_ACTION))
    30913107        CSAMR3DoPendingAction(pVM);
     3108
     3109    if (VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY))
     3110    {
     3111        if (    rc > VINF_EM_NO_MEMORY
     3112            &&  rc <= VINF_EM_LAST)
     3113            rc = VINF_EM_NO_MEMORY;
     3114    }
    30923115
    30933116    return rc;
     
    31373160         * Termination request.
    31383161         */
    3139         if (VM_FF_ISSET(pVM, VM_FF_TERMINATE))
     3162        if (VM_FF_ISPENDING(pVM, VM_FF_TERMINATE))
    31403163        {
    31413164            Log2(("emR3ForcedActions: returns VINF_EM_TERMINATE\n"));
     
    31473170         * Debugger Facility polling.
    31483171         */
    3149         if (VM_FF_ISSET(pVM, VM_FF_DBGF))
     3172        if (VM_FF_ISPENDING(pVM, VM_FF_DBGF))
    31503173        {
    31513174            rc2 = DBGFR3VMMForcedAction(pVM);
     
    31563179         * Postponed reset request.
    31573180         */
    3158         if (VM_FF_ISSET(pVM, VM_FF_RESET))
     3181        if (VM_FF_ISPENDING(pVM, VM_FF_RESET))
    31593182        {
    31603183            rc2 = VMR3Reset(pVM);
     
    31663189         * CSAM page scanning.
    31673190         */
    3168         if (VM_FF_ISSET(pVM, VM_FF_CSAM_SCAN_PAGE))
     3191        if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_CSAM_SCAN_PAGE, VM_FF_PGM_NO_MEMORY))
    31693192        {
    31703193            PCPUMCTX pCtx = pVM->em.s.pCtx;
     
    31773200        }
    31783201
     3202        /*
     3203         * Out of memory? Putting this after CSAM as it may in theory cause us to run out of memory.
     3204         */
     3205        if (VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY))
     3206        {
     3207            rc2 = VINF_EM_NO_MEMORY;
     3208            UPDATE_RC();
     3209            if (rc == VINF_EM_NO_MEMORY)
     3210                return rc;
     3211        }
     3212
    31793213        /* check that we got them all  */
    3180         Assert(!(VM_FF_NORMAL_PRIORITY_POST_MASK & ~(VM_FF_TERMINATE | VM_FF_DBGF | VM_FF_RESET | VM_FF_CSAM_SCAN_PAGE)));
     3214        Assert(!(VM_FF_NORMAL_PRIORITY_POST_MASK & ~(VM_FF_TERMINATE | VM_FF_DBGF | VM_FF_RESET | VM_FF_CSAM_SCAN_PAGE | VM_FF_PGM_NO_MEMORY)));
    31813215    }
    31823216
     
    31853219     * (Executed in no particular order.)
    31863220     */
    3187     if (VM_FF_ISPENDING(pVM, VM_FF_NORMAL_PRIORITY_MASK))
     3221    if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_NORMAL_PRIORITY_MASK, VM_FF_PGM_NO_MEMORY))
    31883222    {
    31893223        /*
    31903224         * PDM Queues are pending.
    31913225         */
    3192         if (VM_FF_ISSET(pVM, VM_FF_PDM_QUEUES))
     3226        if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_PDM_QUEUES, VM_FF_PGM_NO_MEMORY))
    31933227            PDMR3QueueFlushAll(pVM);
    31943228
     
    31963230         * PDM DMA transfers are pending.
    31973231         */
    3198         if (VM_FF_ISSET(pVM, VM_FF_PDM_DMA))
     3232        if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_PDM_DMA, VM_FF_PGM_NO_MEMORY))
    31993233            PDMR3DmaRun(pVM);
    32003234
     
    32023236         * Requests from other threads.
    32033237         */
    3204         if (VM_FF_ISSET(pVM, VM_FF_REQUEST))
     3238        if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_REQUEST, VM_FF_PGM_NO_MEMORY))
    32053239        {
    32063240            rc2 = VMR3ReqProcessU(pVM->pUVM, VMREQDEST_ANY);
     
    32153249
    32163250        /* Replay the handler notification changes. */
    3217         if (VM_FF_ISSET(pVM, VM_FF_REM_HANDLER_NOTIFY))
     3251        if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_REM_HANDLER_NOTIFY, VM_FF_PGM_NO_MEMORY))
    32183252            REMR3ReplayHandlerNotifications(pVM);
    32193253
     
    32223256    }
    32233257
     3258#if 1 /** @todo this is all dead now, remove after the no-memory changes has been committed. */
    32243259    /*
    32253260     * Execute polling function ever so often.
     
    32293264    if (!((++cLast) % 4))
    32303265        PDMR3Poll(pVM);
     3266#endif
    32313267
    32323268    /*
     
    32393275         * Timers before interrupts.
    32403276         */
    3241         if (VM_FF_ISSET(pVM, VM_FF_TIMER))
     3277        if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_TIMER, VM_FF_PGM_NO_MEMORY))
    32423278            TMR3TimerQueuesDo(pVM);
    32433279
     
    32453281         * The instruction following an emulated STI should *always* be executed!
    32463282         */
    3247         if (VM_FF_ISSET(pVM, VM_FF_INHIBIT_INTERRUPTS))
     3283        if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_INHIBIT_INTERRUPTS, VM_FF_PGM_NO_MEMORY))
    32483284        {
    32493285            Log(("VM_FF_EMULATED_STI at %RGv successor %RGv\n", (RTGCPTR)CPUMGetGuestRIP(pVM), EMGetInhibitInterruptsPC(pVM)));
     
    32683304         * Interrupts.
    32693305         */
    3270         if (    !VM_FF_ISSET(pVM, VM_FF_INHIBIT_INTERRUPTS)
     3306        if (    !VM_FF_ISPENDING(pVM, VM_FF_INHIBIT_INTERRUPTS | VM_FF_PGM_NO_MEMORY)
    32713307            &&  (!rc || rc >= VINF_EM_RESCHEDULE_HWACC)
    32723308            &&  !TRPMHasTrap(pVM) /* an interrupt could already be scheduled for dispatching in the recompiler. */
     
    32953331         * Allocate handy pages.
    32963332         */
    3297         if (VM_FF_ISSET(pVM, VM_FF_PGM_NEED_HANDY_PAGES))
     3333        if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_PGM_NEED_HANDY_PAGES, VM_FF_PGM_NO_MEMORY))
    32983334        {
    32993335            rc2 = PGMR3PhysAllocateHandyPages(pVM);
     
    33043340         * Debugger Facility request.
    33053341         */
    3306         if (VM_FF_ISSET(pVM, VM_FF_DBGF))
     3342        if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_DBGF, VM_FF_PGM_NO_MEMORY))
    33073343        {
    33083344            rc2 = DBGFR3VMMForcedAction(pVM);
     
    33133349         * Termination request.
    33143350         */
    3315         if (VM_FF_ISSET(pVM, VM_FF_TERMINATE))
     3351        if (VM_FF_ISPENDING(pVM, VM_FF_TERMINATE))
    33163352        {
    33173353            Log2(("emR3ForcedActions: returns VINF_EM_TERMINATE\n"));
     
    33203356        }
    33213357
     3358        /*
     3359         * Out of memory? Since most of our fellow high priority actions may cause us
     3360         * to run out of memory, we're employing VM_FF_IS_PENDING_EXCEPT and putting this
     3361         * at the end rather than the start. Also, VM_FF_TERMINATE has higher priority
     3362         * than us since we can terminate without allocating more memory.
     3363         */
     3364        if (VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY))
     3365        {
     3366            rc2 = VINF_EM_NO_MEMORY;
     3367            UPDATE_RC();
     3368            if (rc == VINF_EM_NO_MEMORY)
     3369                return rc;
     3370        }
     3371
    33223372#ifdef DEBUG
    33233373        /*
    33243374         * Debug, pause the VM.
    33253375         */
    3326         if (VM_FF_ISSET(pVM, VM_FF_DEBUG_SUSPEND))
     3376        if (VM_FF_ISPENDING(pVM, VM_FF_DEBUG_SUSPEND))
    33273377        {
    33283378            VM_FF_CLEAR(pVM, VM_FF_DEBUG_SUSPEND);
     
    33333383#endif
    33343384        /* check that we got them all  */
    3335         Assert(!(VM_FF_HIGH_PRIORITY_PRE_MASK & ~(VM_FF_TIMER | VM_FF_INTERRUPT_APIC | VM_FF_INTERRUPT_PIC | VM_FF_DBGF | VM_FF_PGM_SYNC_CR3 | VM_FF_PGM_SYNC_CR3_NON_GLOBAL | VM_FF_SELM_SYNC_TSS | VM_FF_TRPM_SYNC_IDT | VM_FF_SELM_SYNC_GDT | VM_FF_SELM_SYNC_LDT | VM_FF_TERMINATE | VM_FF_DEBUG_SUSPEND | VM_FF_INHIBIT_INTERRUPTS | VM_FF_PGM_NEED_HANDY_PAGES)));
     3385        Assert(!(VM_FF_HIGH_PRIORITY_PRE_MASK & ~(VM_FF_TIMER | VM_FF_INTERRUPT_APIC | VM_FF_INTERRUPT_PIC | VM_FF_DBGF | VM_FF_PGM_SYNC_CR3 | VM_FF_PGM_SYNC_CR3_NON_GLOBAL | VM_FF_SELM_SYNC_TSS | VM_FF_TRPM_SYNC_IDT | VM_FF_SELM_SYNC_GDT | VM_FF_SELM_SYNC_LDT | VM_FF_TERMINATE | VM_FF_DEBUG_SUSPEND | VM_FF_INHIBIT_INTERRUPTS | VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_PGM_NO_MEMORY)));
    33363386    }
    33373387
     
    35313581                    return rc;
    35323582
     3583
     3584                /*
     3585                 * Out of memory, suspend the VM and stuff.
     3586                 */
     3587                case VINF_EM_NO_MEMORY:
     3588                    /** @todo Take the out of memory fun from here and up. May have to add another
     3589                     *        VM state, but hope not for 2.2 ... */
     3590                    Log2(("EMR3ExecuteVM: VINF_EM_NO_MEMORY: %d -> %d\n", pVM->em.s.enmState, EMSTATE_SUSPENDED));
     3591                    pVM->em.s.enmState = EMSTATE_SUSPENDED;
     3592                    break;
     3593
    35333594                /*
    35343595                 * Guest debug events.
  • trunk/src/VBox/VMM/PGM.cpp

    r18353 r18617  
    640640
    641641#ifdef VBOX_WITH_DEBUGGER
    642 /** @todo all but the two last commands must be converted to 'info'. */
     642/** @todo Convert the first two commands to 'info' items. */
    643643static DECLCALLBACK(int)  pgmR3CmdRam(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    644644static DECLCALLBACK(int)  pgmR3CmdMap(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
     645static DECLCALLBACK(int)  pgmR3CmdError(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    645646static DECLCALLBACK(int)  pgmR3CmdSync(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
    646647static DECLCALLBACK(int)  pgmR3CmdSyncAlways(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
     
    655656*******************************************************************************/
    656657#ifdef VBOX_WITH_DEBUGGER
     658/** Argument descriptors for '.pgmerror' and '.pgmerroroff'. */
     659static const DBGCVARDESC g_aPgmErrorArgs[] =
     660{
     661    /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
     662    {  0,           1,          DBGCVAR_CAT_STRING,     0,                              "where",        "Error injection location." },
     663};
     664
    657665/** Command descriptors. */
    658666static const DBGCCMD    g_aCmds[] =
    659667{
    660     /* pszCmd,      cArgsMin, cArgsMax, paArgDesc,          cArgDescs,                  pResultDesc,        fFlags,     pfnHandler          pszSyntax,          ....pszDescription */
    661     { "pgmram",     0,        0,        NULL,               0,                          NULL,               0,          pgmR3CmdRam,        "",                     "Display the ram ranges." },
    662     { "pgmmap",     0,        0,        NULL,               0,                          NULL,               0,          pgmR3CmdMap,        "",                     "Display the mapping ranges." },
    663     { "pgmsync",    0,        0,        NULL,               0,                          NULL,               0,          pgmR3CmdSync,       "",                     "Sync the CR3 page." },
     668    /* pszCmd,  cArgsMin, cArgsMax, paArgDesc,          cArgDescs,                  pResultDesc,        fFlags,     pfnHandler          pszSyntax,          ....pszDescription */
     669    { "pgmram",        0, 0,        NULL,               0,                          NULL,               0,          pgmR3CmdRam,        "",                     "Display the ram ranges." },
     670    { "pgmmap",        0, 0,        NULL,               0,                          NULL,               0,          pgmR3CmdMap,        "",                     "Display the mapping ranges." },
     671    { "pgmsync",       0, 0,        NULL,               0,                          NULL,               0,          pgmR3CmdSync,       "",                     "Sync the CR3 page." },
     672    { "pgmerror",      0, 1,        &g_aPgmErrorArgs[0],1,                          NULL,               0,          pgmR3CmdError,      "",                     "Enables inject runtime of errors into parts of PGM." },
     673    { "pgmerroroff",   0, 1,        &g_aPgmErrorArgs[0],1,                          NULL,               0,          pgmR3CmdError,      "",                     "Disables inject runtime errors into parts of PGM." },
    664674#ifdef VBOX_STRICT
    665     { "pgmassertcr3",  0,     0,        NULL,               0,                          NULL,               0,          pgmR3CmdAssertCR3,  "",                     "Check the shadow CR3 mapping." },
     675    { "pgmassertcr3",  0, 0,        NULL,               0,                          NULL,               0,          pgmR3CmdAssertCR3,  "",                     "Check the shadow CR3 mapping." },
    666676#endif
    667     { "pgmsyncalways", 0,     0,        NULL,               0,                          NULL,               0,          pgmR3CmdSyncAlways, "",                     "Toggle permanent CR3 syncing." },
     677    { "pgmsyncalways", 0, 0,        NULL,               0,                          NULL,               0,          pgmR3CmdSyncAlways, "",                     "Toggle permanent CR3 syncing." },
    668678};
    669679#endif
     
    12831293    if (RT_SUCCESS(rc))
    12841294    {
    1285         pVM->pgm.s.pvZeroPgGC = MMHyperR3ToRC(pVM, pVM->pgm.s.pvZeroPgR3);
     1295        pVM->pgm.s.pvZeroPgRC = MMHyperR3ToRC(pVM, pVM->pgm.s.pvZeroPgR3);
    12861296        pVM->pgm.s.pvZeroPgR0 = MMHyperR3ToR0(pVM, pVM->pgm.s.pvZeroPgR3);
    12871297        pVM->pgm.s.HCPhysZeroPg = MMR3HyperHCVirt2HCPhys(pVM, pVM->pgm.s.pvZeroPgR3);
     
    46924702
    46934703/**
     4704 * The '.pgmerror' and '.pgmerroroff' commands.
     4705 *
     4706 * @returns VBox status.
     4707 * @param   pCmd        Pointer to the command descriptor (as registered).
     4708 * @param   pCmdHlp     Pointer to command helper functions.
     4709 * @param   pVM         Pointer to the current VM (if any).
     4710 * @param   paArgs      Pointer to (readonly) array of arguments.
     4711 * @param   cArgs       Number of arguments in the array.
     4712 */
     4713static DECLCALLBACK(int)  pgmR3CmdError(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
     4714{
     4715    /*
     4716     * Validate input.
     4717     */
     4718    if (!pVM)
     4719        return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The command requires a VM to be selected.\n");
     4720    AssertReturn(cArgs == 0 || (cArgs == 1 && paArgs[0].enmType == DBGCVAR_TYPE_STRING),
     4721                 pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Hit bug in the parser.\n"));
     4722
     4723    if (!cArgs)
     4724    {
     4725        /*
     4726         * Print the list of error injection locations with status.
     4727         */
     4728        pCmdHlp->pfnPrintf(pCmdHlp, NULL, "PGM error inject locations:\n");
     4729        pCmdHlp->pfnPrintf(pCmdHlp, NULL, "  handy - %RTbool\n", pVM->pgm.s.fErrInjHandyPages);
     4730    }
     4731    else
     4732    {
     4733
     4734        /*
     4735         * String switch on where to inject the error.
     4736         */
     4737        bool const  fNewState = !strcmp(pCmd->pszCmd, "pgmerror");
     4738        const char *pszWhere = paArgs[0].u.pszString;
     4739        if (!strcmp(pszWhere, "handy"))
     4740            ASMAtomicWriteBool(&pVM->pgm.s.fErrInjHandyPages, fNewState);
     4741        else
     4742            return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Invalid 'where' value: %s.\n", pszWhere);
     4743        pCmdHlp->pfnPrintf(pCmdHlp, NULL, "done\n");
     4744    }
     4745    return VINF_SUCCESS;
     4746}
     4747
     4748
     4749/**
    46944750 * The '.pgmsync' command.
    46954751 *
  • trunk/src/VBox/VMM/PGMInternal.h

    r18604 r18617  
    25662566    RTR0PTR                         pvZeroPgR0;
    25672567    /** The GC mapping of the zero page. */
    2568     RTGCPTR                         pvZeroPgGC;
     2568    RTGCPTR                         pvZeroPgRC;
    25692569#if GC_ARCH_BITS != 32
    25702570    uint32_t                        u32ZeroAlignment; /**< Alignment padding. */
     
    25842584     * (The current size of 32 pages, means 128 KB of handy memory.)
    25852585     */
    2586     GMMPAGEDESC                     aHandyPages[32];
     2586    GMMPAGEDESC                     aHandyPages[PGM_HANDY_PAGES];
     2587
     2588    /** @name   Error injection.
     2589     * @{ */
     2590    /** Inject handy page allocation errors pretending we're completely out of
     2591     * memory. */
     2592    bool volatile                   fErrInjHandyPages;
     2593    /** Padding. */
     2594    bool                            afReserved[7];
     2595    /** @} */
    25872596
    25882597    /** @name Release Statistics
  • trunk/src/VBox/VMM/PGMPhys.cpp

    r18433 r18617  
    33673367 * Response to VM_FF_PGM_NEED_HANDY_PAGES and VMMCALLHOST_PGM_ALLOCATE_HANDY_PAGES.
    33683368 *
     3369 * This function will also work the VM_FF_PGM_NO_MEMORY force action flag, to
     3370 * signal and clear the out of memory condition. When contracted, this API is
     3371 * used to try clear the condition when the user wants to resume.
     3372 *
    33693373 * @returns The following VBox status codes.
    3370  * @retval  VINF_SUCCESS on success. FF cleared.
    3371  * @retval  VINF_EM_NO_MEMORY if we're out of memory. The FF is not cleared in this case.
     3374 * @retval  VINF_SUCCESS on success. FFs cleared.
     3375 * @retval  VINF_EM_NO_MEMORY if we're out of memory. The FF is not cleared in
     3376 *          this case and it gets accompanied by VM_FF_PGM_NO_MEMORY.
    33723377 *
    33733378 * @param   pVM         The VM handle.
     3379 *
     3380 * @remarks The VINF_EM_NO_MEMORY status is for the benefit of the FF processing
     3381 *          in EM.cpp and shouldn't be propagated outside TRPM, HWACCM, EM and
     3382 *          pgmPhysEnsureHandyPage.
    33743383 */
    33753384VMMR3DECL(int) PGMR3PhysAllocateHandyPages(PVM pVM)
     
    34003409    }
    34013410
    3402     /*
    3403      * Clear the pages.
    3404      */
    34053411    if (RT_SUCCESS(rc))
    34063412    {
     3413        AssertMsg(rc == VINF_SUCCESS, ("%Rrc\n", rc));
     3414        Assert(pVM->pgm.s.cHandyPages > 0);
     3415        VM_FF_CLEAR(pVM, VM_FF_PGM_NEED_HANDY_PAGES);
     3416        VM_FF_CLEAR(pVM, VM_FF_PGM_NO_MEMORY);
     3417
     3418        /*
     3419         * Clear the pages.
     3420         */
    34073421        while (iClear < pVM->pgm.s.cHandyPages)
    34083422        {
     
    34153429            Log3(("PGMR3PhysAllocateHandyPages: idPage=%#x HCPhys=%RGp\n", pPage->idPage, pPage->HCPhysGCPhys));
    34163430        }
    3417 
    3418         VM_FF_CLEAR(pVM, VM_FF_PGM_NEED_HANDY_PAGES);
    34193431    }
    34203432    else
    34213433    {
     3434        /*
     3435         * We should never get here unless there is a genuine shortage of
     3436         * memory (or some internal error). Flag the error so the VM can be
     3437         * suspended ASAP and the user informed. If we're totally out of
     3438         * handy pages we will return failure.
     3439         */
     3440        /* Report the failure. */
    34223441        LogRel(("PGM: Failed to procure handy pages; rc=%Rrc rcAlloc=%Rrc rcSeed=%Rrc cHandyPages=%#x\n"
    34233442                "     cAllPages=%#x cPrivatePages=%#x cSharedPages=%#x cZeroPages=%#x\n",
     
    34283447                pVM->pgm.s.cSharedPages,
    34293448                pVM->pgm.s.cZeroPages));
    3430 #if 1
    3431         for (uint32_t i = 0; i < RT_ELEMENTS(pVM->pgm.s.aHandyPages); i++)
    3432         {
    3433             LogRel(("PGM: aHandyPages[#%#04x] = {.HCPhysGCPhys=%RHp, .idPage=%#08x, .idSharedPage=%#08x}\n",
    3434                     i, pVM->pgm.s.aHandyPages[i].HCPhysGCPhys, pVM->pgm.s.aHandyPages[i].idPage,
    3435                     pVM->pgm.s.aHandyPages[i].idSharedPage));
    3436             uint32_t const idPage = pVM->pgm.s.aHandyPages[i].idPage;
    3437             if (idPage != NIL_GMM_PAGEID)
     3449        if (    rc != VERR_NO_MEMORY
     3450            &&  rc != VERR_LOCK_FAILED)
     3451        {
     3452            for (uint32_t i = 0; i < RT_ELEMENTS(pVM->pgm.s.aHandyPages); i++)
    34383453            {
    3439                 for (PPGMRAMRANGE pRam = pVM->pgm.s.pRamRangesR3;
    3440                      pRam;
    3441                      pRam = pRam->pNextR3)
     3454                LogRel(("PGM: aHandyPages[#%#04x] = {.HCPhysGCPhys=%RHp, .idPage=%#08x, .idSharedPage=%#08x}\n",
     3455                        i, pVM->pgm.s.aHandyPages[i].HCPhysGCPhys, pVM->pgm.s.aHandyPages[i].idPage,
     3456                        pVM->pgm.s.aHandyPages[i].idSharedPage));
     3457                uint32_t const idPage = pVM->pgm.s.aHandyPages[i].idPage;
     3458                if (idPage != NIL_GMM_PAGEID)
    34423459                {
    3443                     uint32_t const cPages = pRam->cb >> PAGE_SHIFT;
    3444                     for (uint32_t iPage = 0; iPage < cPages; iPage++)
    3445                         if (PGM_PAGE_GET_PAGEID(&pRam->aPages[iPage]) == idPage)
    3446                             LogRel(("PGM: Used by %RGp %R[pgmpage] (%s)\n",
    3447                                     pRam->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT), &pRam->aPages[iPage], pRam->pszDesc));
     3460                    for (PPGMRAMRANGE pRam = pVM->pgm.s.pRamRangesR3;
     3461                         pRam;
     3462                         pRam = pRam->pNextR3)
     3463                    {
     3464                        uint32_t const cPages = pRam->cb >> PAGE_SHIFT;
     3465                        for (uint32_t iPage = 0; iPage < cPages; iPage++)
     3466                            if (PGM_PAGE_GET_PAGEID(&pRam->aPages[iPage]) == idPage)
     3467                                LogRel(("PGM: Used by %RGp %R[pgmpage] (%s)\n",
     3468                                        pRam->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT), &pRam->aPages[iPage], pRam->pszDesc));
     3469                    }
    34483470                }
    34493471            }
    34503472        }
    3451 #endif
    3452         rc = VERR_EM_NO_MEMORY;
    3453         //rc = VINF_EM_NO_MEMORY;
    3454         //VM_FF_SET(pVM, VM_FF_PGM_WE_ARE_SCREWED?);
    3455     }
    3456 
    3457 /** @todo Do proper VERR_EM_NO_MEMORY reporting. */
    3458     AssertMsg(   pVM->pgm.s.cHandyPages == RT_ELEMENTS(pVM->pgm.s.aHandyPages)
    3459               || rc != VINF_SUCCESS, ("%d rc=%Rrc\n", pVM->pgm.s.cHandyPages, rc));
     3473
     3474        /* Set the FFs and adjust rc. */
     3475        VM_FF_SET(pVM, VM_FF_PGM_NEED_HANDY_PAGES);
     3476        VM_FF_SET(pVM, VM_FF_PGM_NO_MEMORY);
     3477        if (    rc == VERR_NO_MEMORY
     3478            ||  rc == VERR_LOCK_FAILED)
     3479            rc = VINF_EM_NO_MEMORY;
     3480    }
    34603481
    34613482    pgmUnlock(pVM);
    3462     Assert(rc == VINF_SUCCESS || rc == VINF_EM_NO_MEMORY || rc == VERR_EM_NO_MEMORY);
    34633483    return rc;
    34643484}
     
    35203540     * Make sure it's not in the handy page array.
    35213541     */
    3522     uint32_t i = pVM->pgm.s.cHandyPages;
    3523     while (i < RT_ELEMENTS(pVM->pgm.s.aHandyPages))
     3542    for (uint32_t i = pVM->pgm.s.cHandyPages; i < RT_ELEMENTS(pVM->pgm.s.aHandyPages); i++)
    35243543    {
    35253544        if (pVM->pgm.s.aHandyPages[i].idPage == idPage)
     
    35333552            break;
    35343553        }
    3535         i++;
    35363554    }
    35373555
  • trunk/src/VBox/VMM/TRPM.cpp

    r17428 r18617  
    14161416            {
    14171417                /* Must check pending forced actions as our IDT or GDT might be out of sync */
    1418                 EMR3CheckRawForcedActions(pVM);
    1419 
    1420                 /* There's a handler -> let's execute it in raw mode */
    1421                 rc = TRPMForwardTrap(pVM, CPUMCTX2CORE(pCtx), u8Interrupt, 0, TRPM_TRAP_NO_ERRORCODE, enmEvent, -1);
    1422                 if (rc == VINF_SUCCESS /* Don't use RT_SUCCESS */)
     1418                rc = EMR3CheckRawForcedActions(pVM);
     1419                if (rc == VINF_SUCCESS)
    14231420                {
    1424                     Assert(!VM_FF_ISPENDING(pVM, VM_FF_SELM_SYNC_GDT | VM_FF_SELM_SYNC_LDT | VM_FF_TRPM_SYNC_IDT | VM_FF_SELM_SYNC_TSS));
    1425 
    1426                     STAM_COUNTER_INC(&pVM->trpm.s.paStatForwardedIRQR3[u8Interrupt]);
    1427                     return VINF_EM_RESCHEDULE_RAW;
     1421                    /* There's a handler -> let's execute it in raw mode */
     1422                    rc = TRPMForwardTrap(pVM, CPUMCTX2CORE(pCtx), u8Interrupt, 0, TRPM_TRAP_NO_ERRORCODE, enmEvent, -1);
     1423                    if (rc == VINF_SUCCESS /* Don't use RT_SUCCESS */)
     1424                    {
     1425                        Assert(!VM_FF_ISPENDING(pVM, VM_FF_SELM_SYNC_GDT | VM_FF_SELM_SYNC_LDT | VM_FF_TRPM_SYNC_IDT | VM_FF_SELM_SYNC_TSS));
     1426
     1427                        STAM_COUNTER_INC(&pVM->trpm.s.paStatForwardedIRQR3[u8Interrupt]);
     1428                        return VINF_EM_RESCHEDULE_RAW;
     1429                    }
    14281430                }
    14291431            }
  • trunk/src/VBox/VMM/VMM.cpp

    r17367 r18617  
    15351535    PRINT_FLAG(VM_FF_PGM_SYNC_CR3);
    15361536    PRINT_FLAG(VM_FF_PGM_SYNC_CR3_NON_GLOBAL);
     1537    PRINT_FLAG(VM_FF_PGM_NEED_HANDY_PAGES);
     1538    PRINT_FLAG(VM_FF_PGM_NO_MEMORY);
    15371539    PRINT_FLAG(VM_FF_TRPM_SYNC_IDT);
    15381540    PRINT_FLAG(VM_FF_SELM_SYNC_TSS);
     
    15431545    PRINT_FLAG(VM_FF_CSAM_PENDING_ACTION);
    15441546    PRINT_FLAG(VM_FF_TO_R3);
     1547    PRINT_FLAG(VM_FF_REM_HANDLER_NOTIFY);
    15451548    PRINT_FLAG(VM_FF_DEBUG_SUSPEND);
    15461549    if (f)
  • 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
  • trunk/src/VBox/VMM/VMMGC/TRPMGCHandlers.cpp

    r17506 r18617  
    126126 * is already handled. Will process resume guest FFs.
    127127 *
    128  * @returns rc.
     128 * @returns rc, can be adjusted if its VINF_SUCCESS or something really bad
     129 *          happened.
    129130 * @param   pVM         VM handle.
    130131 * @param   rc          The VBox status code to return.
     
    182183     */
    183184    if (    rc == VINF_SUCCESS
    184         &&  VM_FF_ISPENDING(pVM, VM_FF_TO_R3 | VM_FF_TIMER | VM_FF_INTERRUPT_APIC | VM_FF_INTERRUPT_PIC | VM_FF_PGM_SYNC_CR3 | VM_FF_PGM_SYNC_CR3_NON_GLOBAL | VM_FF_REQUEST))
    185     {
     185        &&  VM_FF_ISPENDING(pVM, VM_FF_TO_R3 | VM_FF_TIMER | VM_FF_INTERRUPT_APIC | VM_FF_INTERRUPT_PIC | VM_FF_REQUEST
     186                               | VM_FF_PGM_SYNC_CR3 | VM_FF_PGM_SYNC_CR3_NON_GLOBAL | VM_FF_PGM_NO_MEMORY))
     187    {
     188        /* The out of memory condition naturally outrang the others. */
     189        if (RT_UNLIKELY(VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY)))
     190            rc = VINF_EM_NO_MEMORY;
    186191        /* Pending Ring-3 action. */
    187         if (VM_FF_ISPENDING(pVM, VM_FF_TO_R3))
     192        else if (VM_FF_ISPENDING(pVM, VM_FF_TO_R3))
    188193        {
    189194            VM_FF_CLEAR(pVM, VM_FF_TO_R3);
     
    903908        case VINF_IOM_HC_MMIO_READ_WRITE:
    904909        case VINF_PATM_PATCH_INT3:
     910        case VINF_EM_NO_MEMORY:
    905911        case VINF_EM_RAW_TO_R3:
    906912        case VINF_EM_RAW_TIMER_PENDING:
     
    944950    switch (rc)
    945951    {
    946     case VINF_EM_RAW_EMULATE_INSTR:
    947     case VINF_EM_RAW_EMULATE_INSTR_PD_FAULT:
    948     case VINF_EM_RAW_EMULATE_INSTR_GDT_FAULT:
    949     case VINF_EM_RAW_EMULATE_INSTR_TSS_FAULT:
    950     case VINF_EM_RAW_EMULATE_INSTR_LDT_FAULT:
    951     case VINF_EM_RAW_EMULATE_INSTR_IDT_FAULT:
    952         if (PATMIsPatchGCAddr(pVM, (RTRCPTR)pRegFrame->eip))
    953             rc = VINF_PATCH_EMULATE_INSTR;
    954         break;
    955 
    956     case VINF_EM_RAW_GUEST_TRAP:
    957         if (PATMIsPatchGCAddr(pVM, (RTRCPTR)pRegFrame->eip))
    958             return VINF_PATM_PATCH_TRAP_PF;
    959 
    960         rc = TRPMForwardTrap(pVM, pRegFrame, 0xE, 0, TRPM_TRAP_HAS_ERRORCODE, TRPM_TRAP, 0xe);
    961         Assert(rc == VINF_EM_RAW_GUEST_TRAP);
    962         break;
    963 
    964     case VINF_EM_RAW_INTERRUPT_PENDING:
    965         Assert(TRPMHasTrap(pVM));
    966         /* no break; */
    967     case VINF_IOM_HC_MMIO_READ:
    968     case VINF_IOM_HC_MMIO_WRITE:
    969     case VINF_IOM_HC_MMIO_READ_WRITE:
    970     case VINF_PATM_HC_MMIO_PATCH_READ:
    971     case VINF_PATM_HC_MMIO_PATCH_WRITE:
    972     case VINF_SUCCESS:
    973     case VINF_EM_RAW_TO_R3:
    974     case VINF_EM_PENDING_REQUEST:
    975     case VINF_EM_RAW_TIMER_PENDING:
    976     case VINF_CSAM_PENDING_ACTION:
    977     case VINF_PGM_SYNC_CR3: /** @todo Check this with Sander. */
    978         break;
    979 
    980     default:
    981         AssertMsg(PATMIsPatchGCAddr(pVM, (RTRCPTR)pRegFrame->eip) == false, ("Patch address for return code %d. eip=%08x\n", rc, pRegFrame->eip));
    982         break;
     952        case VINF_EM_RAW_EMULATE_INSTR:
     953        case VINF_EM_RAW_EMULATE_INSTR_PD_FAULT:
     954        case VINF_EM_RAW_EMULATE_INSTR_GDT_FAULT:
     955        case VINF_EM_RAW_EMULATE_INSTR_TSS_FAULT:
     956        case VINF_EM_RAW_EMULATE_INSTR_LDT_FAULT:
     957        case VINF_EM_RAW_EMULATE_INSTR_IDT_FAULT:
     958            if (PATMIsPatchGCAddr(pVM, (RTRCPTR)pRegFrame->eip))
     959                rc = VINF_PATCH_EMULATE_INSTR;
     960            break;
     961
     962        case VINF_EM_RAW_GUEST_TRAP:
     963            if (PATMIsPatchGCAddr(pVM, (RTRCPTR)pRegFrame->eip))
     964                return VINF_PATM_PATCH_TRAP_PF;
     965
     966            rc = TRPMForwardTrap(pVM, pRegFrame, 0xE, 0, TRPM_TRAP_HAS_ERRORCODE, TRPM_TRAP, 0xe);
     967            Assert(rc == VINF_EM_RAW_GUEST_TRAP);
     968            break;
     969
     970        case VINF_EM_RAW_INTERRUPT_PENDING:
     971            Assert(TRPMHasTrap(pVM));
     972            /* no break; */
     973        case VINF_IOM_HC_MMIO_READ:
     974        case VINF_IOM_HC_MMIO_WRITE:
     975        case VINF_IOM_HC_MMIO_READ_WRITE:
     976        case VINF_PATM_HC_MMIO_PATCH_READ:
     977        case VINF_PATM_HC_MMIO_PATCH_WRITE:
     978        case VINF_SUCCESS:
     979        case VINF_EM_RAW_TO_R3:
     980        case VINF_EM_PENDING_REQUEST:
     981        case VINF_EM_RAW_TIMER_PENDING:
     982        case VINF_EM_NO_MEMORY:
     983        case VINF_CSAM_PENDING_ACTION:
     984        case VINF_PGM_SYNC_CR3: /** @todo Check this with Sander. */
     985            break;
     986
     987        default:
     988            AssertMsg(PATMIsPatchGCAddr(pVM, (RTRCPTR)pRegFrame->eip) == false, ("Patch address for return code %d. eip=%08x\n", rc, pRegFrame->eip));
     989            break;
    983990    }
    984991    return trpmGCExitTrap(pVM, rc, pRegFrame);
  • trunk/src/VBox/VMM/VMMR0/GMMR0.cpp

    r18369 r18617  
    14661466            RTR0MemObjFree(MemObj, false /* fFreeMappings */);
    14671467    }
     1468    /** @todo Check that RTR0MemObjAllocPhysNC always returns VERR_NO_MEMORY on
     1469     *        allocation failure. */
    14681470    return rc;
    14691471}
  • trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp

    r17926 r18617  
    894894#endif
    895895    {
    896         if (VM_FF_ISPENDING(pVM, VM_FF_TO_R3 | VM_FF_TIMER | VM_FF_PGM_NEED_HANDY_PAGES))
     896        if (VM_FF_ISPENDING(pVM, VM_FF_HWACCM_TO_R3_MASK))
    897897        {
    898898            VM_FF_CLEAR(pVM, VM_FF_TO_R3);
    899899            STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatSwitchToR3);
    900900            STAM_PROFILE_ADV_STOP(&pVCpu->hwaccm.s.StatEntry, x);
    901             rc = VINF_EM_RAW_TO_R3;
     901            rc = RT_UNLIKELY(VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_NO_MEMORY : VINF_EM_RAW_TO_R3;
    902902            goto end;
    903903        }
  • trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp

    r17924 r18617  
    20752075
    20762076    /* Check for pending actions that force us to go back to ring 3. */
    2077     if (VM_FF_ISPENDING(pVM, VM_FF_TO_R3 | VM_FF_TIMER | VM_FF_PGM_NEED_HANDY_PAGES))
     2077    if (VM_FF_ISPENDING(pVM, VM_FF_HWACCM_TO_R3_MASK))
    20782078    {
    20792079        VM_FF_CLEAR(pVM, VM_FF_TO_R3);
    20802080        STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatSwitchToR3);
    2081         rc = VINF_EM_RAW_TO_R3;
     2081        rc = RT_UNLIKELY(VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_NO_MEMORY : VINF_EM_RAW_TO_R3;
    20822082        goto end;
    20832083    }
  • trunk/src/VBox/VMM/VMMR0/PGMR0.cpp

    r17526 r18617  
    6767    Assert(PDMCritSectIsOwner(&pVM->pgm.s.CritSect));
    6868
     69    /*
     70     * Check for error injection.
     71     */
     72    if (RT_UNLIKELY(pVM->pgm.s.fErrInjHandyPages))
     73        return VERR_NO_MEMORY;
     74
     75    /*
     76     * Try allocate a full set of handy pages.
     77     */
    6978    uint32_t iFirst = pVM->pgm.s.cHandyPages;
    70     if (iFirst > RT_ELEMENTS(pVM->pgm.s.aHandyPages))
    71     {
    72         LogRel(("%d", iFirst));
    73         return VERR_INTERNAL_ERROR;
    74     }
    75 
     79    AssertReturn(iFirst <= RT_ELEMENTS(pVM->pgm.s.aHandyPages), VERR_INTERNAL_ERROR);
    7680    uint32_t cPages = RT_ELEMENTS(pVM->pgm.s.aHandyPages) - iFirst;
    7781    if (!cPages)
    7882        return VINF_SUCCESS;
    79 
    8083    int rc = GMMR0AllocateHandyPages(pVM, cPages, cPages, &pVM->pgm.s.aHandyPages[iFirst]);
    8184    if (RT_SUCCESS(rc))
     
    9396    }
    9497    else if (rc != VERR_GMM_SEED_ME)
    95         LogRel(("PGMR0PhysAllocateHandyPages: rc=%Rrc iFirst=%d cPages=%d\n", rc, iFirst, cPages));
     98    {
     99        if (    (   rc == VERR_GMM_HIT_GLOBAL_LIMIT
     100                 || rc == VERR_GMM_HIT_VM_ACCOUNT_LIMIT)
     101            &&  iFirst < PGM_HANDY_PAGES_MIN)
     102        {
     103
     104#ifdef VBOX_STRICT
     105            /* We're ASSUMING that GMM has updated all the entires before failing us. */
     106            uint32_t i;
     107            for (i = iFirst; i < RT_ELEMENTS(pVM->pgm.s.aHandyPages); i++)
     108            {
     109                Assert(pVM->pgm.s.aHandyPages[i].idPage == NIL_GMM_PAGEID);
     110                Assert(pVM->pgm.s.aHandyPages[i].idSharedPage == NIL_GMM_PAGEID);
     111                Assert(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys == NIL_RTHCPHYS);
     112            }
     113#endif
     114
     115            /*
     116             * Reduce the number of pages until we hit the minimum limit.
     117             */
     118            do
     119            {
     120                cPages >>= 2;
     121                if (cPages + iFirst < PGM_HANDY_PAGES_MIN)
     122                    cPages = PGM_HANDY_PAGES_MIN - iFirst;
     123                rc = GMMR0AllocateHandyPages(pVM, cPages, cPages, &pVM->pgm.s.aHandyPages[iFirst]);
     124            } while (   (   rc == VERR_GMM_HIT_GLOBAL_LIMIT
     125                         || rc == VERR_GMM_HIT_VM_ACCOUNT_LIMIT)
     126                     && cPages + iFirst > PGM_HANDY_PAGES_MIN);
     127            if (RT_SUCCESS(rc))
     128            {
     129#ifdef VBOX_STRICT
     130                i = iFirst + cPages;
     131                while (i-- > 0)
     132                {
     133                    Assert(pVM->pgm.s.aHandyPages[i].idPage != NIL_GMM_PAGEID);
     134                    Assert(pVM->pgm.s.aHandyPages[i].idPage <= GMM_PAGEID_LAST);
     135                    Assert(pVM->pgm.s.aHandyPages[i].idSharedPage == NIL_GMM_PAGEID);
     136                    Assert(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys != NIL_RTHCPHYS);
     137                    Assert(!(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys & ~X86_PTE_PAE_PG_MASK));
     138                }
     139
     140                for (i = cPages + iFirst; i < RT_ELEMENTS(pVM->pgm.s.aHandyPages); i++)
     141                {
     142                    Assert(pVM->pgm.s.aHandyPages[i].idPage == NIL_GMM_PAGEID);
     143                    Assert(pVM->pgm.s.aHandyPages[i].idSharedPage == NIL_GMM_PAGEID);
     144                    Assert(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys == NIL_RTHCPHYS);
     145                }
     146#endif
     147
     148                pVM->pgm.s.cHandyPages = iFirst + cPages;
     149            }
     150        }
     151
     152        if (RT_FAILURE(rc) && rc != VERR_GMM_SEED_ME)
     153        {
     154            LogRel(("PGMR0PhysAllocateHandyPages: rc=%Rrc iFirst=%d cPages=%d\n", rc, iFirst, cPages));
     155            VM_FF_SET(pVM, VM_FF_PGM_NO_MEMORY);
     156        }
     157    }
     158
     159
    96160    LogFlow(("PGMR0PhysAllocateHandyPages: cPages=%d rc=%Rrc\n", cPages, rc));
    97161    return rc;
  • trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp

    r18615 r18617  
    521521    GEN_CHECK_OFF(PGM, pvZeroPgR3);
    522522    GEN_CHECK_OFF(PGM, pvZeroPgR0);
    523     GEN_CHECK_OFF(PGM, pvZeroPgGC);
     523    GEN_CHECK_OFF(PGM, pvZeroPgRC);
    524524    GEN_CHECK_OFF(PGM, cHandyPages);
    525525    GEN_CHECK_OFF(PGM, aHandyPages);
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