VirtualBox

Changeset 80163 in vbox


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

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

Location:
trunk
Files:
15 edited

Legend:

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

    r79630 r80163  
    9898/** The VM has been restored. */
    9999#define VERR_VM_RESTORED                    (-1025)
     100/** The requested feature is not supported by NEM. */
     101#define VERR_NOT_SUP_BY_NEM                 (-1026)
    100102/** @} */
    101103
  • trunk/include/VBox/vmm/pgm.h

    r80118 r80163  
    471471VMMDECL(int)        PGMHandlerPhysicalReset(PVM pVM, RTGCPHYS GCPhys);
    472472VMMDECL(bool)       PGMHandlerPhysicalIsRegistered(PVM pVM, RTGCPHYS GCPhys);
    473 
    474 /** PGM virtual access handler type registration handle (heap offset, valid
    475  * cross contexts without needing fixing up).  Callbacks and handler type is
    476  * associated with this and it is shared by all handler registrations. */
    477 typedef uint32_t PGMVIRTHANDLERTYPE;
    478 /** Pointer to a PGM virtual handler type registration handle. */
    479 typedef PGMVIRTHANDLERTYPE *PPGMVIRTHANDLERTYPE;
    480 /** NIL value for PGM virtual access handler type handle. */
    481 #define NIL_PGMVIRTHANDLERTYPE  UINT32_MAX
    482 #ifdef VBOX_WITH_RAW_MODE
    483 VMM_INT_DECL(uint32_t) PGMHandlerVirtualTypeRelease(PVM pVM, PGMVIRTHANDLERTYPE hType);
    484 VMM_INT_DECL(uint32_t) PGMHandlerVirtualTypeRetain(PVM pVM, PGMVIRTHANDLERTYPE hType);
    485 VMM_INT_DECL(bool)     PGMHandlerVirtualIsRegistered(PVM pVM, RTGCPTR GCPtr);
    486 #endif
    487473
    488474
     
    878864                                                     const char *pszDesc,
    879865                                                     PPGMPHYSHANDLERTYPE phType);
    880 #ifdef VBOX_WITH_RAW_MODE
    881 VMMR3_INT_DECL(int) PGMR3HandlerVirtualTypeRegisterEx(PVM pVM, PGMVIRTHANDLERKIND enmKind, bool fRelocUserRC,
    882                                                       PFNPGMR3VIRTINVALIDATE pfnInvalidateR3,
    883                                                       PFNPGMVIRTHANDLER pfnHandlerR3,
    884                                                       RCPTRTYPE(FNPGMVIRTHANDLER) pfnHandlerRC,
    885                                                       RCPTRTYPE(FNPGMRCVIRTPFHANDLER) pfnPfHandlerRC,
    886                                                       const char *pszDesc, PPGMVIRTHANDLERTYPE phType);
    887 VMMR3_INT_DECL(int) PGMR3HandlerVirtualTypeRegister(PVM pVM, PGMVIRTHANDLERKIND enmKind, bool fRelocUserRC,
    888                                                     PFNPGMR3VIRTINVALIDATE pfnInvalidateR3,
    889                                                     PFNPGMVIRTHANDLER pfnHandlerR3,
    890                                                     const char *pszHandlerRC, const char *pszPfHandlerRC, const char *pszDesc,
    891                                                     PPGMVIRTHANDLERTYPE phType);
    892 VMMR3_INT_DECL(int) PGMR3HandlerVirtualRegister(PVM pVM, PVMCPU pVCpu, PGMVIRTHANDLERTYPE hType, RTGCPTR GCPtr,
    893                                                 RTGCPTR GCPtrLast, void *pvUserR3, RTRCPTR pvUserRC, const char *pszDesc);
    894 VMMR3_INT_DECL(int) PGMHandlerVirtualChangeType(PVM pVM, RTGCPTR GCPtr, PGMVIRTHANDLERTYPE hNewType);
    895 VMMR3_INT_DECL(int) PGMHandlerVirtualDeregister(PVM pVM, PVMCPU pVCpu, RTGCPTR GCPtr, bool fHypervisor);
    896 #endif
    897866VMMR3DECL(int)      PGMR3PoolGrow(PVM pVM);
    898867
  • trunk/src/VBox/VMM/VMMAll/PGMAll.cpp

    r80118 r80163  
    4545#include <VBox/param.h>
    4646#include <VBox/err.h>
    47 
    48 
    49 /*********************************************************************************************************************************
    50 *   Structures and Typedefs                                                                                                      *
    51 *********************************************************************************************************************************/
    52 /**
    53  * Stated structure for PGM_GST_NAME(HandlerVirtualUpdate) that's
    54  * passed to PGM_GST_NAME(VirtHandlerUpdateOne) during enumeration.
    55  */
    56 typedef struct PGMHVUSTATE
    57 {
    58     /** Pointer to the VM. */
    59     PVM         pVM;
    60     /** Pointer to the VMCPU. */
    61     PVMCPU      pVCpu;
    62     /** The todo flags. */
    63     RTUINT      fTodo;
    64     /** The CR4 register value. */
    65     uint32_t    cr4;
    66 } PGMHVUSTATE,  *PPGMHVUSTATE;
    6747
    6848
     
    36183598            static const char s_achHandlerStates[4] = { '-', 't', 'w', 'a' };
    36193599            szTmp[cch++] = s_achHandlerStates[PGM_PAGE_GET_HNDL_PHYS_STATE(pPage)];
    3620             szTmp[cch++] = s_achHandlerStates[PGM_PAGE_GET_HNDL_VIRT_STATE(pPage)];
    36213600        }
    36223601
  • trunk/src/VBox/VMM/VMMAll/PGMAllBth.h

    r80134 r80163  
    369369        }
    370370    }
    371 # if PGM_WITH_PAGING(PGM_GST_TYPE, PGM_SHW_TYPE) && !defined(IN_RING0)
    372     else
    373     {
    374 #  ifdef PGM_SYNC_N_PAGES
    375         /*
    376          * If the region is write protected and we got a page not present fault, then sync
    377          * the pages. If the fault was caused by a read, then restart the instruction.
    378          * In case of write access continue to the GC write handler.
    379          */
    380         if (    PGM_PAGE_GET_HNDL_VIRT_STATE(pPage) < PGM_PAGE_HNDL_PHYS_STATE_ALL
    381             && !(uErr & X86_TRAP_PF_P))
    382         {
    383             rcStrict = PGM_BTH_NAME(SyncPage)(pVCpu, pGstWalk->Pde, pvFault, PGM_SYNC_NR_PAGES, uErr);
    384             if (    RT_FAILURE(rcStrict)
    385                 ||  rcStrict == VINF_PGM_SYNCPAGE_MODIFIED_PDE
    386                 ||  !(uErr & X86_TRAP_PF_RW))
    387             {
    388                 AssertRC(rcStrict);
    389                 STAM_COUNTER_INC(&pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0eHandlersOutOfSync);
    390                 STAM_STATS({ pVCpu->pgm.s.CTX_SUFF(pStatTrap0eAttribution) = &pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0eTime2OutOfSyncHndVirt; });
    391                 return rcStrict;
    392             }
    393         }
    394 #  endif
    395         /*
    396          * Ok, it's an virtual page access handler.
    397          *
    398          * Since it's faster to search by address, we'll do that first
    399          * and then retry by GCPhys if that fails.
    400          */
    401         /** @todo r=bird: perhaps we should consider looking up by physical address directly now?
    402          * r=svl: true, but lookup on virtual address should remain as a fallback as phys & virt trees might be
    403          *        out of sync, because the page was changed without us noticing it (not-present -> present
    404          *        without invlpg or mov cr3, xxx).
    405          */
    406         PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrRangeGet(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, pvFault);
    407         if (pCur)
    408         {
    409             PPGMVIRTHANDLERTYPEINT pCurType = PGMVIRTANDLER_GET_TYPE(pVM, pCur);
    410             AssertMsg(!(pvFault - pCur->Core.Key < pCur->cb)
    411                       || (     pCurType->enmKind != PGMVIRTHANDLERKIND_WRITE
    412                            || !(uErr & X86_TRAP_PF_P)
    413                            || (pCurType->enmKind == PGMVIRTHANDLERKIND_WRITE && (uErr & X86_TRAP_PF_RW))),
    414                       ("Unexpected trap for virtual handler: %RGv (phys=%RGp) pPage=%R[pgmpage] uErr=%X, enumKind=%d\n",
    415                        pvFault, pGstWalk->Core.GCPhys, pPage, uErr, pCurType->enmKind));
    416 
    417             if (    pvFault - pCur->Core.Key < pCur->cb
    418                 &&  (    uErr & X86_TRAP_PF_RW
    419                      ||  pCurType->enmKind != PGMVIRTHANDLERKIND_WRITE ) )
    420             {
    421 #   ifdef IN_RC
    422                 STAM_PROFILE_START(&pCur->Stat, h);
    423                 RTGCPTR GCPtrStart = pCur->Core.Key;
    424                 void *pvUser = pCur->CTX_SUFF(pvUser);
    425                 pgmUnlock(pVM);
    426                 *pfLockTaken = false;
    427 
    428                 rcStrict = pCurType->CTX_SUFF(pfnPfHandler)(pVM, pVCpu, uErr, pRegFrame, pvFault, GCPtrStart,
    429                                                             pvFault - GCPtrStart, pvUser);
    430 
    431 #    ifdef VBOX_WITH_STATISTICS
    432                 pgmLock(pVM);
    433                 pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrRangeGet(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, pvFault);
    434                 if (pCur)
    435                     STAM_PROFILE_STOP(&pCur->Stat, h);
    436                 pgmUnlock(pVM);
    437 #    endif
    438 #   else
    439                 rcStrict = VINF_EM_RAW_EMULATE_INSTR; /** @todo for VMX */
    440 #   endif
    441                 STAM_COUNTER_INC(&pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0eHandlersVirtual);
    442                 STAM_STATS({ pVCpu->pgm.s.CTX_SUFF(pStatTrap0eAttribution) = &pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0eTime2HndVirt; });
    443                 return rcStrict;
    444             }
    445             /* Unhandled part of a monitored page */
    446             Log(("Unhandled part of monitored page %RGv\n", pvFault));
    447         }
    448         else
    449         {
    450            /* Check by physical address. */
    451             unsigned iPage;
    452             pCur = pgmHandlerVirtualFindByPhysAddr(pVM, pGstWalk->Core.GCPhys, &iPage);
    453             if (pCur)
    454             {
    455                 PPGMVIRTHANDLERTYPEINT pCurType = PGMVIRTANDLER_GET_TYPE(pVM, pCur);
    456                 if  (   uErr & X86_TRAP_PF_RW
    457                      || pCurType->enmKind != PGMVIRTHANDLERKIND_WRITE )
    458                 {
    459                     Assert(   (pCur->aPhysToVirt[iPage].Core.Key & X86_PTE_PAE_PG_MASK)
    460                            == (pGstWalk->Core.GCPhys & X86_PTE_PAE_PG_MASK));
    461 #   ifdef IN_RC
    462                     STAM_PROFILE_START(&pCur->Stat, h);
    463                     RTGCPTR GCPtrStart = pCur->Core.Key;
    464                     void *pvUser = pCur->CTX_SUFF(pvUser);
    465                     pgmUnlock(pVM);
    466                     *pfLockTaken = false;
    467 
    468                     RTGCPTR off = (iPage << PAGE_SHIFT)
    469                                 + (pvFault    & PAGE_OFFSET_MASK)
    470                                 - (GCPtrStart & PAGE_OFFSET_MASK);
    471                     Assert(off < pCur->cb);
    472                     rcStrict = pCurType->CTX_SUFF(pfnPfHandler)(pVM, pVCpu, uErr, pRegFrame, pvFault, GCPtrStart, off, pvUser);
    473 
    474 #    ifdef VBOX_WITH_STATISTICS
    475                     pgmLock(pVM);
    476                     pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrRangeGet(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, GCPtrStart);
    477                     if (pCur)
    478                         STAM_PROFILE_STOP(&pCur->Stat, h);
    479                     pgmUnlock(pVM);
    480 #    endif
    481 #   else
    482                     rcStrict = VINF_EM_RAW_EMULATE_INSTR; /** @todo for VMX */
    483 #   endif
    484                     STAM_COUNTER_INC(&pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0eHandlersVirtualByPhys);
    485                     STAM_STATS({ pVCpu->pgm.s.CTX_SUFF(pStatTrap0eAttribution) = &pVCpu->pgm.s.CTX_SUFF(pStats)->StatRZTrap0eTime2HndVirt; });
    486                     return rcStrict;
    487                 }
    488             }
    489         }
    490     }
    491 #  endif /* PGM_WITH_PAGING(PGM_GST_TYPE, PGM_SHW_TYPE) */
    492371
    493372    /*
     
    38153694
    38163695#if !PGM_TYPE_IS_NESTED_OR_EPT(PGM_SHW_TYPE) && PGM_SHW_TYPE != PGM_TYPE_NONE
    3817 
     3696# ifdef PGMPOOL_WITH_OPTIMIZED_DIRTY_PT
    38183697    pgmLock(pVM);
    3819 
    3820 # ifdef PGMPOOL_WITH_OPTIMIZED_DIRTY_PT
    38213698    PPGMPOOL pPool = pVM->pgm.s.CTX_SUFF(pPool);
    38223699    if (pPool->cDirtyPages)
    38233700        pgmPoolResetDirtyPages(pVM);
    3824 # endif
    3825 
    3826     /*
    3827      * Update page access handlers.
    3828      * The virtual are always flushed, while the physical are only on demand.
    3829      * WARNING: We are incorrectly not doing global flushing on Virtual Handler updates. We'll
    3830      *          have to look into that later because it will have a bad influence on the performance.
    3831      * @note SvL: There's no need for that. Just invalidate the virtual range(s).
    3832      *      bird: Yes, but that won't work for aliases.
    3833      */
    3834     /** @todo this MUST go away. See @bugref{1557}. */
    3835     STAM_PROFILE_START(&pVCpu->pgm.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,SyncCR3Handlers), h);
    3836     PGM_GST_NAME(HandlerVirtualUpdate)(pVM, cr4);
    3837     STAM_PROFILE_STOP(&pVCpu->pgm.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,SyncCR3Handlers), h);
    38383701    pgmUnlock(pVM);
     3702# endif
    38393703#endif /* !NESTED && !EPT */
    38403704
  • 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/**
  • trunk/src/VBox/VMM/VMMAll/PGMAllHandler.cpp

    r76993 r80163  
    16661666}
    16671667
    1668 
    1669 #ifdef VBOX_WITH_RAW_MODE
    1670 
    1671 /**
    1672  * Internal worker for releasing a virtual handler type registration reference.
    1673  *
    1674  * @returns New reference count. UINT32_MAX if invalid input (asserted).
    1675  * @param   pVM         The cross context VM structure.
    1676  * @param   pType       Pointer to the type registration.
    1677  */
    1678 DECLINLINE(uint32_t) pgmHandlerVirtualTypeRelease(PVM pVM, PPGMVIRTHANDLERTYPEINT pType)
    1679 {
    1680     AssertMsgReturn(pType->u32Magic == PGMVIRTHANDLERTYPEINT_MAGIC, ("%#x\n", pType->u32Magic), UINT32_MAX);
    1681     uint32_t cRefs = ASMAtomicDecU32(&pType->cRefs);
    1682     if (cRefs == 0)
    1683     {
    1684         pgmLock(pVM);
    1685         pType->u32Magic = PGMVIRTHANDLERTYPEINT_MAGIC_DEAD;
    1686         RTListOff32NodeRemove(&pType->ListNode);
    1687         pgmUnlock(pVM);
    1688         MMHyperFree(pVM, pType);
    1689     }
    1690     return cRefs;
    1691 }
    1692 
    1693 
    1694 /**
    1695  * Internal worker for retaining a virtual handler type registration reference.
    1696  *
    1697  * @returns New reference count. UINT32_MAX if invalid input (asserted).
    1698  * @param   pVM         The cross context VM structure.
    1699  * @param   pType       Pointer to the type registration.
    1700  */
    1701 DECLINLINE(uint32_t) pgmHandlerVirtualTypeRetain(PVM pVM, PPGMVIRTHANDLERTYPEINT pType)
    1702 {
    1703     NOREF(pVM);
    1704     AssertMsgReturn(pType->u32Magic == PGMVIRTHANDLERTYPEINT_MAGIC, ("%#x\n", pType->u32Magic), UINT32_MAX);
    1705     uint32_t cRefs = ASMAtomicIncU32(&pType->cRefs);
    1706     Assert(cRefs < _1M && cRefs > 0);
    1707     return cRefs;
    1708 }
    1709 
    1710 
    1711 /**
    1712  * Releases a reference to a virtual handler type registration.
    1713  *
    1714  * @returns New reference count. UINT32_MAX if invalid input (asserted).
    1715  * @param   pVM         The cross context VM structure.
    1716  * @param   hType       The type regiration handle.
    1717  */
    1718 VMM_INT_DECL(uint32_t) PGMHandlerVirtualTypeRelease(PVM pVM, PGMVIRTHANDLERTYPE hType)
    1719 {
    1720     if (hType != NIL_PGMVIRTHANDLERTYPE)
    1721         return pgmHandlerVirtualTypeRelease(pVM, PGMVIRTHANDLERTYPEINT_FROM_HANDLE(pVM, hType));
    1722     return 0;
    1723 }
    1724 
    1725 
    1726 /**
    1727  * Retains a reference to a virtual handler type registration.
    1728  *
    1729  * @returns New reference count. UINT32_MAX if invalid input (asserted).
    1730  * @param   pVM         The cross context VM structure.
    1731  * @param   hType       The type regiration handle.
    1732  */
    1733 VMM_INT_DECL(uint32_t) PGMHandlerVirtualTypeRetain(PVM pVM, PGMVIRTHANDLERTYPE hType)
    1734 {
    1735     return pgmHandlerVirtualTypeRetain(pVM, PGMVIRTHANDLERTYPEINT_FROM_HANDLE(pVM, hType));
    1736 }
    1737 
    1738 
    1739 /**
    1740  * Check if particular guest's VA is being monitored.
    1741  *
    1742  * @returns true or false
    1743  * @param   pVM             The cross context VM structure.
    1744  * @param   GCPtr           Virtual address.
    1745  * @remarks Will acquire the PGM lock.
    1746  * @thread  Any.
    1747  */
    1748 VMM_INT_DECL(bool) PGMHandlerVirtualIsRegistered(PVM pVM, RTGCPTR GCPtr)
    1749 {
    1750     pgmLock(pVM);
    1751     PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrGet(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, GCPtr);
    1752     pgmUnlock(pVM);
    1753 
    1754     return pCur != NULL;
    1755 }
    1756 
    1757 
    1758 /**
    1759  * Search for virtual handler with matching physical address
    1760  *
    1761  * @returns Pointer to the virtual handler structure if found, otherwise NULL.
    1762  * @param   pVM         The cross context VM structure.
    1763  * @param   GCPhys      GC physical address to search for.
    1764  * @param   piPage      Where to store the pointer to the index of the cached physical page.
    1765  */
    1766 PPGMVIRTHANDLER pgmHandlerVirtualFindByPhysAddr(PVM pVM, RTGCPHYS GCPhys, unsigned *piPage)
    1767 {
    1768     STAM_PROFILE_START(&pVM->pgm.s.CTX_MID_Z(Stat,VirtHandlerSearchByPhys), a);
    1769 
    1770     pgmLock(pVM);
    1771     PPGMPHYS2VIRTHANDLER pCur;
    1772     pCur = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, GCPhys);
    1773     if (pCur)
    1774     {
    1775         /* found a match! */
    1776         PPGMVIRTHANDLER pVirt = (PPGMVIRTHANDLER)((uintptr_t)pCur + pCur->offVirtHandler);
    1777         *piPage = pCur - &pVirt->aPhysToVirt[0];
    1778         pgmUnlock(pVM);
    1779 
    1780 #ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
    1781         AssertRelease(pCur->offNextAlias & PGMPHYS2VIRTHANDLER_IS_HEAD);
    1782 #endif
    1783         LogFlow(("PHYS2VIRT: found match for %RGp -> %RGv *piPage=%#x\n", GCPhys, pVirt->Core.Key, *piPage));
    1784         STAM_PROFILE_STOP(&pVM->pgm.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,VirtHandlerSearchByPhys), a);
    1785         return pVirt;
    1786     }
    1787 
    1788     pgmUnlock(pVM);
    1789     STAM_PROFILE_STOP(&pVM->pgm.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,VirtHandlerSearchByPhys), a);
    1790     return NULL;
    1791 }
    1792 
    1793 
    1794 /**
    1795  * Deal with aliases in phys2virt.
    1796  *
    1797  * As pointed out by the various todos, this currently only deals with
    1798  * aliases where the two ranges match 100%.
    1799  *
    1800  * @param   pVM             The cross context VM structure.
    1801  * @param   pPhys2Virt      The node we failed insert.
    1802  */
    1803 static void pgmHandlerVirtualInsertAliased(PVM pVM, PPGMPHYS2VIRTHANDLER pPhys2Virt)
    1804 {
    1805     /*
    1806      * First find the node which is conflicting with us.
    1807      */
    1808     /** @todo Deal with partial overlapping. (Unlikely situation, so I'm too lazy to do anything about it now.) */
    1809     /** @todo check if the current head node covers the ground we do. This is highly unlikely
    1810      * and I'm too lazy to implement this now as it will require sorting the list and stuff like that. */
    1811     PPGMPHYS2VIRTHANDLER pHead = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key);
    1812 #ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
    1813     AssertReleaseMsg(pHead != pPhys2Virt, ("%RGp-%RGp offVirtHandler=%#RX32\n",
    1814                                            pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler));
    1815 #endif
    1816     if (RT_UNLIKELY(!pHead || pHead->Core.KeyLast != pPhys2Virt->Core.KeyLast))
    1817     {
    1818         /** @todo do something clever here... */
    1819         LogRel(("pgmHandlerVirtualInsertAliased: %RGp-%RGp\n", pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast));
    1820         pPhys2Virt->offNextAlias = 0;
    1821         return;
    1822     }
    1823 
    1824     /*
    1825      * Insert ourselves as the next node.
    1826      */
    1827     if (!(pHead->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK))
    1828         pPhys2Virt->offNextAlias = PGMPHYS2VIRTHANDLER_IN_TREE;
    1829     else
    1830     {
    1831         PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pHead + (pHead->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
    1832         pPhys2Virt->offNextAlias = ((intptr_t)pNext - (intptr_t)pPhys2Virt)
    1833                                  | PGMPHYS2VIRTHANDLER_IN_TREE;
    1834     }
    1835     pHead->offNextAlias = ((intptr_t)pPhys2Virt - (intptr_t)pHead)
    1836                         | (pHead->offNextAlias & ~PGMPHYS2VIRTHANDLER_OFF_MASK);
    1837     Log(("pgmHandlerVirtualInsertAliased: %RGp-%RGp offNextAlias=%#RX32\n", pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offNextAlias));
    1838 }
    1839 
    1840 
    1841 /**
    1842  * Resets one virtual handler range.
    1843  *
    1844  * This is called by HandlerVirtualUpdate when it has detected some kind of
    1845  * problem and have started clearing the virtual handler page states (or
    1846  * when there have been registration/deregistrations). For this reason this
    1847  * function will only update the page status if it's lower than desired.
    1848  *
    1849  * @returns 0
    1850  * @param   pNode   Pointer to a PGMVIRTHANDLER.
    1851  * @param   pvUser  Pointer to the VM.
    1852  */
    1853 DECLCALLBACK(int) pgmHandlerVirtualResetOne(PAVLROGCPTRNODECORE pNode, void *pvUser)
    1854 {
    1855     PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)pNode;
    1856     PVM             pVM = (PVM)pvUser;
    1857 
    1858     PGM_LOCK_ASSERT_OWNER(pVM);
    1859 
    1860     /*
    1861      * Iterate the pages and apply the new state.
    1862      */
    1863     uint32_t        uState   = PGMVIRTANDLER_GET_TYPE(pVM, pCur)->uState;
    1864     PPGMRAMRANGE    pRamHint = NULL;
    1865     RTGCUINTPTR     offPage  = ((RTGCUINTPTR)pCur->Core.Key & PAGE_OFFSET_MASK);
    1866     RTGCUINTPTR     cbLeft   = pCur->cb;
    1867     for (unsigned iPage = 0; iPage < pCur->cPages; iPage++)
    1868     {
    1869         PPGMPHYS2VIRTHANDLER pPhys2Virt = &pCur->aPhysToVirt[iPage];
    1870         if (pPhys2Virt->Core.Key != NIL_RTGCPHYS)
    1871         {
    1872             /*
    1873              * Update the page state wrt virtual handlers.
    1874              */
    1875             PPGMPAGE pPage;
    1876             int rc = pgmPhysGetPageWithHintEx(pVM, pPhys2Virt->Core.Key, &pPage, &pRamHint);
    1877             if (    RT_SUCCESS(rc)
    1878                 &&  PGM_PAGE_GET_HNDL_VIRT_STATE(pPage) < uState)
    1879                 PGM_PAGE_SET_HNDL_VIRT_STATE(pPage, uState);
    1880             else
    1881                 AssertRC(rc);
    1882 
    1883             /*
    1884              * Need to insert the page in the Phys2Virt lookup tree?
    1885              */
    1886             if (pPhys2Virt->Core.KeyLast == NIL_RTGCPHYS)
    1887             {
    1888 #ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
    1889                 AssertRelease(!pPhys2Virt->offNextAlias);
    1890 #endif
    1891                 unsigned cbPhys = cbLeft;
    1892                 if (cbPhys > PAGE_SIZE - offPage)
    1893                     cbPhys = PAGE_SIZE - offPage;
    1894                 else
    1895                     Assert(iPage == pCur->cPages - 1);
    1896                 pPhys2Virt->Core.KeyLast = pPhys2Virt->Core.Key + cbPhys - 1; /* inclusive */
    1897                 pPhys2Virt->offNextAlias = PGMPHYS2VIRTHANDLER_IS_HEAD | PGMPHYS2VIRTHANDLER_IN_TREE;
    1898                 if (!RTAvlroGCPhysInsert(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, &pPhys2Virt->Core))
    1899                     pgmHandlerVirtualInsertAliased(pVM, pPhys2Virt);
    1900 #ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
    1901                 else
    1902                     AssertReleaseMsg(RTAvlroGCPhysGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key) == &pPhys2Virt->Core,
    1903                                      ("%RGp-%RGp offNextAlias=%#RX32\n",
    1904                                       pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offNextAlias));
    1905 #endif
    1906                 Log2(("PHYS2VIRT: Insert physical range %RGp-%RGp offNextAlias=%#RX32 %s\n",
    1907                       pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offNextAlias, R3STRING(pCur->pszDesc)));
    1908             }
    1909         }
    1910         cbLeft -= PAGE_SIZE - offPage;
    1911         offPage = 0;
    1912     }
    1913 
    1914     return 0;
    1915 }
    1916 
    1917 # if defined(VBOX_STRICT) || defined(LOG_ENABLED)
    1918 
    1919 /**
    1920  * Worker for pgmHandlerVirtualDumpPhysPages.
    1921  *
    1922  * @returns 0 (continue enumeration).
    1923  * @param   pNode       The virtual handler node.
    1924  * @param   pvUser      User argument, unused.
    1925  */
    1926 static DECLCALLBACK(int) pgmHandlerVirtualDumpPhysPagesCallback(PAVLROGCPHYSNODECORE pNode, void *pvUser)
    1927 {
    1928     PPGMPHYS2VIRTHANDLER pCur = (PPGMPHYS2VIRTHANDLER)pNode;
    1929     PPGMVIRTHANDLER      pVirt = (PPGMVIRTHANDLER)((uintptr_t)pCur + pCur->offVirtHandler);
    1930     NOREF(pvUser); NOREF(pVirt);
    1931 
    1932     Log(("PHYS2VIRT: Range %RGp-%RGp for virtual handler: %s\n", pCur->Core.Key, pCur->Core.KeyLast, pVirt->pszDesc));
    1933     return 0;
    1934 }
    1935 
    1936 
    1937 /**
    1938  * Assertion / logging helper for dumping all the
    1939  * virtual handlers to the log.
    1940  *
    1941  * @param   pVM         The cross context VM structure.
    1942  */
    1943 void pgmHandlerVirtualDumpPhysPages(PVM pVM)
    1944 {
    1945     RTAvlroGCPhysDoWithAll(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, true /* from left */,
    1946                            pgmHandlerVirtualDumpPhysPagesCallback, 0);
    1947 }
    1948 
    1949 # endif /* VBOX_STRICT || LOG_ENABLED */
    1950 #endif /* VBOX_WITH_RAW_MODE */
    19511668#ifdef VBOX_STRICT
    19521669
     
    19591676    /** The current physical address. */
    19601677    RTGCPHYS    GCPhys;
    1961     /** The state we've calculated. */
    1962     unsigned    uVirtStateFound;
    1963     /** The state we're matching up to. */
    1964     unsigned    uVirtState;
    19651678    /** Number of errors. */
    19661679    unsigned    cErrors;
     
    19691682} PGMAHAFIS, *PPGMAHAFIS;
    19701683
    1971 # ifdef VBOX_WITH_RAW_MODE
    1972 
    1973 #  if 0 /* unused */
    1974 /**
    1975  * Verify virtual handler by matching physical address.
    1976  *
    1977  * @returns 0
    1978  * @param   pNode   Pointer to a PGMVIRTHANDLER.
    1979  * @param   pvUser  Pointer to user parameter.
    1980  */
    1981 static DECLCALLBACK(int) pgmHandlerVirtualVerifyOneByPhysAddr(PAVLROGCPTRNODECORE pNode, void *pvUser)
    1982 {
    1983     PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)pNode;
    1984     PPGMAHAFIS      pState = (PPGMAHAFIS)pvUser;
    1985 
    1986     for (unsigned iPage = 0; iPage < pCur->cPages; iPage++)
    1987     {
    1988         if ((pCur->aPhysToVirt[iPage].Core.Key & X86_PTE_PAE_PG_MASK) == pState->GCPhys)
    1989         {
    1990             unsigned uState = pgmHandlerVirtualCalcState(pCur);
    1991             if (pState->uVirtState < uState)
    1992             {
    1993                 error
    1994             }
    1995 
    1996             if (pState->uVirtState == uState)
    1997                 break; //??
    1998         }
    1999     }
    2000     return 0;
    2001 }
    2002 #  endif /* unused */
    2003 
    2004 
    2005 /**
    2006  * Verify a virtual handler (enumeration callback).
    2007  *
    2008  * Called by PGMAssertHandlerAndFlagsInSync to check the sanity of all
    2009  * the virtual handlers, esp. that the physical addresses matches up.
    2010  *
    2011  * @returns 0
    2012  * @param   pNode   Pointer to a PGMVIRTHANDLER.
    2013  * @param   pvUser  Pointer to a PPGMAHAFIS structure.
    2014  */
    2015 static DECLCALLBACK(int) pgmHandlerVirtualVerifyOne(PAVLROGCPTRNODECORE pNode, void *pvUser)
    2016 {
    2017     PPGMAHAFIS              pState  = (PPGMAHAFIS)pvUser;
    2018     PVM                     pVM     = pState->pVM;
    2019     PPGMVIRTHANDLER         pVirt   = (PPGMVIRTHANDLER)pNode;
    2020     PPGMVIRTHANDLERTYPEINT  pType   = PGMVIRTANDLER_GET_TYPE(pVM, pVirt);
    2021 
    2022     /*
    2023      * Validate the type and calc state.
    2024      */
    2025     switch (pType->enmKind)
    2026     {
    2027         case PGMVIRTHANDLERKIND_WRITE:
    2028         case PGMVIRTHANDLERKIND_ALL:
    2029             break;
    2030         default:
    2031             AssertMsgFailed(("unknown/wrong enmKind=%d\n", pType->enmKind));
    2032             pState->cErrors++;
    2033             return 0;
    2034     }
    2035     const uint32_t uState = pType->uState;
    2036 
    2037     /*
    2038      * Check key alignment.
    2039      */
    2040     if (    (pVirt->aPhysToVirt[0].Core.Key & PAGE_OFFSET_MASK) != ((RTGCUINTPTR)pVirt->Core.Key & PAGE_OFFSET_MASK)
    2041         &&  pVirt->aPhysToVirt[0].Core.Key != NIL_RTGCPHYS)
    2042     {
    2043         AssertMsgFailed(("virt handler phys has incorrect key! %RGp %RGv %s\n",
    2044                          pVirt->aPhysToVirt[0].Core.Key, pVirt->Core.Key, R3STRING(pVirt->pszDesc)));
    2045         pState->cErrors++;
    2046     }
    2047 
    2048     if (    (pVirt->aPhysToVirt[pVirt->cPages - 1].Core.KeyLast & PAGE_OFFSET_MASK) != ((RTGCUINTPTR)pVirt->Core.KeyLast & PAGE_OFFSET_MASK)
    2049         &&  pVirt->aPhysToVirt[pVirt->cPages - 1].Core.Key != NIL_RTGCPHYS)
    2050     {
    2051         AssertMsgFailed(("virt handler phys has incorrect key! %RGp %RGv %s\n",
    2052                          pVirt->aPhysToVirt[pVirt->cPages - 1].Core.KeyLast, pVirt->Core.KeyLast, R3STRING(pVirt->pszDesc)));
    2053         pState->cErrors++;
    2054     }
    2055 
    2056     /*
    2057      * Check pages for sanity and state.
    2058      */
    2059     RTGCUINTPTR   GCPtr = (RTGCUINTPTR)pVirt->Core.Key;
    2060     for (unsigned iPage = 0; iPage < pVirt->cPages; iPage++, GCPtr += PAGE_SIZE)
    2061     {
    2062         for (VMCPUID i = 0; i < pVM->cCpus; i++)
    2063         {
    2064             PVMCPU pVCpu = &pVM->aCpus[i];
    2065 
    2066             RTGCPHYS   GCPhysGst;
    2067             uint64_t   fGst;
    2068             int rc = PGMGstGetPage(pVCpu, (RTGCPTR)GCPtr, &fGst, &GCPhysGst);
    2069             if (    rc == VERR_PAGE_NOT_PRESENT
    2070                 ||  rc == VERR_PAGE_TABLE_NOT_PRESENT)
    2071             {
    2072                 if (pVirt->aPhysToVirt[iPage].Core.Key != NIL_RTGCPHYS)
    2073                 {
    2074                     AssertMsgFailed(("virt handler phys out of sync. %RGp GCPhysNew=~0 iPage=%#x %RGv %s\n",
    2075                                     pVirt->aPhysToVirt[iPage].Core.Key, iPage, GCPtr, R3STRING(pVirt->pszDesc)));
    2076                     pState->cErrors++;
    2077                 }
    2078                 continue;
    2079             }
    2080 
    2081             AssertRCReturn(rc, 0);
    2082             if ((pVirt->aPhysToVirt[iPage].Core.Key & X86_PTE_PAE_PG_MASK) != GCPhysGst)
    2083             {
    2084                 AssertMsgFailed(("virt handler phys out of sync. %RGp GCPhysGst=%RGp iPage=%#x %RGv %s\n",
    2085                                 pVirt->aPhysToVirt[iPage].Core.Key, GCPhysGst, iPage, GCPtr, R3STRING(pVirt->pszDesc)));
    2086                 pState->cErrors++;
    2087                 continue;
    2088             }
    2089 
    2090             PPGMPAGE pPage = pgmPhysGetPage(pVM, GCPhysGst);
    2091             if (!pPage)
    2092             {
    2093                 AssertMsgFailed(("virt handler getting ram flags. GCPhysGst=%RGp iPage=%#x %RGv %s\n",
    2094                                 GCPhysGst, iPage, GCPtr, R3STRING(pVirt->pszDesc)));
    2095                 pState->cErrors++;
    2096                 continue;
    2097             }
    2098 
    2099             if (PGM_PAGE_GET_HNDL_VIRT_STATE(pPage) < uState)
    2100             {
    2101                 AssertMsgFailed(("virt handler state mismatch. pPage=%R[pgmpage] GCPhysGst=%RGp iPage=%#x %RGv state=%d expected>=%d %s\n",
    2102                                 pPage, GCPhysGst, iPage, GCPtr, PGM_PAGE_GET_HNDL_VIRT_STATE(pPage), uState, R3STRING(pVirt->pszDesc)));
    2103                 pState->cErrors++;
    2104                 continue;
    2105             }
    2106         } /* for each VCPU */
    2107     } /* for pages in virtual mapping. */
    2108 
    2109     return 0;
    2110 }
    2111 
    2112 # endif /* VBOX_WITH_RAW_MODE */
    21131684
    21141685/**
     
    21231694    PPGM        pPGM = &pVM->pgm.s;
    21241695    PGMAHAFIS   State;
    2125     State.GCPhys = 0;
    2126     State.uVirtState = 0;
    2127     State.uVirtStateFound = 0;
     1696    State.GCPhys  = 0;
    21281697    State.cErrors = 0;
    2129     State.pVM = pVM;
     1698    State.pVM     = pVM;
    21301699
    21311700    PGM_LOCK_ASSERT_OWNER(pVM);
     
    22071776                    }
    22081777                }
    2209 
    2210                 /*
    2211                  * Virtual handlers.
    2212                  */
    2213                 if (PGM_PAGE_HAS_ACTIVE_VIRTUAL_HANDLERS(pPage))
    2214                 {
    2215                     State.uVirtState = PGM_PAGE_GET_HNDL_VIRT_STATE(pPage);
    2216 
    2217                     /* locate all the matching physical ranges. */
    2218                     State.uVirtStateFound = PGM_PAGE_HNDL_VIRT_STATE_NONE;
    2219 # ifdef VBOX_WITH_RAW_MODE
    2220                     RTGCPHYS GCPhysKey = State.GCPhys;
    2221                     for (;;)
    2222                     {
    2223                         PPGMPHYS2VIRTHANDLER pPhys2Virt = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGetBestFit(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers,
    2224                                                                                                         GCPhysKey, true /* above-or-equal */);
    2225                         if (    !pPhys2Virt
    2226                             ||  (pPhys2Virt->Core.Key & X86_PTE_PAE_PG_MASK) != State.GCPhys)
    2227                             break;
    2228 
    2229                         /* the head */
    2230                         GCPhysKey = pPhys2Virt->Core.KeyLast;
    2231                         PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)((uintptr_t)pPhys2Virt + pPhys2Virt->offVirtHandler);
    2232                         unsigned uState = PGMVIRTANDLER_GET_TYPE(pVM, pCur)->uState;
    2233                         State.uVirtStateFound = RT_MAX(State.uVirtStateFound, uState);
    2234 
    2235                         /* any aliases */
    2236                         while (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK)
    2237                         {
    2238                             pPhys2Virt = (PPGMPHYS2VIRTHANDLER)((uintptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
    2239                             pCur = (PPGMVIRTHANDLER)((uintptr_t)pPhys2Virt + pPhys2Virt->offVirtHandler);
    2240                             uState = PGMVIRTANDLER_GET_TYPE(pVM, pCur)->uState;
    2241                             State.uVirtStateFound = RT_MAX(State.uVirtStateFound, uState);
    2242                         }
    2243 
    2244                         /* done? */
    2245                         if ((GCPhysKey & X86_PTE_PAE_PG_MASK) != State.GCPhys)
    2246                             break;
    2247                     }
    2248 # endif /* VBOX_WITH_RAW_MODE */
    2249                     if (State.uVirtState != State.uVirtStateFound)
    2250                     {
    2251                         AssertMsgFailed(("ram range vs virt handler flags mismatch. GCPhys=%RGp uVirtState=%#x uVirtStateFound=%#x\n",
    2252                                          State.GCPhys, State.uVirtState, State.uVirtStateFound));
    2253                         State.cErrors++;
    2254                     }
    2255                 }
    22561778            }
    22571779        } /* foreach page in ram range. */
    22581780    } /* foreach ram range. */
    22591781
    2260 # ifdef VBOX_WITH_RAW_MODE
    2261     /*
    2262      * Check that the physical addresses of the virtual handlers matches up
    2263      * and that they are otherwise sane.
    2264      */
    2265     RTAvlroGCPtrDoWithAll(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, true, pgmHandlerVirtualVerifyOne, &State);
    2266 # endif
    2267 
    22681782    /*
    22691783     * Do the reverse check for physical handlers.
  • trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp

    r80135 r80163  
    25012501        }
    25022502    }
    2503 
    2504 #if !defined(IN_RING0) && defined(VBOX_WITH_RAW_MODE)
    2505     /*
    2506      * Deal with any virtual handlers.
    2507      */
    2508     if (PGM_PAGE_GET_HNDL_VIRT_STATE(pPage) == PGM_PAGE_HNDL_VIRT_STATE_ALL)
    2509     {
    2510         unsigned        iPage;
    2511         PPGMVIRTHANDLER pVirt = pgmHandlerVirtualFindByPhysAddr(pVM, GCPhys, &iPage);
    2512         AssertReleaseMsg(pVirt, ("GCPhys=%RGp cb=%#x\n", GCPhys, cb));
    2513         Assert((pVirt->Core.Key     & PAGE_OFFSET_MASK) == 0);
    2514         Assert((pVirt->Core.KeyLast & PAGE_OFFSET_MASK) == PAGE_OFFSET_MASK);
    2515         Assert(GCPhys >= pVirt->aPhysToVirt[iPage].Core.Key && GCPhys <= pVirt->aPhysToVirt[iPage].Core.KeyLast);
    2516 
    2517 # ifndef IN_RING3
    2518         if (enmOrigin != PGMACCESSORIGIN_IEM)
    2519         {
    2520             /* Cannot reliably handle informational status codes in this context */
    2521             pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);
    2522             return VERR_PGM_PHYS_WR_HIT_HANDLER;
    2523         }
    2524 # endif
    2525         PPGMVIRTHANDLERTYPEINT pVirtType = PGMVIRTANDLER_GET_TYPE(pVM, pVirt);
    2526         if (!pPhys)
    2527             Log5(("pgmPhysReadHandler: GCPhys=%RGp cb=%#x pPage=%R[pgmpage] virt %s\n", GCPhys, cb, pPage, R3STRING(pVirt->pszDesc) ));
    2528         else
    2529             Log(("pgmPhysReadHandler: GCPhys=%RGp cb=%#x pPage=%R[pgmpage] phys/virt %s/%s\n", GCPhys, cb, pPage, R3STRING(pVirt->pszDesc), R3STRING(pPhys->pszDesc) ));
    2530         RTGCUINTPTR GCPtr = ((RTGCUINTPTR)pVirt->Core.Key & PAGE_BASE_GC_MASK)
    2531                           + (iPage << PAGE_SHIFT)
    2532                           + (GCPhys & PAGE_OFFSET_MASK);
    2533 
    2534         STAM_PROFILE_START(&pVirt->Stat, h);
    2535         VBOXSTRICTRC rcStrict2 = pVirtType->CTX_SUFF(pfnHandler)(pVM, pVCpu, GCPtr, (void *)pvSrc, pvBuf, cb,
    2536                                                                  PGMACCESSTYPE_READ, enmOrigin, pVirt->CTX_SUFF(pvUser));
    2537         STAM_PROFILE_STOP(&pVirt->Stat, h);
    2538 
    2539         /* Merge status codes. */
    2540         if (rcStrict2 == VINF_SUCCESS)
    2541         {
    2542             if (rcStrict == VINF_PGM_HANDLER_DO_DEFAULT)
    2543                 rcStrict = VINF_SUCCESS;
    2544         }
    2545         else if (rcStrict2 != VINF_PGM_HANDLER_DO_DEFAULT)
    2546         {
    2547             AssertLogRelMsg(PGM_HANDLER_VIRT_IS_VALID_STATUS(rcStrict2, false),
    2548                             ("rcStrict2=%Rrc (rcStrict=%Rrc) GCPhys=%RGp pPage=%R[pgmpage] %s\n",
    2549                              VBOXSTRICTRC_VAL(rcStrict2), VBOXSTRICTRC_VAL(rcStrict), GCPhys, pPage, pVirt->pszDesc));
    2550              if (!PGM_PHYS_RW_IS_SUCCESS(rcStrict2))
    2551              {
    2552                  pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);
    2553                  return rcStrict2;
    2554              }
    2555              if (rcStrict == VINF_PGM_HANDLER_DO_DEFAULT)
    2556                  rcStrict = rcStrict2;
    2557              else
    2558                  PGM_PHYS_RW_DO_UPDATE_STRICT_RC(rcStrict, rcStrict2);
    2559         }
    2560     }
    2561 #endif /* !IN_RING0 && VBOX_WITH_RAW_MODE */
    25622503
    25632504    /*
     
    27522693     */
    27532694    PVMCPU pVCpu = VMMGetCpu(pVM);
    2754     if (   !PGM_PAGE_HAS_ACTIVE_VIRTUAL_HANDLERS(pPage)
    2755         || PGM_PAGE_IS_MMIO_OR_SPECIAL_ALIAS(pPage) /* screw virtual handlers on MMIO pages */)
    2756     {
    2757         PPGMPHYSHANDLER pCur = pgmHandlerPhysicalLookup(pVM, GCPhys);
    2758         if (pCur)
    2759         {
    2760             Assert(GCPhys >= pCur->Core.Key && GCPhys <= pCur->Core.KeyLast);
     2695    PPGMPHYSHANDLER pCur = pgmHandlerPhysicalLookup(pVM, GCPhys);
     2696    if (pCur)
     2697    {
     2698        Assert(GCPhys >= pCur->Core.Key && GCPhys <= pCur->Core.KeyLast);
    27612699#ifndef IN_RING3
    2762             if (enmOrigin != PGMACCESSORIGIN_IEM)
    2763                 /* Cannot reliably handle informational status codes in this context */
    2764                 return VERR_PGM_PHYS_WR_HIT_HANDLER;
     2700        if (enmOrigin != PGMACCESSORIGIN_IEM)
     2701            /* Cannot reliably handle informational status codes in this context */
     2702            return VERR_PGM_PHYS_WR_HIT_HANDLER;
    27652703#endif
    2766             size_t cbRange = pCur->Core.KeyLast - GCPhys + 1;
    2767             if (cbRange > cbWrite)
    2768                 cbRange = cbWrite;
    2769 
    2770             Assert(PGMPHYSHANDLER_GET_TYPE(pVM, pCur)->CTX_SUFF(pfnHandler));
    2771             Log5(("pgmPhysWriteHandler: GCPhys=%RGp cbRange=%#x pPage=%R[pgmpage] phys %s\n",
    2772                   GCPhys, cbRange, pPage, R3STRING(pCur->pszDesc) ));
    2773             if (!PGM_PAGE_IS_MMIO_OR_SPECIAL_ALIAS(pPage))
    2774                 rcStrict = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDst, &PgMpLck);
    2775             else
     2704        size_t cbRange = pCur->Core.KeyLast - GCPhys + 1;
     2705        if (cbRange > cbWrite)
     2706            cbRange = cbWrite;
     2707
     2708        Assert(PGMPHYSHANDLER_GET_TYPE(pVM, pCur)->CTX_SUFF(pfnHandler));
     2709        Log5(("pgmPhysWriteHandler: GCPhys=%RGp cbRange=%#x pPage=%R[pgmpage] phys %s\n",
     2710              GCPhys, cbRange, pPage, R3STRING(pCur->pszDesc) ));
     2711        if (!PGM_PAGE_IS_MMIO_OR_SPECIAL_ALIAS(pPage))
     2712            rcStrict = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDst, &PgMpLck);
     2713        else
     2714            rcStrict = VINF_SUCCESS;
     2715        if (RT_SUCCESS(rcStrict))
     2716        {
     2717            PFNPGMPHYSHANDLER pfnHandler = PGMPHYSHANDLER_GET_TYPE(pVM, pCur)->CTX_SUFF(pfnHandler);
     2718            void *pvUser = pCur->CTX_SUFF(pvUser);
     2719            STAM_PROFILE_START(&pCur->Stat, h);
     2720
     2721            /* Release the PGM lock as MMIO handlers take the IOM lock. (deadlock prevention) */
     2722            PGM_LOCK_ASSERT_OWNER(pVM);
     2723            pgmUnlock(pVM);
     2724            rcStrict = pfnHandler(pVM, pVCpu, GCPhys, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE, enmOrigin, pvUser);
     2725            pgmLock(pVM);
     2726
     2727#ifdef VBOX_WITH_STATISTICS
     2728            pCur = pgmHandlerPhysicalLookup(pVM, GCPhys);
     2729            if (pCur)
     2730                STAM_PROFILE_STOP(&pCur->Stat, h);
     2731#else
     2732            pCur = NULL; /* might not be valid anymore. */
     2733#endif
     2734            if (rcStrict == VINF_PGM_HANDLER_DO_DEFAULT)
     2735            {
     2736                if (pvDst)
     2737                    memcpy(pvDst, pvBuf, cbRange);
    27762738                rcStrict = VINF_SUCCESS;
    2777             if (RT_SUCCESS(rcStrict))
    2778             {
    2779                 PFNPGMPHYSHANDLER pfnHandler = PGMPHYSHANDLER_GET_TYPE(pVM, pCur)->CTX_SUFF(pfnHandler);
    2780                 void *pvUser = pCur->CTX_SUFF(pvUser);
    2781                 STAM_PROFILE_START(&pCur->Stat, h);
    2782 
    2783                 /* Release the PGM lock as MMIO handlers take the IOM lock. (deadlock prevention) */
    2784                 PGM_LOCK_ASSERT_OWNER(pVM);
    2785                 pgmUnlock(pVM);
    2786                 rcStrict = pfnHandler(pVM, pVCpu, GCPhys, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE, enmOrigin, pvUser);
    2787                 pgmLock(pVM);
    2788 
    2789 #ifdef VBOX_WITH_STATISTICS
    2790                 pCur = pgmHandlerPhysicalLookup(pVM, GCPhys);
    2791                 if (pCur)
    2792                     STAM_PROFILE_STOP(&pCur->Stat, h);
    2793 #else
    2794                 pCur = NULL; /* might not be valid anymore. */
    2795 #endif
    2796                 if (rcStrict == VINF_PGM_HANDLER_DO_DEFAULT)
    2797                 {
    2798                     if (pvDst)
    2799                         memcpy(pvDst, pvBuf, cbRange);
    2800                     rcStrict = VINF_SUCCESS;
    2801                 }
    2802                 else
    2803                     AssertLogRelMsg(PGM_HANDLER_PHYS_IS_VALID_STATUS(rcStrict, true),
    2804                                     ("rcStrict=%Rrc GCPhys=%RGp pPage=%R[pgmpage] %s\n",
    2805                                      VBOXSTRICTRC_VAL(rcStrict), GCPhys, pPage, pCur ? R3STRING(pCur->pszDesc) : ""));
    28062739            }
    28072740            else
    2808                 AssertLogRelMsgFailedReturn(("pgmPhysGCPhys2CCPtrInternal failed on %RGp / %R[pgmpage] -> %Rrc\n",
    2809                                              GCPhys, pPage, VBOXSTRICTRC_VAL(rcStrict)), rcStrict);
    2810             if (RT_LIKELY(cbRange == cbWrite) || !PGM_PHYS_RW_IS_SUCCESS(rcStrict))
    2811             {
    2812                 if (pvDst)
    2813                     pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);
    2814                 return rcStrict;
    2815             }
    2816 
    2817             /* more fun to be had below */
    2818             cbWrite -= cbRange;
    2819             GCPhys  += cbRange;
    2820             pvBuf    = (uint8_t *)pvBuf + cbRange;
    2821             pvDst    = (uint8_t *)pvDst + cbRange;
    2822         }
    2823         else /* The handler is somewhere else in the page, deal with it below. */
    2824             rcStrict = VINF_SUCCESS;
    2825         Assert(!PGM_PAGE_IS_MMIO_OR_ALIAS(pPage)); /* MMIO handlers are all PAGE_SIZEed! */
    2826     }
    2827 #if !defined(IN_RING0) && defined(VBOX_WITH_RAW_MODE)
    2828     /*
    2829      * A virtual handler without any interfering physical handlers.
    2830      * Hopefully it'll cover the whole write.
    2831      */
    2832     else if (!PGM_PAGE_HAS_ACTIVE_PHYSICAL_HANDLERS(pPage))
    2833     {
    2834         unsigned        iPage;
    2835         PPGMVIRTHANDLER pVirt = pgmHandlerVirtualFindByPhysAddr(pVM, GCPhys, &iPage);
    2836         if (pVirt)
    2837         {
    2838 # ifndef IN_RING3
    2839             if (enmOrigin != PGMACCESSORIGIN_IEM)
    2840                 /* Cannot reliably handle informational status codes in this context */
    2841                 return VERR_PGM_PHYS_WR_HIT_HANDLER;
    2842 # endif
    2843             PPGMVIRTHANDLERTYPEINT pVirtType = PGMVIRTANDLER_GET_TYPE(pVM, pVirt);
    2844             size_t cbRange = (PAGE_OFFSET_MASK & pVirt->Core.KeyLast) - (PAGE_OFFSET_MASK & GCPhys) + 1;
    2845             if (cbRange > cbWrite)
    2846                 cbRange = cbWrite;
    2847 
    2848             Log5(("pgmPhysWriteHandler: GCPhys=%RGp cbRange=%#x pPage=%R[pgmpage] virt %s\n",
    2849                   GCPhys, cbRange, pPage, R3STRING(pVirt->pszDesc) ));
    2850             rcStrict = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDst, &PgMpLck);
    2851             if (RT_SUCCESS(rcStrict))
    2852             {
    2853                 Assert(pVirtType->CTX_SUFF(pfnHandler));
    2854                 RTGCUINTPTR GCPtr = ((RTGCUINTPTR)pVirt->Core.Key & PAGE_BASE_GC_MASK)
    2855                                   + (iPage << PAGE_SHIFT)
    2856                                   + (GCPhys & PAGE_OFFSET_MASK);
    2857 
    2858                 STAM_PROFILE_START(&pVirt->Stat, h);
    2859                 rcStrict = pVirtType->CTX_SUFF(pfnHandler)(pVM, pVCpu, GCPtr, pvDst, (void *)pvBuf, cbRange,
    2860                                                            PGMACCESSTYPE_WRITE, enmOrigin, pVirt->CTX_SUFF(pvUser));
    2861                 STAM_PROFILE_STOP(&pVirt->Stat, h);
    2862                 if (rcStrict == VINF_PGM_HANDLER_DO_DEFAULT)
    2863                 {
    2864                     memcpy(pvDst, pvBuf, cbRange);
    2865                     rcStrict = VINF_SUCCESS;
    2866                 }
    2867                 else
    2868                     AssertLogRelMsg(PGM_HANDLER_VIRT_IS_VALID_STATUS(rcStrict, true),
    2869                                     ("rcStrict=%Rrc GCPhys=%RGp pPage=%R[pgmpage] %s\n",
    2870                                      VBOXSTRICTRC_VAL(rcStrict), GCPhys, pPage, R3STRING(pVirt->pszDesc)));
    2871             }
    2872             else
    2873                 AssertLogRelMsgFailedReturn(("pgmPhysGCPhys2CCPtrInternal failed on %RGp / %R[pgmpage] -> %Rrc\n",
    2874                                              GCPhys, pPage, VBOXSTRICTRC_VAL(rcStrict)), rcStrict);
    2875             if (RT_LIKELY(cbRange == cbWrite) || !PGM_PHYS_RW_IS_SUCCESS(rcStrict))
    2876             {
     2741                AssertLogRelMsg(PGM_HANDLER_PHYS_IS_VALID_STATUS(rcStrict, true),
     2742                                ("rcStrict=%Rrc GCPhys=%RGp pPage=%R[pgmpage] %s\n",
     2743                                 VBOXSTRICTRC_VAL(rcStrict), GCPhys, pPage, pCur ? R3STRING(pCur->pszDesc) : ""));
     2744        }
     2745        else
     2746            AssertLogRelMsgFailedReturn(("pgmPhysGCPhys2CCPtrInternal failed on %RGp / %R[pgmpage] -> %Rrc\n",
     2747                                         GCPhys, pPage, VBOXSTRICTRC_VAL(rcStrict)), rcStrict);
     2748        if (RT_LIKELY(cbRange == cbWrite) || !PGM_PHYS_RW_IS_SUCCESS(rcStrict))
     2749        {
     2750            if (pvDst)
    28772751                pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);
    2878                 return rcStrict;
    2879             }
    2880 
    2881             /* more fun to be had below */
    2882             cbWrite -= cbRange;
    2883             GCPhys  += cbRange;
    2884             pvBuf    = (uint8_t *)pvBuf + cbRange;
    2885             pvDst    = (uint8_t *)pvDst + cbRange;
    2886         }
    2887         else /* The handler is somewhere else in the page, deal with it below. */
    2888             rcStrict = VINF_SUCCESS;
    2889     }
    2890 #endif /* !IN_RING0 && VBOX_WITH_RAW_MODE */
    2891     else
     2752            return rcStrict;
     2753        }
     2754
     2755        /* more fun to be had below */
     2756        cbWrite -= cbRange;
     2757        GCPhys  += cbRange;
     2758        pvBuf    = (uint8_t *)pvBuf + cbRange;
     2759        pvDst    = (uint8_t *)pvDst + cbRange;
     2760    }
     2761    else /* The handler is somewhere else in the page, deal with it below. */
    28922762        rcStrict = VINF_SUCCESS;
    2893 
    2894 
    2895     /*
    2896      * Deal with all the odd ends.
     2763    Assert(!PGM_PAGE_IS_MMIO_OR_ALIAS(pPage)); /* MMIO handlers are all PAGE_SIZEed! */
     2764
     2765    /*
     2766     * Deal with all the odd ends (used to be deal with virt+phys).
    28972767     */
    28982768    Assert(rcStrict != VINF_PGM_HANDLER_DO_DEFAULT);
     
    29082778
    29092779    /* The loop state (big + ugly). */
    2910 #if !defined(IN_RING0) && defined(VBOX_WITH_RAW_MODE)
    2911     unsigned        iVirtPage   = 0;
    2912     PPGMVIRTHANDLER pVirt       = NULL;
    2913     uint32_t        offVirt     = PAGE_SIZE;
    2914     uint32_t        offVirtLast = PAGE_SIZE;
    2915     bool            fMoreVirt   = PGM_PAGE_HAS_ACTIVE_VIRTUAL_HANDLERS(pPage);
    2916 #else
    2917     uint32_t const  offVirt     = UINT32_MAX;
    2918 #endif
    2919 
    29202780    PPGMPHYSHANDLER pPhys       = NULL;
    29212781    uint32_t        offPhys     = PAGE_SIZE;
     
    29262786    for (;;)
    29272787    {
    2928 #if !defined(IN_RING0) && defined(VBOX_WITH_RAW_MODE)
    2929         /*
    2930          * Find the closest handler at or above GCPhys.
    2931          */
    2932         if (fMoreVirt && !pVirt)
    2933         {
    2934             pVirt = pgmHandlerVirtualFindByPhysAddr(pVM, GCPhys, &iVirtPage);
    2935             if (pVirt)
    2936             {
    2937                 offVirt = 0;
    2938                 offVirtLast = (pVirt->aPhysToVirt[iVirtPage].Core.KeyLast & PAGE_OFFSET_MASK) - (GCPhys & PAGE_OFFSET_MASK);
    2939             }
    2940             else
    2941             {
    2942                 PPGMPHYS2VIRTHANDLER pVirtPhys;
    2943                 pVirtPhys = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGetBestFit(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers,
    2944                                                                           GCPhys, true /* fAbove */);
    2945                 if (    pVirtPhys
    2946                     &&  (pVirtPhys->Core.Key >> PAGE_SHIFT) == (GCPhys >> PAGE_SHIFT))
    2947                 {
    2948                     /* ASSUME that pVirtPhys only covers one page. */
    2949                     Assert((pVirtPhys->Core.Key >> PAGE_SHIFT) == (pVirtPhys->Core.KeyLast >> PAGE_SHIFT));
    2950                     Assert(pVirtPhys->Core.Key > GCPhys);
    2951 
    2952                     pVirt       = (PPGMVIRTHANDLER)((uintptr_t)pVirtPhys + pVirtPhys->offVirtHandler);
    2953                     iVirtPage   = pVirtPhys - &pVirt->aPhysToVirt[0]; Assert(iVirtPage == 0);
    2954                     offVirt     = (pVirtPhys->Core.Key     & PAGE_OFFSET_MASK) - (GCPhys & PAGE_OFFSET_MASK);
    2955                     offVirtLast = (pVirtPhys->Core.KeyLast & PAGE_OFFSET_MASK) - (GCPhys & PAGE_OFFSET_MASK);
    2956                 }
    2957                 else
    2958                 {
    2959                     pVirt       = NULL;
    2960                     fMoreVirt   = false;
    2961                     offVirt     = offVirtLast = PAGE_SIZE;
    2962                 }
    2963             }
    2964         }
    2965 #endif
    2966 
    29672788        if (fMorePhys && !pPhys)
    29682789        {
     
    29972818        VBOXSTRICTRC rcStrict2 = VINF_PGM_HANDLER_DO_DEFAULT;
    29982819        uint32_t cbRange = (uint32_t)cbWrite;
    2999         if (offPhys != 0 && offVirt != 0)
    3000         {
    3001             if (cbRange > offPhys)
    3002                 cbRange = offPhys;
    3003             if (cbRange > offVirt)
    3004                 cbRange = offVirt;
    3005             Log5(("pgmPhysWriteHandler: GCPhys=%RGp cbRange=%#x pPage=%R[pgmpage] miss\n", GCPhys, cbRange, pPage));
    3006         }
     2820
    30072821        /*
    30082822         * Physical handler.
    30092823         */
    3010         else if (!offPhys && offVirt)
     2824        if (!offPhys)
    30112825        {
    30122826#ifndef IN_RING3
     
    30172831            if (cbRange > offPhysLast + 1)
    30182832                cbRange = offPhysLast + 1;
    3019             if (cbRange > offVirt)
    3020                 cbRange = offVirt;
    30212833
    30222834            PFNPGMPHYSHANDLER pfnHandler = PGMPHYSHANDLER_GET_TYPE(pVM, pPhys)->CTX_SUFF(pfnHandler);
     
    30432855                             VBOXSTRICTRC_VAL(rcStrict), GCPhys, pPage,  pPhys ? R3STRING(pPhys->pszDesc) : ""));
    30442856        }
    3045 #if !defined(IN_RING0) && defined(VBOX_WITH_RAW_MODE)
    3046         /*
    3047          * Virtual handler.
    3048          */
    3049         else if (offPhys && !offVirt)
    3050         {
    3051 # ifndef IN_RING3
    3052             if (enmOrigin != PGMACCESSORIGIN_IEM)
    3053                 /* Cannot reliably handle informational status codes in this context */
    3054                 return VERR_PGM_PHYS_WR_HIT_HANDLER;
    3055 # endif
    3056             if (cbRange > offVirtLast + 1)
    3057                 cbRange = offVirtLast + 1;
    3058             if (cbRange > offPhys)
    3059                 cbRange = offPhys;
    3060 
    3061             PPGMVIRTHANDLERTYPEINT pVirtType = PGMVIRTANDLER_GET_TYPE(pVM, pVirt);
    3062             Log5(("pgmPhysWriteHandler: GCPhys=%RGp cbRange=%#x pPage=%R[pgmpage] phys %s\n", GCPhys, cbRange, pPage, R3STRING(pVirt->pszDesc) ));
    3063             Assert(pVirtType->CTX_SUFF(pfnHandler));
    3064             RTGCUINTPTR GCPtr = ((RTGCUINTPTR)pVirt->Core.Key & PAGE_BASE_GC_MASK)
    3065                               + (iVirtPage << PAGE_SHIFT)
    3066                               + (GCPhys & PAGE_OFFSET_MASK);
    3067             STAM_PROFILE_START(&pVirt->Stat, h);
    3068             rcStrict2 = pVirtType->CTX_SUFF(pfnHandler)(pVM, pVCpu, GCPtr, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE,
    3069                                                         enmOrigin, pVirt->CTX_SUFF(pvUser));
    3070             STAM_PROFILE_STOP(&pVirt->Stat, h);
    3071             AssertLogRelMsg(PGM_HANDLER_VIRT_IS_VALID_STATUS(rcStrict2, true),
    3072                             ("rcStrict2=%Rrc (rcStrict=%Rrc) GCPhys=%RGp pPage=%R[pgmpage] %s\n", VBOXSTRICTRC_VAL(rcStrict2),
    3073                              VBOXSTRICTRC_VAL(rcStrict), GCPhys, pPage,  pPhys ? R3STRING(pPhys->pszDesc) : ""));
    3074             pVirt = NULL;
    3075         }
    3076         /*
    3077          * Both... give the physical one priority.
    3078          */
    3079         else
    3080         {
    3081 # ifndef IN_RING3
    3082             if (enmOrigin != PGMACCESSORIGIN_IEM)
    3083                 /* Cannot reliably handle informational status codes in this context */
    3084                 return VERR_PGM_PHYS_WR_HIT_HANDLER;
    3085 # endif
    3086             Assert(!offPhys && !offVirt);
    3087             if (cbRange > offVirtLast + 1)
    3088                 cbRange = offVirtLast + 1;
    3089             if (cbRange > offPhysLast + 1)
    3090                 cbRange = offPhysLast + 1;
    3091 
    3092             PPGMVIRTHANDLERTYPEINT pVirtType = PGMVIRTANDLER_GET_TYPE(pVM, pVirt);
    3093             if (pVirtType->pfnHandlerR3)
    3094                 Log(("pgmPhysWriteHandler: overlapping phys and virt handlers at %RGp %R[pgmpage]; cbRange=%#x\n", GCPhys, pPage, cbRange));
    3095             Log5(("pgmPhysWriteHandler: GCPhys=%RGp cbRange=%#x pPage=%R[pgmpage] phys/virt %s/%s\n", GCPhys, cbRange, pPage, R3STRING(pPhys->pszDesc), R3STRING(pVirt->pszDesc) ));
    3096 
    3097             PFNPGMPHYSHANDLER pfnHandler = PGMPHYSHANDLER_GET_TYPE(pVM, pPhys)->CTX_SUFF(pfnHandler);
    3098             void *pvUser = pPhys->CTX_SUFF(pvUser);
    3099             STAM_PROFILE_START(&pPhys->Stat, h);
    3100 
    3101             /* Release the PGM lock as MMIO handlers take the IOM lock. (deadlock prevention) */
    3102             PGM_LOCK_ASSERT_OWNER(pVM);
    3103             pgmUnlock(pVM);
    3104             rcStrict2 = pfnHandler(pVM, pVCpu, GCPhys, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE, enmOrigin, pvUser);
    3105             pgmLock(pVM);
    3106 
    3107 # ifdef VBOX_WITH_STATISTICS
    3108             pPhys = pgmHandlerPhysicalLookup(pVM, GCPhys);
    3109             if (pPhys)
    3110                 STAM_PROFILE_STOP(&pPhys->Stat, h);
    3111 # else
    3112             pPhys = NULL; /* might not be valid anymore. */
    3113 # endif
    3114             AssertLogRelMsg(PGM_HANDLER_PHYS_IS_VALID_STATUS(rcStrict2, true),
    3115                             ("rcStrict2=%Rrc (rcStrict=%Rrc) GCPhys=%RGp pPage=%R[pgmpage] %s\n", VBOXSTRICTRC_VAL(rcStrict2),
    3116                              VBOXSTRICTRC_VAL(rcStrict), GCPhys, pPage,  pPhys ? R3STRING(pPhys->pszDesc) : ""));
    3117             if (rcStrict2 == VINF_PGM_HANDLER_DO_DEFAULT || PGM_PHYS_RW_IS_SUCCESS(rcStrict2))
    3118             {
    3119                 Assert(pVirtType->CTX_SUFF(pfnHandler));
    3120                 RTGCUINTPTR GCPtr = ((RTGCUINTPTR)pVirt->Core.Key & PAGE_BASE_GC_MASK)
    3121                                   + (iVirtPage << PAGE_SHIFT)
    3122                                   + (GCPhys & PAGE_OFFSET_MASK);
    3123                 pvUser = pVirt->CTX_SUFF(pvUser);
    3124 
    3125                 STAM_PROFILE_START(&pVirt->Stat, h2);
    3126                 VBOXSTRICTRC rcStrict3 = pVirtType->CTX_SUFF(pfnHandler)(pVM, pVCpu, GCPtr, pvDst, (void *)pvBuf, cbRange,
    3127                                                                          PGMACCESSTYPE_WRITE, enmOrigin, pvUser);
    3128                 STAM_PROFILE_STOP(&pVirt->Stat, h2);
    3129 
    3130                 /* Merge the 3rd status into the 2nd. */
    3131                 if (rcStrict3 == VINF_SUCCESS)
    3132                 {
    3133                     if (rcStrict2 == VINF_PGM_HANDLER_DO_DEFAULT)
    3134                         rcStrict2 = VINF_SUCCESS;
    3135                 }
    3136                 else if (rcStrict3 != VINF_PGM_HANDLER_DO_DEFAULT)
    3137                 {
    3138                     AssertLogRelMsg(PGM_HANDLER_VIRT_IS_VALID_STATUS(rcStrict3, true),
    3139                                     ("rcStrict3=%Rrc (rcStrict2=%Rrc) (rcStrict=%Rrc) GCPhys=%RGp pPage=%R[pgmpage] %s\n",
    3140                                      VBOXSTRICTRC_VAL(rcStrict3), VBOXSTRICTRC_VAL(rcStrict2), VBOXSTRICTRC_VAL(rcStrict),
    3141                                      GCPhys, pPage, R3STRING(pVirt->pszDesc) ));
    3142                     if (rcStrict2 == VINF_PGM_HANDLER_DO_DEFAULT)
    3143                         rcStrict2 = rcStrict3;
    3144                     else if (!PGM_PHYS_RW_IS_SUCCESS(rcStrict3))
    3145                         rcStrict2 = rcStrict3;
    3146                     else
    3147                         PGM_PHYS_RW_DO_UPDATE_STRICT_RC(rcStrict2, rcStrict3);
    3148                 }
    3149             }
    3150             pPhys = NULL;
    3151             pVirt = NULL;
    3152         }
    3153 #endif /* !IN_RING0 && VBOX_WITH_RAW_MODE */
    3154 
    31552857
    31562858        /*
     
    31872889        offPhys         -= cbRange;
    31882890        offPhysLast     -= cbRange;
    3189 #if !defined(IN_RING0) && defined(VBOX_WITH_RAW_MODE)
    3190         offVirt         -= cbRange;
    3191         offVirtLast     -= cbRange;
    3192 #endif
    31932891    }
    31942892}
  • trunk/src/VBox/VMM/VMMR3/DBGF.cpp

    r80050 r80163  
    21062106    /** @todo NEM: NMI injection   */
    21072107    if (!HMIsEnabled(pVM))
    2108         return VERR_NOT_SUP_IN_RAW_MODE;
     2108        return VERR_NOT_SUP_BY_NEM;
    21092109
    21102110    VMCPU_FF_SET(&pVM->aCpus[idCpu], VMCPU_FF_INTERRUPT_NMI);
  • trunk/src/VBox/VMM/VMMR3/PGM.cpp

    r80118 r80163  
    161161 *
    162162 *
    163  * @subsection      sec_pgm_handlers_virt   Virtual Access Handlers
     163 * @subsection      sec_pgm_handlers_virt   Virtual Access Handlers (obsolete)
    164164 *
    165165 * We currently implement three types of virtual access handlers:  ALL, WRITE
     
    13461346    PGM_REG_COUNTER(&pStats->StatR3RamRangeTlbMisses,           "/PGM/R3/RamRange/TlbMisses",         "TLB misses.");
    13471347
    1348     PGM_REG_PROFILE(&pStats->StatRZSyncCR3HandlerVirtualUpdate, "/PGM/RZ/SyncCR3/Handlers/VirtualUpdate", "Profiling of the virtual handler updates.");
    1349     PGM_REG_PROFILE(&pStats->StatRZSyncCR3HandlerVirtualReset,  "/PGM/RZ/SyncCR3/Handlers/VirtualReset",  "Profiling of the virtual handler resets.");
    1350     PGM_REG_PROFILE(&pStats->StatR3SyncCR3HandlerVirtualUpdate, "/PGM/R3/SyncCR3/Handlers/VirtualUpdate", "Profiling of the virtual handler updates.");
    1351     PGM_REG_PROFILE(&pStats->StatR3SyncCR3HandlerVirtualReset,  "/PGM/R3/SyncCR3/Handlers/VirtualReset",  "Profiling of the virtual handler resets.");
    1352 
    13531348    PGM_REG_COUNTER(&pStats->StatRZPhysHandlerReset,            "/PGM/RZ/PhysHandlerReset",           "The number of times PGMHandlerPhysicalReset is called.");
    13541349    PGM_REG_COUNTER(&pStats->StatR3PhysHandlerReset,            "/PGM/R3/PhysHandlerReset",           "The number of times PGMHandlerPhysicalReset is called.");
     
    13571352    PGM_REG_COUNTER(&pStats->StatRZPhysHandlerLookupMisses,     "/PGM/RZ/PhysHandlerLookupMisses",    "The number of cache misses when looking up physical handlers.");
    13581353    PGM_REG_COUNTER(&pStats->StatR3PhysHandlerLookupMisses,     "/PGM/R3/PhysHandlerLookupMisses",    "The number of cache misses when looking up physical handlers.");
    1359     PGM_REG_PROFILE(&pStats->StatRZVirtHandlerSearchByPhys,     "/PGM/RZ/VirtHandlerSearchByPhys",    "Profiling of pgmHandlerVirtualFindByPhysAddr.");
    1360     PGM_REG_PROFILE(&pStats->StatR3VirtHandlerSearchByPhys,     "/PGM/R3/VirtHandlerSearchByPhys",    "Profiling of pgmHandlerVirtualFindByPhysAddr.");
    13611354
    13621355    PGM_REG_COUNTER(&pStats->StatRZPageReplaceShared,           "/PGM/RZ/Page/ReplacedShared",        "Times a shared page was replaced.");
     
    14441437        PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2GuestTrap,        "/PGM/CPU%u/RZ/Trap0e/Time2/GuestTrap",         "Profiling of the Trap0eHandler body when the cause is a guest trap.");
    14451438        PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2HndPhys,          "/PGM/CPU%u/RZ/Trap0e/Time2/HandlerPhysical",   "Profiling of the Trap0eHandler body when the cause is a physical handler.");
    1446         PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2HndVirt,          "/PGM/CPU%u/RZ/Trap0e/Time2/HandlerVirtual",    "Profiling of the Trap0eHandler body when the cause is a virtual handler.");
    14471439        PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2HndUnhandled,     "/PGM/CPU%u/RZ/Trap0e/Time2/HandlerUnhandled",  "Profiling of the Trap0eHandler body when the cause is access outside the monitored areas of a monitored page.");
    14481440        PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2InvalidPhys,      "/PGM/CPU%u/RZ/Trap0e/Time2/InvalidPhys",       "Profiling of the Trap0eHandler body when the cause is access to an invalid physical guest address.");
     
    14521444        PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2OutOfSync,        "/PGM/CPU%u/RZ/Trap0e/Time2/OutOfSync",         "Profiling of the Trap0eHandler body when the cause is an out-of-sync page.");
    14531445        PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2OutOfSyncHndPhys, "/PGM/CPU%u/RZ/Trap0e/Time2/OutOfSyncHndPhys",  "Profiling of the Trap0eHandler body when the cause is an out-of-sync physical handler page.");
    1454         PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2OutOfSyncHndVirt, "/PGM/CPU%u/RZ/Trap0e/Time2/OutOfSyncHndVirt",  "Profiling of the Trap0eHandler body when the cause is an out-of-sync virtual handler page.");
    14551446        PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2OutOfSyncHndObs,  "/PGM/CPU%u/RZ/Trap0e/Time2/OutOfSyncObsHnd",   "Profiling of the Trap0eHandler body when the cause is an obsolete handler page.");
    14561447        PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2SyncPT,           "/PGM/CPU%u/RZ/Trap0e/Time2/SyncPT",            "Profiling of the Trap0eHandler body when the cause is lazy syncing of a PT.");
     
    14641455        PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersPhysAllOpt,    "/PGM/CPU%u/RZ/Trap0e/Handlers/PhysAllOpt",     "Number of the physical all-access handler traps using the optimization.");
    14651456        PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersPhysWrite,     "/PGM/CPU%u/RZ/Trap0e/Handlers/PhysWrite",      "Number of traps due to physical write-access handlers.");
    1466         PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersVirtual,       "/PGM/CPU%u/RZ/Trap0e/Handlers/Virtual",        "Number of traps due to virtual access handlers.");
    1467         PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersVirtualByPhys, "/PGM/CPU%u/RZ/Trap0e/Handlers/VirtualByPhys",  "Number of traps due to virtual access handlers by physical address.");
    1468         PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersVirtualUnmarked,"/PGM/CPU%u/RZ/Trap0e/Handlers/VirtualUnmarked","Number of traps due to virtual access handlers by virtual address (without proper physical flags).");
    14691457        PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersUnhandled,     "/PGM/CPU%u/RZ/Trap0e/Handlers/Unhandled",      "Number of traps due to access outside range of monitored page(s).");
    14701458        PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersInvalid,       "/PGM/CPU%u/RZ/Trap0e/Handlers/Invalid",        "Number of traps due to access to invalid physical memory.");
     
    21972185            pVCpu->pgm.s.GCPhysA20Mask = ~((RTGCPHYS)!pVCpu->pgm.s.fA20Enabled << 20);
    21982186#ifdef PGM_WITH_A20
    2199             pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;
    22002187            VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
    22012188            pgmR3RefreshShadowModeAfterA20Change(pVCpu);
  • trunk/src/VBox/VMM/VMMR3/PGMHandler.cpp

    r80007 r80163  
    333333}
    334334
    335 #ifdef VBOX_WITH_RAW_MODE
    336 
    337 /**
    338  * Register a virtual page access handler type, extended version.
    339  *
    340  * @returns VBox status code.
    341  * @param   pVM             The cross context VM structure.
    342  * @param   enmKind         The kind of access handler.
    343  * @param   fRelocUserRC    Whether the pvUserRC argument should be
    344  *                          automatically relocated or not.
    345  * @param   pfnInvalidateR3 Pointer to the ring-3 invalidation handler callback.
    346  *                          Warning! This callback stopped working in VBox v1.2!
    347  * @param   pfnHandlerR3    Pointer to the ring-3 handler callback.
    348  * @param   pfnHandlerRC    Pointer to the raw-mode context handler callback.
    349  * @param   pfnPfHandlerRC  Pointer to the raw-mode context \#PF handler
    350  *                          callback.
    351  * @param   pszDesc         The type description.
    352  * @param   phType          Where to return the type handle (cross context
    353  *                          safe).
    354  * @remarks No virtual handlers when executing using HM (i.e. ring-0).
    355  */
    356 VMMR3_INT_DECL(int) PGMR3HandlerVirtualTypeRegisterEx(PVM pVM, PGMVIRTHANDLERKIND enmKind, bool fRelocUserRC,
    357                                                       PFNPGMR3VIRTINVALIDATE pfnInvalidateR3,
    358                                                       PFNPGMVIRTHANDLER pfnHandlerR3,
    359                                                       RCPTRTYPE(FNPGMVIRTHANDLER) pfnHandlerRC,
    360                                                       RCPTRTYPE(FNPGMRCVIRTPFHANDLER) pfnPfHandlerRC,
    361                                                       const char *pszDesc, PPGMVIRTHANDLERTYPE phType)
    362 {
    363     AssertReturn(VM_IS_RAW_MODE_ENABLED(pVM), VERR_NOT_AVAILABLE); /* Only supported/relevant for raw-mode. */
    364     AssertReturn(   enmKind == PGMVIRTHANDLERKIND_WRITE
    365                  || enmKind == PGMVIRTHANDLERKIND_ALL
    366                  || enmKind == PGMVIRTHANDLERKIND_HYPERVISOR,
    367                  VERR_INVALID_PARAMETER);
    368     if (enmKind != PGMVIRTHANDLERKIND_HYPERVISOR)
    369     {
    370         AssertPtrNullReturn(pfnInvalidateR3, VERR_INVALID_POINTER);
    371         AssertPtrReturn(pfnHandlerR3, VERR_INVALID_POINTER);
    372         AssertReturn(pfnHandlerRC != NIL_RTRCPTR, VERR_INVALID_POINTER);
    373     }
    374     else
    375     {
    376         AssertReturn(pfnInvalidateR3 == NULL, VERR_INVALID_POINTER);
    377         AssertReturn(pfnHandlerR3 == NULL, VERR_INVALID_POINTER);
    378         AssertReturn(pfnHandlerRC == NIL_RTR0PTR, VERR_INVALID_POINTER);
    379     }
    380     AssertReturn(pfnPfHandlerRC != NIL_RTRCPTR, VERR_INVALID_POINTER);
    381     AssertPtrReturn(pszDesc, VERR_INVALID_POINTER);
    382 
    383     PPGMVIRTHANDLERTYPEINT pType;
    384     int rc = MMHyperAlloc(pVM, sizeof(*pType), 0, MM_TAG_PGM_HANDLER_TYPES, (void **)&pType);
    385     if (RT_SUCCESS(rc))
    386     {
    387         pType->u32Magic         = PGMVIRTHANDLERTYPEINT_MAGIC;
    388         pType->cRefs            = 1;
    389         pType->enmKind          = enmKind;
    390         pType->fRelocUserRC     = fRelocUserRC;
    391         pType->uState           = enmKind == PGMVIRTHANDLERKIND_ALL
    392                                 ? PGM_PAGE_HNDL_VIRT_STATE_ALL : PGM_PAGE_HNDL_VIRT_STATE_WRITE;
    393         pType->pfnInvalidateR3  = pfnInvalidateR3;
    394         pType->pfnHandlerR3     = pfnHandlerR3;
    395         pType->pfnHandlerRC     = pfnHandlerRC;
    396         pType->pfnPfHandlerRC   = pfnPfHandlerRC;
    397         pType->pszDesc          = pszDesc;
    398 
    399         pgmLock(pVM);
    400         RTListOff32Append(&pVM->pgm.s.CTX_SUFF(pTrees)->HeadVirtHandlerTypes, &pType->ListNode);
    401         pgmUnlock(pVM);
    402 
    403         *phType = MMHyperHeapPtrToOffset(pVM, pType);
    404         LogFlow(("PGMR3HandlerVirtualTypeRegisterEx: %p/%#x: enmKind=%d pfnInvalidateR3=%RHv pfnHandlerR3=%RHv pfnPfHandlerRC=%RRv pszDesc=%s\n",
    405                  pType, *phType, enmKind, pfnInvalidateR3, pfnHandlerR3, pfnPfHandlerRC, pszDesc));
    406         return VINF_SUCCESS;
    407     }
    408     *phType = NIL_PGMVIRTHANDLERTYPE;
    409     return rc;
    410 }
    411 
    412 
    413 /**
    414  * Register a physical page access handler type.
    415  *
    416  * @returns VBox status code.
    417  * @param   pVM             The cross context VM structure.
    418  * @param   enmKind         The kind of access handler.
    419  * @param   fRelocUserRC    Whether the pvUserRC argument should be
    420  *                          automatically relocated or not.
    421  * @param   pfnInvalidateR3 Pointer to the ring-3 invalidateion callback
    422  *                          (optional, can be NULL).
    423  * @param   pfnHandlerR3    Pointer to the ring-3 handler callback.
    424  * @param   pszHandlerRC    The name of the raw-mode context handler callback
    425  *                          (in VMMRC.rc).
    426  * @param   pszPfHandlerRC  The name of the raw-mode context \#PF handler (in
    427  *                          VMMRC.rc).
    428  * @param   pszDesc         The type description.
    429  * @param   phType          Where to return the type handle (cross context
    430  *                          safe).
    431  * @remarks No virtual handlers when executing using HM (i.e. ring-0).
    432  */
    433 VMMR3_INT_DECL(int) PGMR3HandlerVirtualTypeRegister(PVM pVM, PGMVIRTHANDLERKIND enmKind, bool fRelocUserRC,
    434                                                     PFNPGMR3VIRTINVALIDATE pfnInvalidateR3,
    435                                                     PFNPGMVIRTHANDLER pfnHandlerR3,
    436                                                     const char *pszHandlerRC, const char *pszPfHandlerRC, const char *pszDesc,
    437                                                     PPGMVIRTHANDLERTYPE phType)
    438 {
    439     LogFlow(("PGMR3HandlerVirtualTypeRegister: enmKind=%d pfnInvalidateR3=%RHv pfnHandlerR3=%RHv pszPfHandlerRC=%s pszDesc=%s\n",
    440              enmKind, pfnInvalidateR3, pfnHandlerR3, pszPfHandlerRC, pszDesc));
    441 
    442     /*
    443      * Validate input.
    444      */
    445     AssertPtrNullReturn(pszHandlerRC, VERR_INVALID_POINTER);
    446     AssertPtrReturn(pszPfHandlerRC, VERR_INVALID_POINTER);
    447 
    448     /*
    449      * Resolve the GC handler.
    450      */
    451     RTRCPTR pfnHandlerRC = NIL_RTRCPTR;
    452     int rc = VINF_SUCCESS;
    453     if (pszHandlerRC)
    454         rc = PDMR3LdrGetSymbolRCLazy(pVM, VMMRC_MAIN_MODULE_NAME, NULL /*pszSearchPath*/, pszHandlerRC, &pfnHandlerRC);
    455     if (RT_SUCCESS(rc))
    456     {
    457         RTRCPTR pfnPfHandlerRC = NIL_RTRCPTR;
    458         rc = PDMR3LdrGetSymbolRCLazy(pVM, VMMRC_MAIN_MODULE_NAME, NULL /*pszSearchPath*/, pszPfHandlerRC, &pfnPfHandlerRC);
    459         if (RT_SUCCESS(rc))
    460             return PGMR3HandlerVirtualTypeRegisterEx(pVM, enmKind, fRelocUserRC,
    461                                                      pfnInvalidateR3, pfnHandlerR3,
    462                                                      pfnHandlerRC, pfnPfHandlerRC,
    463                                                      pszDesc, phType);
    464 
    465         AssertMsgFailed(("Failed to resolve %s.%s, rc=%Rrc.\n", VMMRC_MAIN_MODULE_NAME, pszPfHandlerRC, rc));
    466     }
    467     else
    468         AssertMsgFailed(("Failed to resolve %s.%s, rc=%Rrc.\n", VMMRC_MAIN_MODULE_NAME, pszHandlerRC, rc));
    469     return rc;
    470 }
    471 
    472 
    473 /**
    474  * Register a access handler for a virtual range.
    475  *
    476  * @returns VBox status code.
    477  * @param   pVM             The cross context VM structure.
    478  * @param   pVCpu           The cross context virtual CPU structure of the
    479  *                          calling EMT.
    480  * @param   hType           The handler type.
    481  * @param   GCPtr           Start address.
    482  * @param   GCPtrLast       Last address (inclusive).
    483  * @param   pvUserR3        The ring-3 context user argument.
    484  * @param   pvUserRC        The raw-mode context user argument.  Whether this is
    485  *                          automatically relocated or not depends on the type.
    486  * @param   pszDesc         Pointer to description string. This must not be freed.
    487  */
    488 VMMR3_INT_DECL(int) PGMR3HandlerVirtualRegister(PVM pVM, PVMCPU pVCpu, PGMVIRTHANDLERTYPE hType, RTGCPTR GCPtr, RTGCPTR GCPtrLast,
    489                                                 void *pvUserR3, RTRCPTR pvUserRC, const char *pszDesc)
    490 {
    491     AssertReturn(VM_IS_RAW_MODE_ENABLED(pVM), VERR_NOT_AVAILABLE); /* Only supported/relevant for raw-mode. */
    492     PPGMVIRTHANDLERTYPEINT pType = PGMVIRTHANDLERTYPEINT_FROM_HANDLE(pVM, hType);
    493     Log(("PGMR3HandlerVirtualRegister: GCPhys=%RGp GCPhysLast=%RGp pvUserR3=%RHv pvUserGC=%RRv hType=%#x (%d, %s) pszDesc=%RHv:%s\n",
    494          GCPtr, GCPtrLast, pvUserR3, pvUserRC, hType, pType->enmKind, R3STRING(pType->pszDesc), pszDesc, R3STRING(pszDesc)));
    495 
    496     /*
    497      * Validate input.
    498      */
    499     AssertReturn(pType->u32Magic == PGMVIRTHANDLERTYPEINT_MAGIC, VERR_INVALID_HANDLE);
    500     AssertMsgReturn(GCPtr < GCPtrLast, ("GCPtr >= GCPtrLast (%RGp >= %RGp)\n", GCPtr, GCPtrLast), VERR_INVALID_PARAMETER);
    501     switch (pType->enmKind)
    502     {
    503         case PGMVIRTHANDLERKIND_ALL:
    504             /* Simplification for PGMPhysRead and others: Full pages. */
    505             AssertReleaseMsgReturn(   (GCPtr     & PAGE_OFFSET_MASK) == 0
    506                                    && (GCPtrLast & PAGE_OFFSET_MASK) == PAGE_OFFSET_MASK,
    507                                    ("PGMVIRTHANDLERKIND_ALL: GCPtr=%RGv GCPtrLast=%RGv\n", GCPtr, GCPtrLast),
    508                                    VERR_NOT_IMPLEMENTED);
    509             break;
    510         case PGMVIRTHANDLERKIND_WRITE:
    511         case PGMVIRTHANDLERKIND_HYPERVISOR:
    512             break;
    513         default:
    514             AssertMsgFailedReturn(("Invalid enmKind=%d!\n", pType->enmKind), VERR_INVALID_PARAMETER);
    515     }
    516     AssertMsgReturn(   (RTRCUINTPTR)pvUserRC < 0x10000
    517                     || MMHyperR3ToRC(pVM, MMHyperRCToR3(pVM, pvUserRC)) == pvUserRC,
    518                     ("Not RC pointer! pvUserRC=%RRv\n", pvUserRC),
    519                     VERR_INVALID_PARAMETER);
    520 
    521     /*
    522      * Allocate and initialize a new entry.
    523      */
    524     unsigned cPages = (RT_ALIGN(GCPtrLast + 1, PAGE_SIZE) - (GCPtr & PAGE_BASE_GC_MASK)) >> PAGE_SHIFT;
    525     PPGMVIRTHANDLER pNew;
    526     int rc = MMHyperAlloc(pVM, RT_UOFFSETOF_DYN(PGMVIRTHANDLER, aPhysToVirt[cPages]), 0, MM_TAG_PGM_HANDLERS, (void **)&pNew); /** @todo r=bird: incorrect member name PhysToVirt? */
    527     if (RT_FAILURE(rc))
    528         return rc;
    529 
    530     pNew->Core.Key      = GCPtr;
    531     pNew->Core.KeyLast  = GCPtrLast;
    532 
    533     pNew->hType         = hType;
    534     pNew->pvUserRC      = pvUserRC;
    535     pNew->pvUserR3      = pvUserR3;
    536     pNew->pszDesc       = pszDesc ? pszDesc : pType->pszDesc;
    537     pNew->cb            = GCPtrLast - GCPtr + 1;
    538     pNew->cPages        = cPages;
    539     /* Will be synced at next guest execution attempt. */
    540     while (cPages-- > 0)
    541     {
    542         pNew->aPhysToVirt[cPages].Core.Key = NIL_RTGCPHYS;
    543         pNew->aPhysToVirt[cPages].Core.KeyLast = NIL_RTGCPHYS;
    544         pNew->aPhysToVirt[cPages].offVirtHandler = -(int32_t)RT_UOFFSETOF_DYN(PGMVIRTHANDLER, aPhysToVirt[cPages]);
    545         pNew->aPhysToVirt[cPages].offNextAlias = 0;
    546     }
    547 
    548     /*
    549      * Try to insert it into the tree.
    550      *
    551      * The current implementation doesn't allow multiple handlers for
    552      * the same range this makes everything much simpler and faster.
    553      */
    554     AVLROGCPTRTREE *pRoot = pType->enmKind != PGMVIRTHANDLERKIND_HYPERVISOR
    555                           ? &pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers
    556                           : &pVM->pgm.s.CTX_SUFF(pTrees)->HyperVirtHandlers;
    557     pgmLock(pVM);
    558     if (*pRoot != 0)
    559     {
    560         PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrGetBestFit(pRoot, pNew->Core.Key, true);
    561         if (    !pCur
    562             ||  GCPtr     > pCur->Core.KeyLast
    563             ||  GCPtrLast < pCur->Core.Key)
    564             pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrGetBestFit(pRoot, pNew->Core.Key, false);
    565         if (    pCur
    566             &&  GCPtr     <= pCur->Core.KeyLast
    567             &&  GCPtrLast >= pCur->Core.Key)
    568         {
    569             /*
    570              * The LDT sometimes conflicts with the IDT and LDT ranges while being
    571              * updated on linux. So, we don't assert simply log it.
    572              */
    573             Log(("PGMR3HandlerVirtualRegister: Conflict with existing range %RGv-%RGv (%s), req. %RGv-%RGv (%s)\n",
    574                  pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc, GCPtr, GCPtrLast, pszDesc));
    575             MMHyperFree(pVM, pNew);
    576             pgmUnlock(pVM);
    577             return VERR_PGM_HANDLER_VIRTUAL_CONFLICT;
    578         }
    579     }
    580     if (RTAvlroGCPtrInsert(pRoot, &pNew->Core))
    581     {
    582         if (pType->enmKind != PGMVIRTHANDLERKIND_HYPERVISOR)
    583         {
    584             pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL | PGM_SYNC_CLEAR_PGM_POOL;
    585             VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
    586         }
    587         PGMHandlerVirtualTypeRetain(pVM, hType);
    588         pgmUnlock(pVM);
    589 
    590 #ifdef VBOX_WITH_STATISTICS
    591         rc = STAMR3RegisterF(pVM, &pNew->Stat, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pNew->pszDesc,
    592                              "/PGM/VirtHandler/Calls/%RGv-%RGv", pNew->Core.Key, pNew->Core.KeyLast);
    593         AssertRC(rc);
    594 #endif
    595         return VINF_SUCCESS;
    596     }
    597 
    598     pgmUnlock(pVM);
    599     AssertFailed();
    600     MMHyperFree(pVM, pNew);
    601     return VERR_PGM_HANDLER_VIRTUAL_CONFLICT;
    602 
    603 }
    604 
    605 
    606 /**
    607  * Changes the type of a virtual handler.
    608  *
    609  * The new and old type must have the same access kind.
    610  *
    611  * @returns VBox status code.
    612  * @param   pVM             The cross context VM structure.
    613  * @param   GCPtr           Start address of the virtual handler.
    614  * @param   hNewType        The new handler type.
    615  */
    616 VMMR3_INT_DECL(int) PGMHandlerVirtualChangeType(PVM pVM, RTGCPTR GCPtr, PGMVIRTHANDLERTYPE hNewType)
    617 {
    618     PPGMVIRTHANDLERTYPEINT pNewType = PGMVIRTHANDLERTYPEINT_FROM_HANDLE(pVM, hNewType);
    619     AssertReturn(pNewType->u32Magic == PGMVIRTHANDLERTYPEINT_MAGIC, VERR_INVALID_HANDLE);
    620 
    621     pgmLock(pVM);
    622     PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrGet(&pVM->pgm.s.pTreesR3->VirtHandlers, GCPtr);
    623     if (pCur)
    624     {
    625         PGMVIRTHANDLERTYPE     hOldType = pCur->hType;
    626         PPGMVIRTHANDLERTYPEINT pOldType = PGMVIRTHANDLERTYPEINT_FROM_HANDLE(pVM, hOldType);
    627         if (pOldType != pNewType)
    628         {
    629             AssertReturnStmt(pNewType->enmKind == pOldType->enmKind, pgmUnlock(pVM), VERR_ACCESS_DENIED);
    630             PGMHandlerVirtualTypeRetain(pVM, hNewType);
    631             pCur->hType = hNewType;
    632             PGMHandlerVirtualTypeRelease(pVM, hOldType);
    633         }
    634         pgmUnlock(pVM);
    635         return VINF_SUCCESS;
    636     }
    637     pgmUnlock(pVM);
    638     AssertMsgFailed(("Range %#x not found!\n", GCPtr));
    639     return VERR_INVALID_PARAMETER;
    640 }
    641 
    642 
    643 /**
    644  * Deregister an access handler for a virtual range.
    645  *
    646  * @returns VBox status code.
    647  * @param   pVM         The cross context VM structure.
    648  * @param   pVCpu       The cross context virtual CPU structure of the calling
    649  *                      EMT.
    650  * @param   GCPtr       Start address.
    651  * @param   fHypervisor Set if PGMVIRTHANDLERKIND_HYPERVISOR, false if not.
    652  * @thread  EMT(pVCpu)
    653  */
    654 VMMR3_INT_DECL(int) PGMHandlerVirtualDeregister(PVM pVM, PVMCPU pVCpu, RTGCPTR GCPtr, bool fHypervisor)
    655 {
    656     pgmLock(pVM);
    657 
    658     PPGMVIRTHANDLER pCur;
    659     if (!fHypervisor)
    660     {
    661         /*
    662          * Normal guest handler.
    663          */
    664         pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrRemove(&pVM->pgm.s.CTX_SUFF(pTrees)->VirtHandlers, GCPtr);
    665         AssertMsgReturnStmt(pCur, ("GCPtr=%RGv\n", GCPtr), pgmUnlock(pVM), VERR_INVALID_PARAMETER);
    666         Assert(PGMVIRTANDLER_GET_TYPE(pVM, pCur)->enmKind != PGMVIRTHANDLERKIND_HYPERVISOR);
    667 
    668         Log(("PGMHandlerVirtualDeregister: Removing Virtual (%d) Range %RGv-%RGv %s\n",
    669              PGMVIRTANDLER_GET_TYPE(pVM, pCur)->enmKind, pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc));
    670 
    671         /* Reset the flags and remove phys2virt nodes. */
    672         for (uint32_t iPage = 0; iPage < pCur->cPages; iPage++)
    673             if (pCur->aPhysToVirt[iPage].offNextAlias & PGMPHYS2VIRTHANDLER_IN_TREE)
    674                 pgmHandlerVirtualClearPage(pVM, pCur, iPage);
    675 
    676         /* Schedule CR3 sync. */
    677         pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL | PGM_SYNC_CLEAR_PGM_POOL;
    678         VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
    679     }
    680     else
    681     {
    682         /*
    683          * Hypervisor one (hypervisor relocation or termination only).
    684          */
    685         pCur = (PPGMVIRTHANDLER)RTAvlroGCPtrRemove(&pVM->pgm.s.CTX_SUFF(pTrees)->HyperVirtHandlers, GCPtr);
    686         AssertMsgReturnStmt(pCur, ("GCPtr=%RGv\n", GCPtr), pgmUnlock(pVM), VERR_INVALID_PARAMETER);
    687         Assert(PGMVIRTANDLER_GET_TYPE(pVM, pCur)->enmKind == PGMVIRTHANDLERKIND_HYPERVISOR);
    688 
    689         Log(("PGMHandlerVirtualDeregister: Removing Hyper Virtual Range %RGv-%RGv %s\n",
    690              pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc));
    691     }
    692 
    693     pgmUnlock(pVM);
    694 
    695     /*
    696      * Free it.
    697      */
    698 #ifdef VBOX_WITH_STATISTICS
    699     STAMR3DeregisterF(pVM->pUVM, "/PGM/VirtHandler/Calls/%RGv-%RGv", pCur->Core.Key, pCur->Core.KeyLast);
    700 #endif
    701     PGMHandlerVirtualTypeRelease(pVM, pCur->hType);
    702     MMHyperFree(pVM, pCur);
    703 
    704     return VINF_SUCCESS;
    705 }
    706 
    707 #endif /* VBOX_WITH_RAW_MODE */
    708 
    709335
    710336/**
  • trunk/src/VBox/VMM/VMMR3/PGMPhys.cpp

    r80161 r80163  
    47944794        NEMR3NotifySetA20(pVCpu, fEnable);
    47954795#ifdef PGM_WITH_A20
    4796         pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;
    47974796        VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
    47984797        pgmR3RefreshShadowModeAfterA20Change(pVCpu);
  • trunk/src/VBox/VMM/VMMR3/PGMSavedState.cpp

    r80074 r80163  
    31743174                VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL);
    31753175                VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
    3176                 pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;
    31773176                /** @todo For guest PAE, we might get the wrong
    31783177                 *        aGCPhysGstPaePDs values now. We should used the
     
    32613260                VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL);
    32623261                VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
    3263                 pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;
    32643262            }
    32653263        }
  • trunk/src/VBox/VMM/include/PGMInline.h

    r80135 r80163  
    12611261
    12621262
    1263 #ifdef VBOX_WITH_RAW_MODE
    1264 /**
    1265  * Clears one physical page of a virtual handler.
    1266  *
    1267  * @param   pVM         The cross context VM structure.
    1268  * @param   pCur        Virtual handler structure.
    1269  * @param   iPage       Physical page index.
    1270  *
    1271  * @remark  Only used when PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL is being set, so no
    1272  *          need to care about other handlers in the same page.
    1273  */
    1274 DECLINLINE(void) pgmHandlerVirtualClearPage(PVM pVM, PPGMVIRTHANDLER pCur, unsigned iPage)
    1275 {
    1276     const PPGMPHYS2VIRTHANDLER pPhys2Virt = &pCur->aPhysToVirt[iPage];
    1277 
    1278     /*
    1279      * Remove the node from the tree (it's supposed to be in the tree if we get here!).
    1280      */
    1281 # ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
    1282     AssertReleaseMsg(pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_IN_TREE,
    1283                      ("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
    1284                       pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias));
    1285 # endif
    1286     if (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_IS_HEAD)
    1287     {
    1288         /* We're the head of the alias chain. */
    1289         PPGMPHYS2VIRTHANDLER pRemove = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysRemove(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key); NOREF(pRemove);
    1290 # ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
    1291         AssertReleaseMsg(pRemove != NULL,
    1292                          ("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
    1293                           pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias));
    1294         AssertReleaseMsg(pRemove == pPhys2Virt,
    1295                          ("wanted: pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n"
    1296                           "   got:    pRemove=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
    1297                           pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias,
    1298                           pRemove, pRemove->Core.Key, pRemove->Core.KeyLast, pRemove->offVirtHandler, pRemove->offNextAlias));
    1299 # endif
    1300         if (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK)
    1301         {
    1302             /* Insert the next list in the alias chain into the tree. */
    1303             PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
    1304 # ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
    1305             AssertReleaseMsg(pNext->offNextAlias & PGMPHYS2VIRTHANDLER_IN_TREE,
    1306                              ("pNext=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
    1307                              pNext, pNext->Core.Key, pNext->Core.KeyLast, pNext->offVirtHandler, pNext->offNextAlias));
    1308 # endif
    1309             pNext->offNextAlias |= PGMPHYS2VIRTHANDLER_IS_HEAD;
    1310             bool fRc = RTAvlroGCPhysInsert(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, &pNext->Core);
    1311             AssertRelease(fRc);
    1312         }
    1313     }
    1314     else
    1315     {
    1316         /* Locate the previous node in the alias chain. */
    1317         PPGMPHYS2VIRTHANDLER pPrev = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key);
    1318 # ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
    1319         AssertReleaseMsg(pPrev != pPhys2Virt,
    1320                          ("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} pPrev=%p\n",
    1321                           pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias, pPrev));
    1322 # endif
    1323         for (;;)
    1324         {
    1325             PPGMPHYS2VIRTHANDLER pNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPrev + (pPrev->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
    1326             if (pNext == pPhys2Virt)
    1327             {
    1328                 /* unlink. */
    1329                 LogFlow(("pgmHandlerVirtualClearPage: removed %p:{.offNextAlias=%#RX32} from alias chain. prev %p:{.offNextAlias=%#RX32} [%RGp-%RGp]\n",
    1330                          pPhys2Virt, pPhys2Virt->offNextAlias, pPrev, pPrev->offNextAlias, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast));
    1331                 if (!(pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK))
    1332                     pPrev->offNextAlias &= ~PGMPHYS2VIRTHANDLER_OFF_MASK;
    1333                 else
    1334                 {
    1335                     PPGMPHYS2VIRTHANDLER pNewNext = (PPGMPHYS2VIRTHANDLER)((intptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
    1336                     pPrev->offNextAlias = ((intptr_t)pNewNext - (intptr_t)pPrev)
    1337                                         | (pPrev->offNextAlias & ~PGMPHYS2VIRTHANDLER_OFF_MASK);
    1338                 }
    1339                 break;
    1340             }
    1341 
    1342             /* next */
    1343             if (pNext == pPrev)
    1344             {
    1345 # ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL
    1346                 AssertReleaseMsg(pNext != pPrev,
    1347                                  ("pPhys2Virt=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32} pPrev=%p\n",
    1348                                   pPhys2Virt, pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler, pPhys2Virt->offNextAlias, pPrev));
    1349 # endif
    1350                 break;
    1351             }
    1352             pPrev = pNext;
    1353         }
    1354     }
    1355     Log2(("PHYS2VIRT: Removing %RGp-%RGp %#RX32 %s\n",
    1356           pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offNextAlias, R3STRING(pCur->pszDesc)));
    1357     pPhys2Virt->offNextAlias = 0;
    1358     pPhys2Virt->Core.KeyLast = NIL_RTGCPHYS; /* require reinsert */
    1359 
    1360     /*
    1361      * Clear the ram flags for this page.
    1362      */
    1363     PPGMPAGE pPage = pgmPhysGetPage(pVM, pPhys2Virt->Core.Key);
    1364     AssertReturnVoid(pPage);
    1365     PGM_PAGE_SET_HNDL_VIRT_STATE(pPage, PGM_PAGE_HNDL_VIRT_STATE_NONE);
    1366 }
    1367 #endif /* VBOX_WITH_RAW_MODE */
    1368 
    1369 
    13701263/**
    13711264 * Internal worker for finding a 'in-use' shadow page give by it's physical address.
  • trunk/src/VBox/VMM/include/PGMInternal.h

    r80135 r80163  
    694694
    695695
    696 #ifdef VBOX_WITH_RAW_MODE
    697 
    698 /**
    699  * Cache node for the physical addresses covered by a virtual handler.
    700  */
    701 typedef struct PGMPHYS2VIRTHANDLER
    702 {
    703     /** Core node for the tree based on physical ranges. */
    704     AVLROGCPHYSNODECORE                 Core;
    705     /** Offset from this struct to the PGMVIRTHANDLER structure. */
    706     int32_t                             offVirtHandler;
    707     /** Offset of the next alias relative to this one.
    708      * Bit 0 is used for indicating whether we're in the tree.
    709      * Bit 1 is used for indicating that we're the head node.
    710      */
    711     int32_t                             offNextAlias;
    712 } PGMPHYS2VIRTHANDLER;
    713 /** Pointer to a phys to virtual handler structure. */
    714 typedef PGMPHYS2VIRTHANDLER *PPGMPHYS2VIRTHANDLER;
    715 
    716 /** The bit in PGMPHYS2VIRTHANDLER::offNextAlias used to indicate that the
    717  * node is in the tree. */
    718 # define PGMPHYS2VIRTHANDLER_IN_TREE     RT_BIT(0)
    719 /** The bit in PGMPHYS2VIRTHANDLER::offNextAlias used to indicate that the
    720  * node is in the head of an alias chain.
    721  * The PGMPHYS2VIRTHANDLER_IN_TREE is always set if this bit is set. */
    722 # define PGMPHYS2VIRTHANDLER_IS_HEAD     RT_BIT(1)
    723 /** The mask to apply to PGMPHYS2VIRTHANDLER::offNextAlias to get the offset. */
    724 # define PGMPHYS2VIRTHANDLER_OFF_MASK    (~(int32_t)3)
    725 
    726 
    727 /**
    728  * Virtual page access handler type registration.
    729  */
    730 typedef struct PGMVIRTANDLERTYPEINT
    731 {
    732     /** Number of references.   */
    733     uint32_t volatile                   cRefs;
    734     /** Magic number (PGMVIRTHANDLERTYPEINT_MAGIC). */
    735     uint32_t                            u32Magic;
    736     /** Link of handler types anchored in PGMTREES::HeadVirtHandlerTypes. */
    737     RTLISTOFF32NODE                     ListNode;
    738     /** The kind of accesses we're handling. */
    739     PGMVIRTHANDLERKIND                  enmKind;
    740     /** The PGM_PAGE_HNDL_PHYS_STATE_XXX value corresponding to enmKind. */
    741     uint32_t                            uState;
    742     /** Whether the pvUserRC argument should be automatically relocated or not. */
    743     bool                                fRelocUserRC;
    744     bool                                afPadding[HC_ARCH_BITS == 64 ? 7 : 3];
    745     /** Pointer to RC callback function. */
    746     RCPTRTYPE(PFNPGMVIRTHANDLER)        pfnHandlerRC;
    747     /** Pointer to RC callback function for \#PFs. */
    748     RCPTRTYPE(PFNPGMRCVIRTPFHANDLER)    pfnPfHandlerRC;
    749     /** Pointer to the R3 callback function for invalidation. */
    750     R3PTRTYPE(PFNPGMR3VIRTINVALIDATE)   pfnInvalidateR3;
    751     /** Pointer to R3 callback function. */
    752     R3PTRTYPE(PFNPGMVIRTHANDLER)        pfnHandlerR3;
    753     /** Description / Name. For easing debugging. */
    754     R3PTRTYPE(const char *)             pszDesc;
    755 } PGMVIRTHANDLERTYPEINT;
    756 /** Pointer to a virtual access handler type registration. */
    757 typedef PGMVIRTHANDLERTYPEINT *PPGMVIRTHANDLERTYPEINT;
    758 /** Magic value for the virtual handler callbacks (Sir Arthur Charles Clarke). */
    759 # define PGMVIRTHANDLERTYPEINT_MAGIC       UINT32_C(0x19171216)
    760 /** Magic value for the virtual handler callbacks. */
    761 # define PGMVIRTHANDLERTYPEINT_MAGIC_DEAD  UINT32_C(0x20080319)
    762 
    763 /**
    764  * Converts a handle to a pointer.
    765  * @returns PPGMVIRTHANDLERTYPEINT
    766  * @param   a_pVM           The cross context VM structure.
    767  * @param   a_hType         Vitual access handler type handle.
    768  */
    769 # define PGMVIRTHANDLERTYPEINT_FROM_HANDLE(a_pVM, a_hType) ((PPGMVIRTHANDLERTYPEINT)MMHyperHeapOffsetToPtr(a_pVM, a_hType))
    770 
    771 
    772 /**
    773  * Virtual page access handler structure.
    774  *
    775  * This is used to keep track of virtual address ranges
    776  * which are being monitored in some kind of way.
    777  */
    778 typedef struct PGMVIRTHANDLER
    779 {
    780     /** Core node for the tree based on virtual ranges. */
    781     AVLROGCPTRNODECORE                  Core;
    782     /** Size of the range (in bytes). */
    783     uint32_t                            cb;
    784     /** Number of cache pages. */
    785     uint32_t                            cPages;
    786     /** Registered handler type handle (heap offset). */
    787     PGMVIRTHANDLERTYPE                  hType;
    788     /** User argument for RC handlers. */
    789     RCPTRTYPE(void *)                   pvUserRC;
    790     /** User argument for R3 handlers. */
    791     R3PTRTYPE(void *)                   pvUserR3;
    792     /** Description / Name. For easing debugging. */
    793     R3PTRTYPE(const char *)             pszDesc;
    794 # ifdef VBOX_WITH_STATISTICS
    795     /** Profiling of this handler. */
    796     STAMPROFILE                         Stat;
    797 # endif
    798     /** Array of cached physical addresses for the monitored ranged. */
    799     PGMPHYS2VIRTHANDLER                 aPhysToVirt[HC_ARCH_BITS == 32 ? 1 : 2];
    800 } PGMVIRTHANDLER;
    801 /** Pointer to a virtual page access handler structure. */
    802 typedef PGMVIRTHANDLER *PPGMVIRTHANDLER;
    803 
    804 /**
    805  * Gets the type record for a virtual handler (no reference added).
    806  * @returns PPGMVIRTHANDLERTYPEINT
    807  * @param   a_pVM           The cross context VM structure.
    808  * @param   a_pVirtHandler  Pointer to the virtual handler structure
    809  *                          (PGMVIRTHANDLER).
    810  */
    811 # define PGMVIRTANDLER_GET_TYPE(a_pVM, a_pVirtHandler) PGMVIRTHANDLERTYPEINT_FROM_HANDLE(a_pVM, (a_pVirtHandler)->hType)
    812 
    813 #endif /* VBOX_WITH_RAW_MODE */
    814 
    815 
    816696/**
    817697 * A Physical Guest Page tracking structure.
     
    840720        /** 7:6   - Unused. */
    841721        uint64_t    u2Unused0           : 2;
    842         /** 9:8   - The physical handler state (PGM_PAGE_HNDL_VIRT_STATE_*). */
    843         uint64_t    u2HandlerVirtStateY : 2;
     722        /** 9:8   - Unused (was used by PGM_PAGE_HNDL_VIRT_STATE_*). */
     723        uint64_t    u2Unused1          : 2;
    844724        /** 11:10 - NEM state bits. */
    845725        uint64_t    u2NemStateY         : 2;
     
    12051085#define PGM_PAGE_GET_PDE_TYPE(a_pPage)          ( (a_pPage)->s.u2PDETypeY )
    12061086
    1207 /** Enabled optimized access handler tests.
    1208  * These optimizations makes ASSUMPTIONS about the state values and the s1
    1209  * layout.  When enabled, the compiler should normally generate more compact
    1210  * code.
    1211  */
    1212 #define PGM_PAGE_WITH_OPTIMIZED_HANDLER_ACCESS  1
    1213 
    12141087/** @name Physical Access Handler State values (PGMPAGE::u2HandlerPhysStateY).
    12151088 *
     
    12891162
    12901163/**
    1291  * Checks if the page has any virtual access handlers.
    1292  * @returns true/false
    1293  * @param   a_pPage     Pointer to the physical guest page tracking structure.
    1294  */
    1295 #define PGM_PAGE_HAS_ANY_VIRTUAL_HANDLERS(a_pPage) \
    1296     ( PGM_PAGE_GET_HNDL_VIRT_STATE(a_pPage) != PGM_PAGE_HNDL_VIRT_STATE_NONE )
    1297 
    1298 /**
    12991164 * Same as PGM_PAGE_HAS_ANY_VIRTUAL_HANDLERS - can't disable pages in
    13001165 * virtual handlers.
     
    13111176 * @param   a_pPage     Pointer to the physical guest page tracking structure.
    13121177 */
    1313 #ifdef PGM_PAGE_WITH_OPTIMIZED_HANDLER_ACCESS
    1314 # define PGM_PAGE_HAS_ANY_HANDLERS(a_pPage) \
    1315     ( ((a_pPage)->au32[0] & UINT16_C(0x0303)) != 0 )
    1316 #else
    1317 # define PGM_PAGE_HAS_ANY_HANDLERS(a_pPage) \
    1318     (   PGM_PAGE_GET_HNDL_PHYS_STATE(a_pPage) != PGM_PAGE_HNDL_PHYS_STATE_NONE \
    1319      || PGM_PAGE_GET_HNDL_VIRT_STATE(a_pPage) != PGM_PAGE_HNDL_VIRT_STATE_NONE )
    1320 #endif
     1178#define PGM_PAGE_HAS_ANY_HANDLERS(a_pPage) \
     1179    ( PGM_PAGE_GET_HNDL_PHYS_STATE(a_pPage) != PGM_PAGE_HNDL_PHYS_STATE_NONE )
    13211180
    13221181/**
     
    13251184 * @param   a_pPage     Pointer to the physical guest page tracking structure.
    13261185 */
    1327 #ifdef PGM_PAGE_WITH_OPTIMIZED_HANDLER_ACCESS
    1328 # define PGM_PAGE_HAS_ACTIVE_HANDLERS(a_pPage) \
    1329     ( ((a_pPage)->au32[0] & UINT16_C(0x0202)) != 0 )
    1330 #else
    1331 # define PGM_PAGE_HAS_ACTIVE_HANDLERS(a_pPage) \
    1332     (   PGM_PAGE_GET_HNDL_PHYS_STATE(a_pPage) >= PGM_PAGE_HNDL_PHYS_STATE_WRITE \
    1333      || PGM_PAGE_GET_HNDL_VIRT_STATE(a_pPage) >= PGM_PAGE_HNDL_VIRT_STATE_WRITE )
    1334 #endif
     1186#define PGM_PAGE_HAS_ACTIVE_HANDLERS(a_pPage) \
     1187     (PGM_PAGE_GET_HNDL_PHYS_STATE(a_pPage) >= PGM_PAGE_HNDL_PHYS_STATE_WRITE )
    13351188
    13361189/**
     
    13391192 * @param   a_pPage     Pointer to the physical guest page tracking structure.
    13401193 */
    1341 #ifdef PGM_PAGE_WITH_OPTIMIZED_HANDLER_ACCESS
    1342 # define PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(a_pPage) \
    1343     (   ( ((a_pPage)->au8[0] | (a_pPage)->au8[1]) & UINT8_C(0x3) ) \
    1344      == PGM_PAGE_HNDL_PHYS_STATE_ALL )
    1345 #else
    1346 # define PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(a_pPage) \
    1347     (   PGM_PAGE_GET_HNDL_PHYS_STATE(a_pPage) == PGM_PAGE_HNDL_PHYS_STATE_ALL \
    1348      || PGM_PAGE_GET_HNDL_VIRT_STATE(a_pPage) == PGM_PAGE_HNDL_VIRT_STATE_ALL )
    1349 #endif
     1194#define PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(a_pPage) \
     1195    ( PGM_PAGE_GET_HNDL_PHYS_STATE(a_pPage) == PGM_PAGE_HNDL_PHYS_STATE_ALL )
    13501196
    13511197
     
    32353081    STAMCOUNTER StatR3RamRangeTlbHits;              /**< R3: RAM range TLB hits. */
    32363082    STAMCOUNTER StatR3RamRangeTlbMisses;            /**< R3: RAM range TLB misses. */
    3237     STAMPROFILE StatRZSyncCR3HandlerVirtualReset;   /**< RC/R0: Profiling of the virtual handler resets. */
    3238     STAMPROFILE StatRZSyncCR3HandlerVirtualUpdate;  /**< RC/R0: Profiling of the virtual handler updates. */
    3239     STAMPROFILE StatR3SyncCR3HandlerVirtualReset;   /**< R3: Profiling of the virtual handler resets. */
    3240     STAMPROFILE StatR3SyncCR3HandlerVirtualUpdate;  /**< R3: Profiling of the virtual handler updates. */
    32413083    STAMCOUNTER StatR3PhysHandlerReset;             /**< R3: The number of times PGMHandlerPhysicalReset is called. */
    32423084    STAMCOUNTER StatRZPhysHandlerReset;             /**< RC/R0: The number of times PGMHandlerPhysicalReset is called. */
     
    32453087    STAMCOUNTER StatRZPhysHandlerLookupHits;        /**< RC/R0: Number of cache hits when lookup up physical handlers. */
    32463088    STAMCOUNTER StatRZPhysHandlerLookupMisses;      /**< RC/R0: Number of cache misses when looking up physical handlers */
    3247     STAMPROFILE StatRZVirtHandlerSearchByPhys;      /**< RC/R0: Profiling of pgmHandlerVirtualFindByPhysAddr. */
    3248     STAMPROFILE StatR3VirtHandlerSearchByPhys;      /**< R3: Profiling of pgmHandlerVirtualFindByPhysAddr. */
    32493089    STAMCOUNTER StatRZPageReplaceShared;            /**< RC/R0: Times a shared page has been replaced by a private one. */
    32503090    STAMCOUNTER StatRZPageReplaceZero;              /**< RC/R0: Times the zero page has been replaced by a private one. */
     
    37623602    STAMPROFILE StatRZTrap0eTime2GuestTrap;         /**< RC/R0: Profiling of the Trap0eHandler body when the cause is a guest trap. */
    37633603    STAMPROFILE StatRZTrap0eTime2HndPhys;           /**< RC/R0: Profiling of the Trap0eHandler body when the cause is a physical handler. */
    3764     STAMPROFILE StatRZTrap0eTime2HndVirt;           /**< RC/R0: Profiling of the Trap0eHandler body when the cause is a virtual handler. */
    37653604    STAMPROFILE StatRZTrap0eTime2HndUnhandled;      /**< RC/R0: Profiling of the Trap0eHandler body when the cause is access outside the monitored areas of a monitored page. */
    37663605    STAMPROFILE StatRZTrap0eTime2InvalidPhys;       /**< RC/R0: Profiling of the Trap0eHandler body when the cause is access to an invalid physical guest address. */
     
    37703609    STAMPROFILE StatRZTrap0eTime2OutOfSync;         /**< RC/R0: Profiling of the Trap0eHandler body when the cause is an out-of-sync page. */
    37713610    STAMPROFILE StatRZTrap0eTime2OutOfSyncHndPhys;  /**< RC/R0: Profiling of the Trap0eHandler body when the cause is an out-of-sync physical handler page. */
    3772     STAMPROFILE StatRZTrap0eTime2OutOfSyncHndVirt;  /**< RC/R0: Profiling of the Trap0eHandler body when the cause is an out-of-sync virtual handler page. */
    37733611    STAMPROFILE StatRZTrap0eTime2OutOfSyncHndObs;   /**< RC/R0: Profiling of the Trap0eHandler body when the cause is an obsolete handler page. */
    37743612    STAMPROFILE StatRZTrap0eTime2SyncPT;            /**< RC/R0: Profiling of the Trap0eHandler body when the cause is lazy syncing of a PT. */
     
    37823620    STAMCOUNTER StatRZTrap0eHandlersPhysAllOpt;     /**< RC/R0: Number of the physical all-access handler traps using the optimization. */
    37833621    STAMCOUNTER StatRZTrap0eHandlersPhysWrite;      /**< RC/R0: Number of traps due to write-physical access handlers. */
    3784     STAMCOUNTER StatRZTrap0eHandlersVirtual;        /**< RC/R0: Number of traps due to virtual access handlers. */
    3785     STAMCOUNTER StatRZTrap0eHandlersVirtualByPhys;  /**< RC/R0: Number of traps due to virtual access handlers found by physical address. */
    3786     STAMCOUNTER StatRZTrap0eHandlersVirtualUnmarked;/**< RC/R0: Number of traps due to virtual access handlers found by virtual address (without proper physical flags). */
    37873622    STAMCOUNTER StatRZTrap0eHandlersUnhandled;      /**< RC/R0: Number of traps due to access outside range of monitored page(s). */
    37883623    STAMCOUNTER StatRZTrap0eHandlersInvalid;        /**< RC/R0: Number of traps due to access to invalid physical memory. */
     
    41573992 * @{
    41583993 */
    4159 /** Updates the virtual access handler state bit in PGMPAGE. */
    4160 #define PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL        RT_BIT(0)
     3994/* 0 used to be PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL */
    41613995/** Always sync CR3. */
    41623996#define PGM_SYNC_ALWAYS                         RT_BIT(1)
  • trunk/src/VBox/VMM/testcase/tstVMStructSize.cpp

    r80018 r80163  
    438438
    439439    /*
    440      * Check that the optimized access macros for PGMPAGE works correctly.
     440     * Check that the optimized access macros for PGMPAGE works correctly (kind of
     441     * obsolete after dropping raw-mode).
    441442     */
    442443    PGMPAGE Page;
     
    456457    PGM_PAGE_SET_HNDL_PHYS_STATE(&Page, PGM_PAGE_HNDL_PHYS_STATE_WRITE);
    457458    CHECK_EXPR(PGM_PAGE_GET_HNDL_PHYS_STATE(&Page) == PGM_PAGE_HNDL_PHYS_STATE_WRITE);
    458     CHECK_EXPR(PGM_PAGE_HAS_ANY_HANDLERS(&Page) == true);
    459     CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_HANDLERS(&Page) == true);
    460     CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(&Page) == false);
    461 
    462     PGM_PAGE_CLEAR(&Page);
    463     PGM_PAGE_SET_HNDL_VIRT_STATE(&Page, PGM_PAGE_HNDL_VIRT_STATE_ALL);
    464     CHECK_EXPR(PGM_PAGE_GET_HNDL_VIRT_STATE(&Page) == PGM_PAGE_HNDL_VIRT_STATE_ALL);
    465     CHECK_EXPR(PGM_PAGE_HAS_ANY_HANDLERS(&Page) == true);
    466     CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_HANDLERS(&Page) == true);
    467     CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(&Page) == true);
    468 
    469     PGM_PAGE_SET_HNDL_VIRT_STATE(&Page, PGM_PAGE_HNDL_VIRT_STATE_WRITE);
    470     CHECK_EXPR(PGM_PAGE_GET_HNDL_VIRT_STATE(&Page) == PGM_PAGE_HNDL_VIRT_STATE_WRITE);
    471     CHECK_EXPR(PGM_PAGE_HAS_ANY_HANDLERS(&Page) == true);
    472     CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_HANDLERS(&Page) == true);
    473     CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(&Page) == false);
    474 
    475 
    476     PGM_PAGE_CLEAR(&Page);
    477     PGM_PAGE_SET_HNDL_PHYS_STATE(&Page, PGM_PAGE_HNDL_PHYS_STATE_ALL);
    478     PGM_PAGE_SET_HNDL_VIRT_STATE(&Page, PGM_PAGE_HNDL_VIRT_STATE_WRITE);
    479     CHECK_EXPR(PGM_PAGE_GET_HNDL_PHYS_STATE(&Page) == PGM_PAGE_HNDL_PHYS_STATE_ALL);
    480     CHECK_EXPR(PGM_PAGE_GET_HNDL_VIRT_STATE(&Page) == PGM_PAGE_HNDL_VIRT_STATE_WRITE);
    481     CHECK_EXPR(PGM_PAGE_HAS_ANY_HANDLERS(&Page) == true);
    482     CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_HANDLERS(&Page) == true);
    483     CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(&Page) == true);
    484 
    485     PGM_PAGE_SET_HNDL_PHYS_STATE(&Page, PGM_PAGE_HNDL_PHYS_STATE_WRITE);
    486     PGM_PAGE_SET_HNDL_VIRT_STATE(&Page, PGM_PAGE_HNDL_VIRT_STATE_ALL);
    487     CHECK_EXPR(PGM_PAGE_GET_HNDL_PHYS_STATE(&Page) == PGM_PAGE_HNDL_PHYS_STATE_WRITE);
    488     CHECK_EXPR(PGM_PAGE_GET_HNDL_VIRT_STATE(&Page) == PGM_PAGE_HNDL_VIRT_STATE_ALL);
    489     CHECK_EXPR(PGM_PAGE_HAS_ANY_HANDLERS(&Page) == true);
    490     CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_HANDLERS(&Page) == true);
    491     CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(&Page) == true);
    492 
    493     PGM_PAGE_SET_HNDL_PHYS_STATE(&Page, PGM_PAGE_HNDL_PHYS_STATE_WRITE);
    494     PGM_PAGE_SET_HNDL_VIRT_STATE(&Page, PGM_PAGE_HNDL_VIRT_STATE_WRITE);
    495     CHECK_EXPR(PGM_PAGE_GET_HNDL_PHYS_STATE(&Page) == PGM_PAGE_HNDL_PHYS_STATE_WRITE);
    496     CHECK_EXPR(PGM_PAGE_GET_HNDL_VIRT_STATE(&Page) == PGM_PAGE_HNDL_VIRT_STATE_WRITE);
    497     CHECK_EXPR(PGM_PAGE_HAS_ANY_HANDLERS(&Page) == true);
    498     CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_HANDLERS(&Page) == true);
    499     CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(&Page) == false);
    500 
    501     PGM_PAGE_SET_HNDL_VIRT_STATE(&Page, PGM_PAGE_HNDL_VIRT_STATE_NONE);
    502     CHECK_EXPR(PGM_PAGE_GET_HNDL_PHYS_STATE(&Page) == PGM_PAGE_HNDL_PHYS_STATE_WRITE);
    503     CHECK_EXPR(PGM_PAGE_GET_HNDL_VIRT_STATE(&Page) == PGM_PAGE_HNDL_VIRT_STATE_NONE);
    504459    CHECK_EXPR(PGM_PAGE_HAS_ANY_HANDLERS(&Page) == true);
    505460    CHECK_EXPR(PGM_PAGE_HAS_ACTIVE_HANDLERS(&Page) == true);
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