VirtualBox

Changeset 92390 in vbox


Ignore:
Timestamp:
Nov 12, 2021 9:24:33 AM (3 years ago)
Author:
vboxsync
Message:

VMM/PGM: Moved the zeroing and failure reporting from PGMR3PhysAllocateHandyPages and into PGMR0PhysAllocateHandyPages. bugref:10093

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR0/PGMR0.cpp

    r92389 r92390  
    133133 * @param   pGVM        The global (ring-0) VM structure.
    134134 * @param   idCpu       The ID of the calling EMT.
     135 * @param   fRing3      Set if the caller is ring-3.  Determins whether to
     136 *                      return VINF_EM_NO_MEMORY or not.
    135137 *
    136138 * @thread  EMT(idCpu)
     
    139141 *          must clear the new pages.
    140142 */
    141 VMMR0_INT_DECL(int) PGMR0PhysAllocateHandyPages(PGVM pGVM, VMCPUID idCpu)
     143int pgmR0PhysAllocateHandyPages(PGVM pGVM, VMCPUID idCpu, bool fRing3)
    142144{
    143145    /*
     
    145147     */
    146148    AssertReturn(idCpu < pGVM->cCpus, VERR_INVALID_CPU_ID); /* caller already checked this, but just to be sure. */
    147     AssertReturn(pGVM->aCpus[idCpu].hEMT == RTThreadNativeSelf(), VERR_NOT_OWNER);
     149    Assert(pGVM->aCpus[idCpu].hEMT == RTThreadNativeSelf());
    148150    PGM_LOCK_ASSERT_OWNER_EX(pGVM, &pGVM->aCpus[idCpu]);
    149151
     
    159161     * Try allocate a full set of handy pages.
    160162     */
    161     uint32_t iFirst = pGVM->pgm.s.cHandyPages;
    162     AssertReturn(iFirst <= RT_ELEMENTS(pGVM->pgm.s.aHandyPages), VERR_PGM_HANDY_PAGE_IPE);
    163     uint32_t cPages = RT_ELEMENTS(pGVM->pgm.s.aHandyPages) - iFirst;
     163    uint32_t const iFirst = pGVM->pgm.s.cHandyPages;
     164    AssertMsgReturn(iFirst <= RT_ELEMENTS(pGVM->pgm.s.aHandyPages), ("%#x\n", iFirst), VERR_PGM_HANDY_PAGE_IPE);
     165
     166    uint32_t const cPages = RT_ELEMENTS(pGVM->pgm.s.aHandyPages) - iFirst;
    164167    if (!cPages)
    165168        return VINF_SUCCESS;
     169
    166170    int rc = GMMR0AllocateHandyPages(pGVM, idCpu, cPages, cPages, &pGVM->pgm.s.aHandyPages[iFirst]);
    167171    if (RT_SUCCESS(rc))
    168172    {
     173        uint32_t const cHandyPages = RT_ELEMENTS(pGVM->pgm.s.aHandyPages); /** @todo allow allocating less... */
     174        pGVM->pgm.s.cHandyPages = cHandyPages;
     175        VM_FF_CLEAR(pGVM, VM_FF_PGM_NEED_HANDY_PAGES);
     176        VM_FF_CLEAR(pGVM, VM_FF_PGM_NO_MEMORY);
     177
    169178#ifdef VBOX_STRICT
    170         for (uint32_t i = 0; i < RT_ELEMENTS(pGVM->pgm.s.aHandyPages); i++)
     179        for (uint32_t i = 0; i < cHandyPages; i++)
    171180        {
    172181            Assert(pGVM->pgm.s.aHandyPages[i].idPage != NIL_GMM_PAGEID);
     
    178187#endif
    179188
    180         pGVM->pgm.s.cHandyPages = RT_ELEMENTS(pGVM->pgm.s.aHandyPages);
     189        /*
     190         * Clear the pages.
     191         */
     192        for (uint32_t iPage = iFirst; iPage < cHandyPages; iPage++)
     193        {
     194            PGMMPAGEDESC pPage = &pGVM->pgm.s.aHandyPages[iPage];
     195            if (!pPage->fZeroed)
     196            {
     197                void *pv = NULL;
     198#ifdef VBOX_WITH_LINEAR_HOST_PHYS_MEM
     199                rc = SUPR0HCPhysToVirt(pPage->HCPhysGCPhys, &pv);
     200#else
     201                rc = GMMR0PageIdToVirt(pGVM, pPage->idPage, &pv);
     202#endif
     203                AssertMsgRCReturn(rc, ("idPage=%#x HCPhys=%RHp rc=%Rrc\n", pPage->idPage, pPage->HCPhysGCPhys, rc), rc);
     204
     205                ASMMemZeroPage(pv);
     206                pPage->fZeroed = true;
     207            }
     208#ifdef VBOX_STRICT
     209            else
     210            {
     211                void *pv = NULL;
     212# ifdef VBOX_WITH_LINEAR_HOST_PHYS_MEM
     213                rc = SUPR0HCPhysToVirt(pPage->HCPhysGCPhys, &pv);
     214# else
     215                rc = GMMR0PageIdToVirt(pGVM, pPage->idPage, &pv);
     216# endif
     217                AssertMsgRCReturn(rc, ("idPage=%#x HCPhys=%RHp rc=%Rrc\n", pPage->idPage, pPage->HCPhysGCPhys, rc), rc);
     218                AssertReturn(ASMMemIsZeroPage(pv), VERR_PGM_HANDY_PAGE_IPE);
     219            }
     220#endif
     221            Log3(("PGMR0PhysAllocateHandyPages: idPage=%#x HCPhys=%RGp\n", pPage->idPage, pPage->HCPhysGCPhys));
     222        }
    181223    }
    182224    else
    183225    {
    184         LogRel(("PGMR0PhysAllocateHandyPages: rc=%Rrc iFirst=%d cPages=%d\n", rc, iFirst, cPages));
     226        /*
     227         * We should never get here unless there is a genuine shortage of
     228         * memory (or some internal error). Flag the error so the VM can be
     229         * suspended ASAP and the user informed. If we're totally out of
     230         * handy pages we will return failure.
     231         */
     232        /* Report the failure. */
     233        LogRel(("PGM: Failed to procure handy pages; rc=%Rrc cHandyPages=%#x\n"
     234                "     cAllPages=%#x cPrivatePages=%#x cSharedPages=%#x cZeroPages=%#x\n",
     235                rc, pGVM->pgm.s.cHandyPages,
     236                pGVM->pgm.s.cAllPages, pGVM->pgm.s.cPrivatePages, pGVM->pgm.s.cSharedPages, pGVM->pgm.s.cZeroPages));
     237
     238        GMMMEMSTATSREQ Stats = { { SUPVMMR0REQHDR_MAGIC, sizeof(Stats) }, 0, 0, 0, 0, 0 };
     239        if (RT_SUCCESS(GMMR0QueryMemoryStatsReq(pGVM, idCpu, &Stats)))
     240            LogRel(("GMM: Statistics:\n"
     241                    "     Allocated pages: %RX64\n"
     242                    "     Free      pages: %RX64\n"
     243                    "     Shared    pages: %RX64\n"
     244                    "     Maximum   pages: %RX64\n"
     245                    "     Ballooned pages: %RX64\n",
     246                    Stats.cAllocPages, Stats.cFreePages, Stats.cSharedPages, Stats.cMaxPages, Stats.cBalloonedPages));
     247
     248        if (   rc != VERR_NO_MEMORY
     249            && rc != VERR_NO_PHYS_MEMORY
     250            && rc != VERR_LOCK_FAILED)
     251            for (uint32_t iPage = 0; iPage < RT_ELEMENTS(pGVM->pgm.s.aHandyPages); iPage++)
     252                LogRel(("PGM: aHandyPages[#%#04x] = {.HCPhysGCPhys=%RHp, .idPage=%#08x, .idSharedPage=%#08x}\n",
     253                        iPage, pGVM->pgm.s.aHandyPages[iPage].HCPhysGCPhys, pGVM->pgm.s.aHandyPages[iPage].idPage,
     254                        pGVM->pgm.s.aHandyPages[iPage].idSharedPage));
     255
     256        /* Set the FFs and adjust rc. */
     257        VM_FF_SET(pGVM, VM_FF_PGM_NEED_HANDY_PAGES);
    185258        VM_FF_SET(pGVM, VM_FF_PGM_NO_MEMORY);
     259        if (!fRing3)
     260            if (   rc == VERR_NO_MEMORY
     261                || rc == VERR_NO_PHYS_MEMORY
     262                || rc == VERR_LOCK_FAILED
     263                || rc == VERR_MAP_FAILED)
     264                rc = VINF_EM_NO_MEMORY;
    186265    }
    187266
    188267    LogFlow(("PGMR0PhysAllocateHandyPages: cPages=%d rc=%Rrc\n", cPages, rc));
     268    return rc;
     269}
     270
     271
     272/**
     273 * Worker function for PGMR3PhysAllocateHandyPages / VMMR0_DO_PGM_ALLOCATE_HANDY_PAGES.
     274 *
     275 * @returns The following VBox status codes.
     276 * @retval  VINF_SUCCESS on success. FF cleared.
     277 * @retval  VINF_EM_NO_MEMORY if we're out of memory. The FF is set in this case.
     278 *
     279 * @param   pGVM        The global (ring-0) VM structure.
     280 * @param   idCpu       The ID of the calling EMT.
     281 *
     282 * @thread  EMT(idCpu)
     283 *
     284 * @remarks Must be called from within the PGM critical section. The caller
     285 *          must clear the new pages.
     286 */
     287VMMR0_INT_DECL(int) PGMR0PhysAllocateHandyPages(PGVM pGVM, VMCPUID idCpu)
     288{
     289    /*
     290     * Validate inputs.
     291     */
     292    AssertReturn(idCpu < pGVM->cCpus, VERR_INVALID_CPU_ID); /* caller already checked this, but just to be sure. */
     293    AssertReturn(pGVM->aCpus[idCpu].hEMT == RTThreadNativeSelf(), VERR_NOT_OWNER);
     294
     295    /*
     296     * Enter the PGM lock and call the worker.
     297     */
     298    int rc = PGM_LOCK(pGVM);
     299    if (RT_SUCCESS(rc))
     300    {
     301        rc = pgmR0PhysAllocateHandyPages(pGVM, idCpu, true /*fRing3*/);
     302        PGM_UNLOCK(pGVM);
     303    }
    189304    return rc;
    190305}
  • trunk/src/VBox/VMM/VMMR3/PGMPhys.cpp

    r92368 r92390  
    58435843    AssertMsgReturn(iClear <= RT_ELEMENTS(pVM->pgm.s.aHandyPages), ("%d", iClear), VERR_PGM_HANDY_PAGE_IPE);
    58445844    Log(("PGMR3PhysAllocateHandyPages: %d -> %d\n", iClear, RT_ELEMENTS(pVM->pgm.s.aHandyPages)));
    5845     int rcAlloc = VINF_SUCCESS;
    5846     int rcSeed  = VINF_SUCCESS;
    58475845    int rc = VMMR3CallR0(pVM, VMMR0_DO_PGM_ALLOCATE_HANDY_PAGES, 0, NULL);
    58485846    /** @todo we should split this up into an allocate and flush operation. sometimes you want to flush and not allocate more (which will trigger the vm account limit error) */
     
    58585856        AssertMsg(rc == VINF_SUCCESS, ("%Rrc\n", rc));
    58595857        Assert(pVM->pgm.s.cHandyPages > 0);
    5860         VM_FF_CLEAR(pVM, VM_FF_PGM_NEED_HANDY_PAGES);
    5861         VM_FF_CLEAR(pVM, VM_FF_PGM_NO_MEMORY);
    5862 
    58635858#ifdef VBOX_STRICT
    58645859        uint32_t i;
     
    58815876        }
    58825877#endif
    5883         /*
    5884          * Clear the pages.
    5885          */
    5886         while (iClear < pVM->pgm.s.cHandyPages)
    5887         {
    5888             PGMMPAGEDESC pPage = &pVM->pgm.s.aHandyPages[iClear];
    5889             if (!pPage->fZeroed)
    5890             {
    5891                 void *pv;
    5892                 rc = pgmPhysPageMapByPageID(pVM, pPage->idPage, pPage->HCPhysGCPhys, &pv);
    5893                 AssertLogRelMsgBreak(RT_SUCCESS(rc),
    5894                                      ("%u/%u: idPage=%#x HCPhysGCPhys=%RHp rc=%Rrc\n",
    5895                                       iClear, pVM->pgm.s.cHandyPages, pPage->idPage, pPage->HCPhysGCPhys, rc));
    5896                 ASMMemZeroPage(pv);
    5897                 pPage->fZeroed = true;
    5898             }
    5899 #ifdef VBOX_STRICT
    5900             else
    5901             {
    5902                 void *pv;
    5903                 rc = pgmPhysPageMapByPageID(pVM, pPage->idPage, pPage->HCPhysGCPhys, &pv);
    5904                 AssertLogRelMsgBreak(RT_SUCCESS(rc),
    5905                                      ("%u/%u: idPage=%#x HCPhysGCPhys=%RHp rc=%Rrc\n",
    5906                                       iClear, pVM->pgm.s.cHandyPages, pPage->idPage, pPage->HCPhysGCPhys, rc));
    5907                 Assert(ASMMemIsZeroPage(pv));
    5908             }
    5909 #endif
    5910             iClear++;
    5911             Log3(("PGMR3PhysAllocateHandyPages: idPage=%#x HCPhys=%RGp\n", pPage->idPage, pPage->HCPhysGCPhys));
    5912         }
    59135878    }
    59145879    else
    59155880    {
    5916         uint64_t cAllocPages, cMaxPages, cBalloonPages;
    5917 
    59185881        /*
    59195882         * We should never get here unless there is a genuine shortage of
     
    59235886         */
    59245887        /* Report the failure. */
    5925         LogRel(("PGM: Failed to procure handy pages; rc=%Rrc rcAlloc=%Rrc rcSeed=%Rrc cHandyPages=%#x\n"
     5888        LogRel(("PGM: Failed to procure handy pages; rc=%Rrc cHandyPages=%#x\n"
    59265889                "     cAllPages=%#x cPrivatePages=%#x cSharedPages=%#x cZeroPages=%#x\n",
    5927                 rc, rcAlloc, rcSeed,
    5928                 pVM->pgm.s.cHandyPages,
    5929                 pVM->pgm.s.cAllPages,
    5930                 pVM->pgm.s.cPrivatePages,
    5931                 pVM->pgm.s.cSharedPages,
    5932                 pVM->pgm.s.cZeroPages));
    5933 
    5934         if (GMMR3QueryMemoryStats(pVM, &cAllocPages, &cMaxPages, &cBalloonPages) == VINF_SUCCESS)
    5935         {
    5936             LogRel(("GMM: Statistics:\n"
    5937                     "     Allocated pages: %RX64\n"
    5938                     "     Maximum   pages: %RX64\n"
    5939                     "     Ballooned pages: %RX64\n", cAllocPages, cMaxPages, cBalloonPages));
    5940         }
     5890                rc, pVM->pgm.s.cHandyPages,
     5891                pVM->pgm.s.cAllPages, pVM->pgm.s.cPrivatePages, pVM->pgm.s.cSharedPages, pVM->pgm.s.cZeroPages));
    59415892
    59425893        if (   rc != VERR_NO_MEMORY
    59435894            && rc != VERR_NO_PHYS_MEMORY
    59445895            && rc != VERR_LOCK_FAILED)
    5945         {
    59465896            for (uint32_t i = 0; i < RT_ELEMENTS(pVM->pgm.s.aHandyPages); i++)
    59475897            {
     
    59645914                }
    59655915            }
    5966         }
    59675916
    59685917        if (rc == VERR_NO_MEMORY)
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