VirtualBox

Ignore:
Timestamp:
Aug 6, 2019 8:28:12 PM (6 years ago)
Author:
vboxsync
Message:

VMM: Kicking out raw-mode - PGM Virt Handlers, ++. bugref:9517

File:
1 edited

Legend:

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

    r76553 r80163  
    2929PGM_GST_DECL(int,  ModifyPage)(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask);
    3030PGM_GST_DECL(int,  GetPDE)(PVMCPU pVCpu, RTGCPTR GCPtr, PX86PDEPAE pPDE);
    31 PGM_GST_DECL(bool, HandlerVirtualUpdate)(PVM pVM, uint32_t cr4);
    3231
    3332#ifdef IN_RING3 /* r3 only for now.  */
     
    507506
    508507
    509 #if (   PGM_GST_TYPE == PGM_TYPE_32BIT \
    510      || PGM_GST_TYPE == PGM_TYPE_PAE \
    511      || PGM_GST_TYPE == PGM_TYPE_AMD64) \
    512  && defined(VBOX_WITH_RAW_MODE)
    513 /**
    514  * Updates one virtual handler range.
    515  *
    516  * @returns 0
    517  * @param   pNode   Pointer to a PGMVIRTHANDLER.
    518  * @param   pvUser  Pointer to a PGMVHUARGS structure (see PGM.cpp).
    519  */
    520 static DECLCALLBACK(int) PGM_GST_NAME(VirtHandlerUpdateOne)(PAVLROGCPTRNODECORE pNode, void *pvUser)
    521 {
    522     PPGMHVUSTATE            pState   = (PPGMHVUSTATE)pvUser;
    523     PVM                     pVM      = pState->pVM;
    524     PVMCPU                  pVCpu    = pState->pVCpu;
    525     PPGMVIRTHANDLER         pCur     = (PPGMVIRTHANDLER)pNode;
    526     PPGMVIRTHANDLERTYPEINT  pCurType = PGMVIRTANDLER_GET_TYPE(pVM, pCur);
    527 
    528     Assert(pCurType->enmKind != PGMVIRTHANDLERKIND_HYPERVISOR); NOREF(pCurType);
    529 
    530 # if PGM_GST_TYPE == PGM_TYPE_32BIT
    531     PX86PD          pPDSrc = pgmGstGet32bitPDPtr(pVCpu);
    532 # endif
    533 
    534     RTGCPTR         GCPtr  = pCur->Core.Key;
    535 # if PGM_GST_TYPE != PGM_TYPE_AMD64
    536     /* skip all stuff above 4GB if not AMD64 mode. */
    537     if (RT_UNLIKELY(GCPtr >= _4G))
    538         return 0;
    539 # endif
    540 
    541     unsigned        offPage = GCPtr & PAGE_OFFSET_MASK;
    542     unsigned        iPage = 0;
    543     while (iPage < pCur->cPages)
    544     {
    545 # if PGM_GST_TYPE == PGM_TYPE_32BIT
    546         X86PDE      Pde = pPDSrc->a[GCPtr >> X86_PD_SHIFT];
    547 # elif PGM_GST_TYPE == PGM_TYPE_PAE
    548         X86PDEPAE   Pde = pgmGstGetPaePDE(pVCpu, GCPtr);
    549 # elif PGM_GST_TYPE == PGM_TYPE_AMD64
    550         X86PDEPAE   Pde = pgmGstGetLongModePDE(pVCpu, GCPtr);
    551 # endif
    552 # if PGM_GST_TYPE == PGM_TYPE_32BIT
    553         bool const  fBigPage = Pde.b.u1Size && (pState->cr4 & X86_CR4_PSE);
    554 # else
    555         bool const  fBigPage = Pde.b.u1Size;
    556 # endif
    557         if (    Pde.n.u1Present
    558             &&  (  !fBigPage
    559                  ? GST_IS_PDE_VALID(pVCpu, Pde)
    560                  : GST_IS_BIG_PDE_VALID(pVCpu, Pde)) )
    561         {
    562             if (!fBigPage)
    563             {
    564                 /*
    565                  * Normal page table.
    566                  */
    567                 PGSTPT pPT;
    568                 int rc = PGM_GCPHYS_2_PTR_V2(pVM, pVCpu, GST_GET_PDE_GCPHYS(Pde), &pPT);
    569                 if (RT_SUCCESS(rc))
    570                 {
    571                     for (unsigned iPTE = (GCPtr >> GST_PT_SHIFT) & GST_PT_MASK;
    572                          iPTE < RT_ELEMENTS(pPT->a) && iPage < pCur->cPages;
    573                          iPTE++, iPage++, GCPtr += PAGE_SIZE, offPage = 0)
    574                     {
    575                         GSTPTE      Pte = pPT->a[iPTE];
    576                         RTGCPHYS    GCPhysNew;
    577                         if (Pte.n.u1Present)
    578                             GCPhysNew = PGM_A20_APPLY(pVCpu, (RTGCPHYS)(pPT->a[iPTE].u & GST_PTE_PG_MASK) + offPage);
    579                         else
    580                             GCPhysNew = NIL_RTGCPHYS;
    581                         if (pCur->aPhysToVirt[iPage].Core.Key != GCPhysNew)
    582                         {
    583                             if (pCur->aPhysToVirt[iPage].Core.Key != NIL_RTGCPHYS)
    584                                 pgmHandlerVirtualClearPage(pVM, pCur, iPage);
    585 #ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
    586                             AssertReleaseMsg(!pCur->aPhysToVirt[iPage].offNextAlias,
    587                                              ("{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} GCPhysNew=%RGp\n",
    588                                               pCur->aPhysToVirt[iPage].Core.Key, pCur->aPhysToVirt[iPage].Core.KeyLast,
    589                                               pCur->aPhysToVirt[iPage].offVirtHandler, pCur->aPhysToVirt[iPage].offNextAlias, GCPhysNew));
    590 #endif
    591                             pCur->aPhysToVirt[iPage].Core.Key = GCPhysNew;
    592                             pState->fTodo |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;
    593                         }
    594                     }
    595                 }
    596                 else
    597                 {
    598                     /* not-present. */
    599                     offPage = 0;
    600                     AssertRC(rc);
    601                     for (unsigned iPTE = (GCPtr >> GST_PT_SHIFT) & GST_PT_MASK;
    602                          iPTE < RT_ELEMENTS(pPT->a) && iPage < pCur->cPages;
    603                          iPTE++, iPage++, GCPtr += PAGE_SIZE)
    604                     {
    605                         if (pCur->aPhysToVirt[iPage].Core.Key != NIL_RTGCPHYS)
    606                         {
    607                             pgmHandlerVirtualClearPage(pVM, pCur, iPage);
    608 #ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
    609                             AssertReleaseMsg(!pCur->aPhysToVirt[iPage].offNextAlias,
    610                                              ("{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
    611                                               pCur->aPhysToVirt[iPage].Core.Key, pCur->aPhysToVirt[iPage].Core.KeyLast,
    612                                               pCur->aPhysToVirt[iPage].offVirtHandler, pCur->aPhysToVirt[iPage].offNextAlias));
    613 #endif
    614                             pCur->aPhysToVirt[iPage].Core.Key = NIL_RTGCPHYS;
    615                             pState->fTodo |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;
    616                         }
    617                     }
    618                 }
    619             }
    620             else
    621             {
    622                 /*
    623                  * 2/4MB page.
    624                  */
    625                 RTGCPHYS GCPhys = (RTGCPHYS)GST_GET_PDE_GCPHYS(Pde);
    626                 for (unsigned i4KB = (GCPtr >> GST_PT_SHIFT) & GST_PT_MASK;
    627                      i4KB < PAGE_SIZE / sizeof(GSTPDE) && iPage < pCur->cPages;
    628                      i4KB++, iPage++, GCPtr += PAGE_SIZE, offPage = 0)
    629                 {
    630                     RTGCPHYS GCPhysNew = PGM_A20_APPLY(pVCpu, GCPhys + (i4KB << PAGE_SHIFT) + offPage);
    631                     if (pCur->aPhysToVirt[iPage].Core.Key != GCPhysNew)
    632                     {
    633                         if (pCur->aPhysToVirt[iPage].Core.Key != NIL_RTGCPHYS)
    634                             pgmHandlerVirtualClearPage(pVM, pCur, iPage);
    635 #ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
    636                         AssertReleaseMsg(!pCur->aPhysToVirt[iPage].offNextAlias,
    637                                          ("{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} GCPhysNew=%RGp\n",
    638                                           pCur->aPhysToVirt[iPage].Core.Key, pCur->aPhysToVirt[iPage].Core.KeyLast,
    639                                           pCur->aPhysToVirt[iPage].offVirtHandler, pCur->aPhysToVirt[iPage].offNextAlias, GCPhysNew));
    640 #endif
    641                         pCur->aPhysToVirt[iPage].Core.Key = GCPhysNew;
    642                         pState->fTodo |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;
    643                     }
    644                 }
    645             } /* pde type */
    646         }
    647         else
    648         {
    649             /* not-present / invalid. */
    650             Log(("VirtHandler: Not present / invalid Pde=%RX64\n", (uint64_t)Pde.u));
    651             for (unsigned cPages = (GST_PT_MASK + 1) - ((GCPtr >> GST_PT_SHIFT) & GST_PT_MASK);
    652                  cPages && iPage < pCur->cPages;
    653                  iPage++, GCPtr += PAGE_SIZE)
    654             {
    655                 if (pCur->aPhysToVirt[iPage].Core.Key != NIL_RTGCPHYS)
    656                 {
    657                     pgmHandlerVirtualClearPage(pVM, pCur, iPage);
    658                     pCur->aPhysToVirt[iPage].Core.Key = NIL_RTGCPHYS;
    659                     pState->fTodo |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;
    660                 }
    661             }
    662             offPage = 0;
    663         }
    664     } /* for pages in virtual mapping. */
    665 
    666     return 0;
    667 }
    668 #endif /* 32BIT, PAE and AMD64 + VBOX_WITH_RAW_MODE */
    669 
    670 
    671 /**
    672  * Updates the virtual page access handlers.
    673  *
    674  * @returns true if bits were flushed.
    675  * @returns false if bits weren't flushed.
    676  * @param   pVM     The cross context VM structure.
    677  * @param   cr4     The cr4 register value.
    678  */
    679 PGM_GST_DECL(bool, HandlerVirtualUpdate)(PVM pVM, uint32_t cr4)
    680 {
    681 #if (   PGM_GST_TYPE == PGM_TYPE_32BIT \
    682      || PGM_GST_TYPE == PGM_TYPE_PAE \
    683      || PGM_GST_TYPE == PGM_TYPE_AMD64) \
    684  && defined(VBOX_WITH_RAW_MODE)
    685 
    686     /** @todo
    687      * In theory this is not sufficient: the guest can change a single page in a range with invlpg
    688      */
    689 
    690     /*
    691      * Resolve any virtual address based access handlers to GC physical addresses.
    692      * This should be fairly quick.
    693      */
    694     RTUINT      fTodo = 0;
    695 
    696     pgmLock(pVM);
    697     STAM_PROFILE_START(&pVM->pgm.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,SyncCR3HandlerVirtualUpdate), a);
    698 
    699     for (VMCPUID i = 0; i < pVM->cCpus; i++)
    700     {
    701         PGMHVUSTATE State;
    702         PVMCPU      pVCpu = &pVM->aCpus[i];
    703 
    704         State.pVM   = pVM;
    705         State.pVCpu = pVCpu;
    706         State.fTodo = pVCpu->pgm.s.fSyncFlags;
    707         State.cr4   = cr4;
    708         RTAvlroGCPtrDoWithAll(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, true, PGM_GST_NAME(VirtHandlerUpdateOne), &State);
    709 
    710         fTodo |= State.fTodo;
    711     }
    712     STAM_PROFILE_STOP(&pVM->pgm.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,SyncCR3HandlerVirtualUpdate), a);
    713 
    714 
    715     /*
    716      * Set / reset bits?
    717      */
    718     if (fTodo & PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL)
    719     {
    720         STAM_PROFILE_START(&pVM->pgm.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,SyncCR3HandlerVirtualReset), b);
    721         Log(("HandlerVirtualUpdate: resets bits\n"));
    722         RTAvlroGCPtrDoWithAll(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, true, pgmHandlerVirtualResetOne, pVM);
    723 
    724         for (VMCPUID i = 0; i < pVM->cCpus; i++)
    725         {
    726             PVMCPU pVCpu = &pVM->aCpus[i];
    727             pVCpu->pgm.s.fSyncFlags &= ~PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;
    728         }
    729 
    730         STAM_PROFILE_STOP(&pVM->pgm.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,SyncCR3HandlerVirtualReset), b);
    731     }
    732     pgmUnlock(pVM);
    733 
    734     return !!(fTodo & PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL);
    735 
    736 #else /* real / protected */
    737     NOREF(pVM); NOREF(cr4);
    738     return false;
    739 #endif
    740 }
    741 
    742 
    743508#ifdef IN_RING3
    744509/**
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