VirtualBox

Changeset 29468 in vbox for trunk/src/VBox/VMM/VMMR0


Ignore:
Timestamp:
May 14, 2010 12:16:44 PM (15 years ago)
Author:
vboxsync
Message:

Split up

Location:
trunk/src/VBox/VMM/VMMR0
Files:
1 added
1 edited

Legend:

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

    r29424 r29468  
    302302}
    303303
    304 #ifdef VBOX_WITH_PAGE_SHARING
    305 /**
    306  * Check a registered module for shared page changes
    307  *
    308  * @returns The following VBox status codes.
    309  *
    310  * @param   pVM         The VM handle.
    311  * @param   idCpu       VCPU id
    312  * @param   pModule     Module description
    313  * @param   pGVM        Pointer to the GVM instance data.
    314  */
    315 VMMR0DECL(int) PGMR0SharedModuleCheckRegion(PVM pVM, VMCPUID idCpu, PGMMSHAREDMODULE pModule, PGVM pGVM)
    316 {
    317     int                rc = VINF_SUCCESS;
    318     PGMMSHAREDPAGEDESC paPageDesc = NULL;
    319     uint32_t           cbPreviousRegion  = 0;
    320     bool               fFlushTLBs = false;
    321     PVMCPU             pVCpu = &pVM->aCpus[idCpu];
    322 
    323     Log(("PGMR0SharedModuleCheck: check %s %s base=%RGv size=%x\n", pModule->szName, pModule->szVersion, pModule->Core.Key, pModule->cbModule));
    324 
    325     pgmLock(pVM);
    326 
    327     /* Check every region of the shared module. */
    328     for (unsigned i = 0; i < pModule->cRegions; i++)
    329     {
    330         Assert((pModule->aRegions[i].cbRegion & 0xfff) == 0);
    331         Assert((pModule->aRegions[i].GCRegionAddr & 0xfff) == 0);
    332 
    333         RTGCPTR  GCRegion  = pModule->aRegions[i].GCRegionAddr;
    334         unsigned cbRegion = pModule->aRegions[i].cbRegion & ~0xfff;
    335         unsigned idxPage = 0;
    336         bool     fValidChanges = false;
    337 
    338         if (cbPreviousRegion < cbRegion)
    339         {
    340             if (paPageDesc)
    341                 RTMemFree(paPageDesc);
    342 
    343             paPageDesc = (PGMMSHAREDPAGEDESC)RTMemAlloc((cbRegion >> PAGE_SHIFT) * sizeof(*paPageDesc));
    344             if (!paPageDesc)
    345             {
    346                 AssertFailed();
    347                 rc = VERR_NO_MEMORY;
    348                 goto end;
    349             }
    350             cbPreviousRegion  = cbRegion;
    351         }
    352 
    353         while (cbRegion)
    354         {
    355             RTGCPHYS GCPhys;
    356             uint64_t fFlags;
    357 
    358             rc = PGMGstGetPage(pVCpu, GCRegion, &fFlags, &GCPhys);
    359             if (    rc == VINF_SUCCESS
    360                 &&  !(fFlags & X86_PTE_RW)) /* important as we make assumptions about this below! */
    361             {
    362                 PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);
    363                 if (    pPage
    364                     &&  !PGM_PAGE_IS_SHARED(pPage))
    365                 {
    366                     fValidChanges = true;
    367                     paPageDesc[idxPage].uHCPhysPageId = PGM_PAGE_GET_PAGEID(pPage);
    368                     paPageDesc[idxPage].HCPhys        = PGM_PAGE_GET_HCPHYS(pPage);
    369                     paPageDesc[idxPage].GCPhys        = GCPhys;
    370                 }
    371                 else
    372                     paPageDesc[idxPage].uHCPhysPageId = NIL_GMM_PAGEID;
    373             }
    374             else
    375                 paPageDesc[idxPage].uHCPhysPageId = NIL_GMM_PAGEID;
    376 
    377             idxPage++;
    378             GCRegion += PAGE_SIZE;
    379             cbRegion -= PAGE_SIZE;
    380         }
    381 
    382         if (fValidChanges)
    383         {
    384             rc = GMMR0SharedModuleCheckRange(pGVM, pModule, i, idxPage, paPageDesc);
    385             AssertRC(rc);
    386             if (RT_FAILURE(rc))
    387                 break;
    388                
    389             for (unsigned i = 0; i < idxPage; i++)
    390             {
    391                 /* Any change for this page? */
    392                 if (paPageDesc[i].uHCPhysPageId != NIL_GMM_PAGEID)
    393                 {
    394                     /** todo: maybe cache these to prevent the nth lookup. */
    395                     PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, paPageDesc[i].GCPhys);
    396                     if (!pPage)
    397                     {
    398                         /* Should never happen. */
    399                         AssertFailed();
    400                         rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
    401                         goto end;
    402                     }
    403                     Assert(!PGM_PAGE_IS_SHARED(pPage));
    404 
    405                     Log(("PGMR0SharedModuleCheck: shared page gc phys %RGp host %RHp->%RHp\n", paPageDesc[i].GCPhys, PGM_PAGE_GET_HCPHYS(pPage), paPageDesc[i].HCPhys));
    406                     if (paPageDesc[i].HCPhys != PGM_PAGE_GET_HCPHYS(pPage))
    407                     {
    408                         bool fFlush = false;
    409 
    410                         /* Page was replaced by an existing shared version of it; clear all references first. */
    411                         rc = pgmPoolTrackUpdateGCPhys(pVM, paPageDesc[i].GCPhys, pPage, true /* clear the entries */, &fFlush);
    412                         if (RT_FAILURE(rc))
    413                         {
    414                             AssertRC(rc);
    415                             goto end;
    416                         }
    417                         Assert(rc == VINF_SUCCESS || (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3) && (pVCpu->pgm.s.fSyncFlags & PGM_SYNC_CLEAR_PGM_POOL)));
    418                         if (rc = VINF_SUCCESS)
    419                             fFlushTLBs |= fFlush;
    420 
    421                         /* Update the physical address and page id now. */
    422                         PGM_PAGE_SET_HCPHYS(pPage, paPageDesc[i].HCPhys);
    423                         PGM_PAGE_SET_PAGEID(pPage, paPageDesc[i].uHCPhysPageId);
    424 
    425                         /* Invalidate page map TLB entry for this page too. */
    426                         PGMPhysInvalidatePageMapTLBEntry(pVM, paPageDesc[i].GCPhys);
    427                     }
    428                     /* else nothing changed (== this page is now a shared page), so no need to flush anything. */
    429 
    430                     pVM->pgm.s.cSharedPages++;
    431                     pVM->pgm.s.cPrivatePages--;
    432                     PGM_PAGE_SET_STATE(pPage, PGM_PAGE_STATE_SHARED);
    433                 }
    434             }
    435         }
    436         else
    437             rc = VINF_SUCCESS;  /* nothing to do. */
    438     }
    439 
    440 end:
    441     pgmUnlock(pVM);
    442     if (fFlushTLBs)
    443         PGM_INVL_ALL_VCPU_TLBS(pVM);
    444 
    445     if (paPageDesc)
    446         RTMemFree(paPageDesc);
    447 
    448     return rc;
    449 }
    450 #endif
    451 
    452 #if 0
    453 /**
    454  * Shared module registration helper (called on the way out).
    455  *
    456  * @param   pVM         The VM handle.
    457  * @param   pReq        Registration request info
    458  */
    459 static DECLCALLBACK(void) pgmR3SharedModuleRegisterHelper(PVM pVM, PGMMREGISTERSHAREDMODULEREQ pReq)
    460 {
    461     int rc;
    462    
    463     rc = GMMR3RegisterSharedModule(pVM, pReq);
    464     Assert(rc == VINF_SUCCESS || rc == VINF_PGM_SHARED_MODULE_COLLISION || rc == VINF_PGM_SHARED_MODULE_ALREADY_REGISTERED);
    465     if (rc == VINF_PGM_SHARED_MODULE_ALREADY_REGISTERED)
    466     {
    467         PVMCPU   pVCpu = VMMGetCpu(pVM);
    468         unsigned cFlushedPages = 0;
    469 
    470         /** todo count copy-on-write actions in the trap handler so we don't have to check everything all the time! */
    471 
    472         /* Count the number of shared pages that were changed (copy-on-write). */
    473         for (unsigned i = 0; i < pReq->cRegions; i++)
    474         {
    475             Assert((pReq->aRegions[i].cbRegion & 0xfff) == 0);
    476             Assert((pReq->aRegions[i].GCRegionAddr & 0xfff) == 0);
    477 
    478             RTGCPTR GCRegion  = pReq->aRegions[i].GCRegionAddr;
    479             uint32_t cbRegion = pReq->aRegions[i].cbRegion & ~0xfff;
    480 
    481             while (cbRegion)
    482             {
    483                 RTGCPHYS GCPhys;
    484                 uint64_t fFlags;
    485 
    486                 rc = PGMGstGetPage(pVCpu, GCRegion, &fFlags, &GCPhys);
    487                 if (    rc == VINF_SUCCESS
    488                     &&  !(fFlags & X86_PTE_RW))
    489                 {
    490                     PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);
    491                     if (    pPage
    492                         &&  !PGM_PAGE_IS_SHARED(pPage))
    493                     {
    494                         cFlushedPages++;
    495                     }
    496                 }
    497 
    498                 GCRegion += PAGE_SIZE;
    499                 cbRegion -= PAGE_SIZE;
    500             }
    501         }
    502 
    503         if (cFlushedPages > 32)
    504             rc = VINF_SUCCESS;  /* force recheck below */
    505     }
    506     /* Full (re)check needed? */
    507     if (rc == VINF_SUCCESS)
    508     {
    509         pReq->Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
    510         pReq->Hdr.cbReq = RT_OFFSETOF(GMMREGISTERSHAREDMODULEREQ, aRegions[pReq->cRegions]);
    511 
    512         /* We must stall other VCPUs as we'd otherwise have to send IPI flush commands for every single change we make. */
    513         rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, pgmR3SharedModuleRegRendezvous, pReq);
    514         AssertRC(rc);
    515     }
    516     RTMemFree(pReq);
    517     return;
    518 }
    519 #endif
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