VirtualBox

Changeset 38953 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Oct 6, 2011 8:49:36 AM (13 years ago)
Author:
vboxsync
Message:

PGM: Attempt at fixing the VERR_MAP_FAILED during state save problem on 32-bit hosts when assigning lots of memory to the guest. PGM should lock down guest RAM pages before use and release them afterwards like everyone else. Still quite some stuff left to do there, so I've deviced a little hack for tracking unlocked mappings and using this as input when deciding to do async or sync chunk unmapping at save/load time. See xtracker #5912 and public ticket 7929.

Location:
trunk/src/VBox/VMM/VMMR3
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/PGM.cpp

    r38712 r38953  
    11861186    AssertCompile(sizeof(pVM->pgm.s) <= sizeof(pVM->pgm.padding));
    11871187    AssertCompile(sizeof(pVM->aCpus[0].pgm.s) <= sizeof(pVM->aCpus[0].pgm.padding));
    1188     AssertCompileMemberAlignment(PGM, CritSect, sizeof(uintptr_t));
     1188    AssertCompileMemberAlignment(PGM, CritSectX, sizeof(uintptr_t));
    11891189
    11901190    /*
     
    13421342     * Initialize the PGM critical section and flush the phys TLBs
    13431343     */
    1344     rc = PDMR3CritSectInit(pVM, &pVM->pgm.s.CritSect, RT_SRC_POS, "PGM");
     1344    rc = PDMR3CritSectInit(pVM, &pVM->pgm.s.CritSectX, RT_SRC_POS, "PGM");
    13451345    AssertRCReturn(rc, rc);
    13461346
     
    14541454
    14551455    /* Almost no cleanup necessary, MM frees all memory. */
    1456     PDMR3CritSectDelete(&pVM->pgm.s.CritSect);
     1456    PDMR3CritSectDelete(&pVM->pgm.s.CritSectX);
    14571457
    14581458    return rc;
     
    25782578
    25792579    PGMDeregisterStringFormatTypes();
    2580     return PDMR3CritSectDelete(&pVM->pgm.s.CritSect);
     2580    return PDMR3CritSectDelete(&pVM->pgm.s.CritSectX);
    25812581}
    25822582
     
    26892689     * Get page directory addresses.
    26902690     */
     2691    pgmLock(pVM);
    26912692    PX86PD     pPDSrc = pgmGstGet32bitPDPtr(pVCpu);
    26922693    Assert(pPDSrc);
    2693     Assert(PGMPhysGCPhys2R3PtrAssert(pVM, (RTGCPHYS)(CPUMGetGuestCR3(pVCpu) & X86_CR3_PAGE_MASK), sizeof(*pPDSrc)) == pPDSrc);
    26942694
    26952695    /*
     
    27152715        }
    27162716    }
     2717    pgmUnlock(pVM);
    27172718}
    27182719
     
    27262727VMMR3DECL(int) PGMR3LockCall(PVM pVM)
    27272728{
    2728     int rc = PDMR3CritSectEnterEx(&pVM->pgm.s.CritSect, true /* fHostCall */);
     2729    int rc = PDMR3CritSectEnterEx(&pVM->pgm.s.CritSectX, true /* fHostCall */);
    27292730    AssertRC(rc);
    27302731    return rc;
  • trunk/src/VBox/VMM/VMMR3/PGMPhys.cpp

    r38838 r38953  
    150150                 * Simple stuff, go ahead.
    151151                 */
    152                 size_t   cb    = PAGE_SIZE - (off & PAGE_OFFSET_MASK);
     152                size_t cb = PAGE_SIZE - (off & PAGE_OFFSET_MASK);
    153153                if (cb > cbRead)
    154154                    cb = cbRead;
    155                 const void *pvSrc;
    156                 int rc = pgmPhysGCPhys2CCPtrInternalReadOnly(pVM, pPage, pRam->GCPhys + off, &pvSrc);
     155                PGMPAGEMAPLOCK PgMpLck;
     156                const void    *pvSrc;
     157                int rc = pgmPhysGCPhys2CCPtrInternalReadOnly(pVM, pPage, pRam->GCPhys + off, &pvSrc, &PgMpLck);
    157158                if (RT_SUCCESS(rc))
     159                {
    158160                    memcpy(pvBuf, pvSrc, cb);
     161                    pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);
     162                }
    159163                else
    160164                {
     
    290294                 * Simple stuff, go ahead.
    291295                 */
    292                 size_t      cb    = PAGE_SIZE - (off & PAGE_OFFSET_MASK);
     296                size_t cb = PAGE_SIZE - (off & PAGE_OFFSET_MASK);
    293297                if (cb > cbWrite)
    294298                    cb = cbWrite;
    295                 void *pvDst;
    296                 int rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, pRam->GCPhys + off, &pvDst);
     299                PGMPAGEMAPLOCK PgMpLck;
     300                void          *pvDst;
     301                int rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, pRam->GCPhys + off, &pvDst, &PgMpLck);
    297302                if (RT_SUCCESS(rc))
     303                {
    298304                    memcpy(pvDst, pvBuf, cb);
     305                    pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);
     306                }
    299307                else
    300308                    AssertLogRelMsgFailed(("pgmPhysGCPhys2CCPtrInternal failed on %RGp / %R[pgmpage] -> %Rrc\n",
     
    39964004        pVM->pgm.s.cMappedChunks++;
    39974005
    3998         /* If we're running out of virtual address space, then we should unmap another chunk. */
     4006        /*
     4007         * If we're running out of virtual address space, then we should
     4008         * unmap another chunk.
     4009         *
     4010         * Currently, an unmap operation requires that all other virtual CPUs
     4011         * are idling and not by chance making use of the memory we're
     4012         * unmapping.  So, we create an async unmap operation here.
     4013         *
     4014         * Now, when creating or restoring a saved state this wont work very
     4015         * well since we may want to restore all guest RAM + a little something.
     4016         * So, we have to do the unmap synchronously.  Fortunately for us
     4017         * though, during these operations the other virtual CPUs are inactive
     4018         * and it should be safe to do this.
     4019         */
     4020        /** @todo Eventually we should lock all memory when used and do
     4021         *        map+unmap as one kernel call without any rendezvous or
     4022         *        other precautions. */
    39994023        if (pVM->pgm.s.ChunkR3Map.c >= pVM->pgm.s.ChunkR3Map.cMax)
    40004024        {
    4001             /* Postpone the unmap operation (which requires a rendezvous operation) as we own the PGM lock here. */
    4002             rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)pgmR3PhysUnmapChunk, 1, pVM);
    4003             AssertRC(rc);
     4025            switch (VMR3GetState(pVM))
     4026            {
     4027                case VMSTATE_LOADING:
     4028                case VMSTATE_SAVING:
     4029                {
     4030                    PVMCPU pVCpu = VMMGetCpu(pVM);
     4031                    if (   pVCpu
     4032                        && pVM->pgm.s.cDeprecatedPageLocks == 0)
     4033                    {
     4034                        pgmR3PhysUnmapChunkRendezvous(pVM, pVCpu, NULL);
     4035                        break;
     4036                    }
     4037                    /* fall thru */
     4038                }
     4039                default:
     4040                    rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)pgmR3PhysUnmapChunk, 1, pVM);
     4041                    AssertRC(rc);
     4042                    break;
     4043            }
    40044044        }
    40054045    }
  • trunk/src/VBox/VMM/VMMR3/PGMSavedState.cpp

    r38707 r38953  
    12431243static void pgmR3StateCalcCrc32ForRamPage(PVM pVM, PPGMRAMRANGE pCur, PPGMLIVESAVERAMPAGE paLSPages, uint32_t iPage)
    12441244{
    1245     RTGCPHYS    GCPhys = pCur->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT);
    1246     void const *pvPage;
    1247     int rc = pgmPhysGCPhys2CCPtrInternalReadOnly(pVM, &pCur->aPages[iPage], GCPhys, &pvPage);
     1245    RTGCPHYS        GCPhys = pCur->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT);
     1246    PGMPAGEMAPLOCK  PgMpLck;
     1247    void const     *pvPage;
     1248    int rc = pgmPhysGCPhys2CCPtrInternalReadOnly(pVM, &pCur->aPages[iPage], GCPhys, &pvPage, &PgMpLck);
    12481249    if (RT_SUCCESS(rc))
     1250    {
    12491251        paLSPages[iPage].u32Crc = RTCrc32(pvPage, PAGE_SIZE);
     1252        pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);
     1253    }
    12501254    else
    12511255        paLSPages[iPage].u32Crc = UINT32_MAX; /* Invalid */
     
    12901294    if (paLSPages[iPage].u32Crc != UINT32_MAX)
    12911295    {
    1292         RTGCPHYS    GCPhys = pCur->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT);
    1293         void const *pvPage;
    1294         int rc = pgmPhysGCPhys2CCPtrInternalReadOnly(pVM, &pCur->aPages[iPage], GCPhys, &pvPage);
     1296        RTGCPHYS        GCPhys = pCur->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT);
     1297        PGMPAGEMAPLOCK  PgMpLck;
     1298        void const     *pvPage;
     1299        int rc = pgmPhysGCPhys2CCPtrInternalReadOnly(pVM, &pCur->aPages[iPage], GCPhys, &pvPage, &PgMpLck);
    12951300        if (RT_SUCCESS(rc))
     1301        {
    12961302            pgmR3StateVerifyCrc32ForPage(pvPage, pCur, paLSPages, iPage, pszWhere);
     1303            pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);
     1304        }
    12971305    }
    12981306}
     
    13331341                        && (iPage & 0x7ff) == 0x100
    13341342#endif
    1335                         && PDMR3CritSectYield(&pVM->pgm.s.CritSect)
     1343                        && PDMR3CritSectYield(&pVM->pgm.s.CritSectX)
    13361344                        && pVM->pgm.s.idRamRangesGen != idRamRangesGen)
    13371345                    {
     
    15581566                    if (   uPass != SSM_PASS_FINAL
    15591567                        && (iPage & 0x7ff) == 0x100
    1560                         && PDMR3CritSectYield(&pVM->pgm.s.CritSect)
     1568                        && PDMR3CritSectYield(&pVM->pgm.s.CritSectX)
    15611569                        && pVM->pgm.s.idRamRangesGen != idRamRangesGen)
    15621570                    {
     
    16221630                         * SSM call may block).
    16231631                         */
    1624                         uint8_t     abPage[PAGE_SIZE];
    1625                         void const *pvPage;
    1626                         rc = pgmPhysGCPhys2CCPtrInternalReadOnly(pVM, pCurPage, GCPhys, &pvPage);
     1632                        uint8_t         abPage[PAGE_SIZE];
     1633                        PGMPAGEMAPLOCK  PgMpLck;
     1634                        void const     *pvPage;
     1635                        rc = pgmPhysGCPhys2CCPtrInternalReadOnly(pVM, pCurPage, GCPhys, &pvPage, &PgMpLck);
    16271636                        if (RT_SUCCESS(rc))
    16281637                        {
     
    16321641                                pgmR3StateVerifyCrc32ForPage(abPage, pCur, paLSPages, iPage, "save#3");
    16331642#endif
     1643                            pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);
    16341644                        }
    16351645                        pgmUnlock(pVM);
     
    22312241     * Load the page.
    22322242     */
    2233     void *pvPage;
    2234     int rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvPage);
     2243    PGMPAGEMAPLOCK PgMpLck;
     2244    void          *pvPage;
     2245    int rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvPage, &PgMpLck);
    22352246    if (RT_SUCCESS(rc))
     2247    {
    22362248        rc = SSMR3GetMem(pSSM, pvPage, PAGE_SIZE);
     2249        pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);
     2250    }
    22372251
    22382252    return rc;
     
    26772691                            || PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_ROM_SHADOW)
    26782692                        {
    2679                             void *pvDstPage;
    2680                             rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDstPage);
     2693                            PGMPAGEMAPLOCK PgMpLck;
     2694                            void          *pvDstPage;
     2695                            rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDstPage, &PgMpLck);
    26812696                            AssertLogRelMsgRCReturn(rc, ("GCPhys=%RGp %R[pgmpage] rc=%Rrc\n", GCPhys, pPage, rc), rc);
     2697
    26822698                            ASMMemZeroPage(pvDstPage);
     2699                            pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);
    26832700                        }
    26842701                        /* Free it only if it's not part of a previously
     
    27192736                    case PGM_STATE_REC_RAM_RAW:
    27202737                    {
    2721                         void *pvDstPage;
    2722                         rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDstPage);
     2738                        PGMPAGEMAPLOCK PgMpLck;
     2739                        void          *pvDstPage;
     2740                        rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDstPage, &PgMpLck);
    27232741                        AssertLogRelMsgRCReturn(rc, ("GCPhys=%RGp %R[pgmpage] rc=%Rrc\n", GCPhys, pPage, rc), rc);
    27242742                        rc = SSMR3GetMem(pSSM, pvDstPage, PAGE_SIZE);
     2743                        pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);
    27252744                        if (RT_FAILURE(rc))
    27262745                            return rc;
  • trunk/src/VBox/VMM/VMMR3/PGMSharedPage.cpp

    r36891 r38953  
    342342                    case PGM_PAGE_STATE_WRITE_MONITORED:
    343343                    {
    344                         const void *pvPage;
    345344                        /* Check if the page was allocated, but completely zero. */
    346                         int rc = pgmPhysGCPhys2CCPtrInternalReadOnly(pVM, pPage, GCPhys, &pvPage);
    347                         if (    rc == VINF_SUCCESS
     345                        PGMPAGEMAPLOCK PgMpLck;
     346                        const void    *pvPage;
     347                        int rc = pgmPhysGCPhys2CCPtrInternalReadOnly(pVM, pPage, GCPhys, &pvPage, &PgMpLck);
     348                        if (    RT_SUCCESS(rc)
    348349                            &&  ASMMemIsZeroPage(pvPage))
    349                         {
    350350                            cAllocZero++;
    351                         }
    352                         else
    353                         if (GMMR3IsDuplicatePage(pVM, PGM_PAGE_GET_PAGEID(pPage)))
     351                        else if (GMMR3IsDuplicatePage(pVM, PGM_PAGE_GET_PAGEID(pPage)))
    354352                            cDuplicate++;
    355353                        else
    356354                            cUnique++;
    357 
     355                        if (RT_SUCCESS(rc))
     356                            pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);
    358357                        break;
    359358                    }
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