VirtualBox

Changeset 6927

Show
Ignore:
Timestamp:
02/12/08 21:44:35 (10 months ago)
Author:
vboxsync
Message:

Converted MM_RAM_FLAGS_VIRTUAL_HANDLER, MM_RAM_FLAGS_VIRTUAL_WRITE
and MM_RAM_FLAGS_VIRTUAL_ALL into a two bit state variable in PGMPAGE.
I've checked this trice because, like last time, bugs may have odd
sideeffects and hide for a while before showing up. Hope I got this
right (unlike for phys).

Fixed a regression from the MM_RAM_FLAGS_PHYSICAL in the physical read/write code.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/include/VBox/mm.h

    r6902 r6927  
    7777#define MM_RAM_FLAGS_MMIO2              RT_BIT(3) 
    7878 
    79 /** PGM has virtual page access handler(s) defined for pages with this flag. */ 
    80 #define MM_RAM_FLAGS_VIRTUAL_HANDLER    RT_BIT(4) 
    81 /** PGM has virtual page access handler(s) for write access. */ 
    82 #define MM_RAM_FLAGS_VIRTUAL_WRITE      RT_BIT(5) 
    83 /** PGM has virtual page access handler(s) for all access. */ 
    84 #define MM_RAM_FLAGS_VIRTUAL_ALL        RT_BIT(6) 
    8579#ifndef VBOX_WITH_NEW_PHYS_CODE 
    8680/** Physical backing memory is allocated dynamically. Not set implies a one time static allocation. */ 
  • trunk/src/VBox/VMM/PGM.cpp

    r6925 r6927  
    21502150            uint16_t    u16 = 0; 
    21512151            SSMR3GetU16(pSSM, &u16); 
    2152             u16 &= PAGE_OFFSET_MASK & ~(  MM_RAM_FLAGS_VIRTUAL_HANDLER | MM_RAM_FLAGS_VIRTUAL_WRITE | MM_RAM_FLAGS_VIRTUAL_ALL 
     2152            u16 &= PAGE_OFFSET_MASK & ~(  RT_BIT(4) | RT_BIT(5) | RT_BIT(6) 
    21532153                                        | RT_BIT(7) | RT_BIT(8) | RT_BIT(9) | RT_BIT(10) ); 
    21542154                   // &= MM_RAM_FLAGS_DYNAMIC_ALLOC | MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_ROM | MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_MMIO2 
  • trunk/src/VBox/VMM/PGMInternal.h

    r6914 r6927  
    405405    AVLROGCPHYSNODECORE                 Core; 
    406406    /** Offset from this struct to the PGMVIRTHANDLER structure. */ 
    407     RTGCINTPTR                          offVirtHandler; 
    408     /** Offset of the next alias relativer to this one. 
     407    int32_t                             offVirtHandler; 
     408    /** Offset of the next alias relative to this one. 
    409409     * Bit 0 is used for indicating whether we're in the tree. 
    410410     * Bit 1 is used for indicating that we're the head node. 
     
    530530    /** The physical handler state (PGM_PAGE_HNDL_PHYS_STATE*) */ 
    531531    uint32_t    u2HandlerPhysStateX : 2; 
    532     uint32_t    u29B : 27; 
     532    /** The virtual handler state (PGM_PAGE_HNDL_VIRT_STATE*) */ 
     533    uint32_t    u2HandlerVirtStateX : 2; 
     534    uint32_t    u29B : 25; 
    533535} PGMPAGE; 
    534536AssertCompileSize(PGMPAGE, 16); 
     
    791793 
    792794/** 
    793  * Checks if the page has any access handlers, including temporarily disabled ones. 
    794  * @returns true/false 
    795  * @param   pPage       Pointer to the physical guest page tracking structure. 
    796  */ 
    797 #define PGM_PAGE_HAVE_ANY_HANDLERS(pPage) \ 
    798     (   (pPage)->u2HandlerPhysStateX != PGM_PAGE_HNDL_PHYS_STATE_NONE \ 
    799      || ((pPage)->HCPhys & MM_RAM_FLAGS_VIRTUAL_HANDLER) ) 
    800  
    801 /** 
    802  * Checks if the page has any active access handlers. 
    803  * @returns true/false 
    804  * @param   pPage       Pointer to the physical guest page tracking structure. 
    805  */ 
    806 #define PGM_PAGE_HAVE_ACTIVE_HANDLERS(pPage) \ 
    807     (   (pPage)->u2HandlerPhysStateX >= PGM_PAGE_HNDL_PHYS_STATE_WRITE \ 
    808      || ((pPage)->HCPhys & MM_RAM_FLAGS_VIRTUAL_HANDLER) ) 
    809  
    810 /** 
    811  * Checks if the page has any active access handlers catching all accesses. 
    812  * @returns true/false 
    813  * @param   pPage       Pointer to the physical guest page tracking structure. 
    814  */ 
    815 #define PGM_PAGE_HAVE_ACTIVE_ALL_HANDLERS(pPage) \ 
    816     (   (pPage)->u2HandlerPhysStateX == PGM_PAGE_HNDL_PHYS_STATE_ALL \ 
    817      || ((pPage)->HCPhys & MM_RAM_FLAGS_VIRTUAL_ALL) ) 
    818  
    819 /** 
    820795 * Checks if the page has any physical access handlers, including temporariliy disabled ones. 
    821796 * @returns true/false 
     
    831806#define PGM_PAGE_HAVE_ACTIVE_PHYSICAL_HANDLERS(pPage)   ( (pPage)->u2HandlerPhysStateX >= PGM_PAGE_HNDL_PHYS_STATE_WRITE ) 
    832807 
     808 
     809/** @name Virtual Access Handler State values (PGMPAGE::u2HandlerVirtStateX). 
     810 * 
     811 * @remarks The values are assigned in order of priority, so we can calculate 
     812 *          the correct state for a page with different handlers installed. 
     813 * @{ */ 
     814/** No handler installed. */ 
     815#define PGM_PAGE_HNDL_VIRT_STATE_NONE       0 
     816/* 1 is reserved so the lineup is identical with the physical ones. */ 
     817/** Write access is monitored. */ 
     818#define PGM_PAGE_HNDL_VIRT_STATE_WRITE      2 
     819/** All access is monitored. */ 
     820#define PGM_PAGE_HNDL_VIRT_STATE_ALL        3 
     821/** @} */ 
     822 
     823/** 
     824 * Gets the virtual access handler state of a page. 
     825 * @returns PGM_PAGE_HNDL_VIRT_STATE_* value. 
     826 * @param   pPage       Pointer to the physical guest page tracking structure. 
     827 */ 
     828#define PGM_PAGE_GET_HNDL_VIRT_STATE(pPage)     ( (pPage)->u2HandlerVirtStateX ) 
     829 
     830/** 
     831 * Sets the virtual access handler state of a page. 
     832 * @param   pPage       Pointer to the physical guest page tracking structure. 
     833 * @param   _uState     The new state value. 
     834 */ 
     835#define PGM_PAGE_SET_HNDL_VIRT_STATE(pPage, _uState) \ 
     836    do { (pPage)->u2HandlerVirtStateX = (_uState); } while (0) 
     837 
    833838/** 
    834839 * Checks if the page has any virtual access handlers. 
     
    836841 * @param   pPage       Pointer to the physical guest page tracking structure. 
    837842 */ 
    838 #define PGM_PAGE_HAVE_ANY_VIRTUAL_HANDLERS(pPage)    ( (pPage)->HCPhys & MM_RAM_FLAGS_VIRTUAL_HANDLER
     843#define PGM_PAGE_HAVE_ANY_VIRTUAL_HANDLERS(pPage)    ( (pPage)->u2HandlerVirtStateX != PGM_PAGE_HNDL_VIRT_STATE_NONE
    839844 
    840845/** 
     
    845850 */ 
    846851#define PGM_PAGE_HAVE_ACTIVE_VIRTUAL_HANDLERS(pPage) PGM_PAGE_HAVE_ANY_VIRTUAL_HANDLERS(pPage) 
     852 
     853 
     854 
     855/** 
     856 * Checks if the page has any access handlers, including temporarily disabled ones. 
     857 * @returns true/false 
     858 * @param   pPage       Pointer to the physical guest page tracking structure. 
     859 */ 
     860#define PGM_PAGE_HAVE_ANY_HANDLERS(pPage) \ 
     861    (   (pPage)->u2HandlerPhysStateX != PGM_PAGE_HNDL_PHYS_STATE_NONE \ 
     862     || (pPage)->u2HandlerVirtStateX != PGM_PAGE_HNDL_VIRT_STATE_NONE ) 
     863 
     864/** 
     865 * Checks if the page has any active access handlers. 
     866 * @returns true/false 
     867 * @param   pPage       Pointer to the physical guest page tracking structure. 
     868 */ 
     869#define PGM_PAGE_HAVE_ACTIVE_HANDLERS(pPage) \ 
     870    (   (pPage)->u2HandlerPhysStateX >= PGM_PAGE_HNDL_PHYS_STATE_WRITE \ 
     871     || (pPage)->u2HandlerVirtStateX >= PGM_PAGE_HNDL_VIRT_STATE_WRITE ) 
     872 
     873/** 
     874 * Checks if the page has any active access handlers catching all accesses. 
     875 * @returns true/false 
     876 * @param   pPage       Pointer to the physical guest page tracking structure. 
     877 */ 
     878#define PGM_PAGE_HAVE_ACTIVE_ALL_HANDLERS(pPage) \ 
     879    (   (pPage)->u2HandlerPhysStateX == PGM_PAGE_HNDL_PHYS_STATE_ALL \ 
     880     || (pPage)->u2HandlerVirtStateX == PGM_PAGE_HNDL_VIRT_STATE_ALL ) 
    847881 
    848882 
     
    24552489 * @{ 
    24562490 */ 
    2457 /** Updates the MM_RAM_FLAGS_VIRTUAL_HANDLER page bit. */ 
     2491/** Updates the virtual access handler state bit in PGMPAGE. */ 
    24582492#define PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL        RT_BIT(0) 
    24592493/** Always sync CR3. */ 
     
    32503284 
    32513285/** 
     3286 * Gets the page state for a virtual handler. 
     3287 * 
     3288 * @returns The virtual handler page state. 
     3289 * @param   pCur    The virtual handler in question. 
     3290 * @remarks This should never be used on a hypervisor access handler. 
     3291 */ 
     3292DECLINLINE(unsigned) pgmHandlerVirtualCalcState(PPGMVIRTHANDLER pCur) 
     3293{ 
     3294    switch (pCur->enmType) 
     3295    { 
     3296        case PGMVIRTHANDLERTYPE_WRITE: 
     3297            return PGM_PAGE_HNDL_VIRT_STATE_WRITE; 
     3298        case PGMVIRTHANDLERTYPE_ALL: 
     3299            return PGM_PAGE_HNDL_VIRT_STATE_ALL; 
     3300        default: 
     3301            AssertFatalMsgFailed(("Invalid type %d\n", pCur->enmType)); 
     3302    } 
     3303} 
     3304 
     3305 
     3306/** 
    32523307 * Clears one physical page of a virtual handler 
    32533308 * 
     
    32553310 * @param   pCur    Virtual handler structure 
    32563311 * @param   iPage   Physical page index 
     3312 * 
     3313 * @remark  Only used when PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL is being set, so no 
     3314 *          need to care about other handlers in the same page. 
    32573315 */ 
    32583316DECLINLINE(void) pgmHandlerVirtualClearPage(PPGM pPGM, PPGMVIRTHANDLER pCur, unsigned iPage) 
     
    33453403     * Clear the ram flags for this page. 
    33463404     */ 
    3347     int rc = pgmRamFlagsClearByGCPhys(pPGM, pPhys2Virt->Core.Key, 
    3348                                       MM_RAM_FLAGS_VIRTUAL_HANDLER | MM_RAM_FLAGS_VIRTUAL_ALL | MM_RAM_FLAGS_VIRTUAL_WRITE); 
    3349     AssertRC(rc); 
     3405    PPGMPAGE pPage = pgmPhysGetPage(pPGM, pPhys2Virt->Core.Key); 
     3406    AssertReturnVoid(pPage); 
     3407    PGM_PAGE_SET_HNDL_VIRT_STATE(pPage, PGM_PAGE_HNDL_VIRT_STATE_NONE); 
    33503408} 
    33513409 
  • trunk/src/VBox/VMM/VMMAll/PGMAllBth.h

    r6913 r6927  
    9393 
    9494# if PGM_WITH_PAGING(PGM_GST_TYPE) 
    95     /* Determine current privilege level */ 
    96     uint32_t cpl = CPUMGetGuestCPL(pVM, pRegFrame); 
    97  
    9895#  ifdef PGM_SYNC_DIRTY_BIT 
    9996    /* 
     
    345342                         * In case of write access continue to the GC write handler. 
    346343                         */ 
    347                         if (    (pPage->HCPhys & (MM_RAM_FLAGS_VIRTUAL_WRITE | MM_RAM_FLAGS_VIRTUAL_ALL)) == MM_RAM_FLAGS_VIRTUAL_WRITE /** @todo PAGE FLAGS */ 
     344                        if (    PGM_PAGE_GET_HNDL_VIRT_STATE(pPage) < PGM_PAGE_HNDL_PHYS_STATE_ALL 
    348345                            && !(uErr & X86_TRAP_PF_P)) 
    349346                        { 
     
    439436                    STAM_COUNTER_INC(&pVM->pgm.s.StatHandlersUnhandled); 
    440437 
    441                     if (    !(pPage->HCPhys & (MM_RAM_FLAGS_VIRTUAL_ALL)) /** @todo PAGE FLAGS */ 
    442                         &&  PGM_PAGE_GET_HNDL_PHYS_STATE(pPage) < PGM_PAGE_HNDL_PHYS_STATE_ALL 
     438                    if (    !PGM_PAGE_HAVE_ACTIVE_ALL_HANDLERS(pPage) 
    443439                        &&  !(uErr & X86_TRAP_PF_P)) 
    444440                    { 
     
    539535 
    540536#  if PGM_WITH_PAGING(PGM_GST_TYPE) && !defined(IN_RING0) 
    541                 if (cpl == 0) 
     537                if (CPUMGetGuestCPL(pVM, pRegFrame) == 0) 
    542538                { 
    543539                    uint64_t fPageGst; 
     
    11281124            const RTHCPHYS HCPhys = pPage->HCPhys; /** @todo FLAGS */ 
    11291125            SHWPTE PteDst; 
    1130             if (    PGM_PAGE_GET_HNDL_PHYS_STATE(pPage) >= PGM_PAGE_HNDL_PHYS_STATE_WRITE 
    1131                 ||  (HCPhys & (MM_RAM_FLAGS_VIRTUAL_ALL | MM_RAM_FLAGS_VIRTUAL_WRITE))) 
     1126            if (PGM_PAGE_HAVE_ACTIVE_HANDLERS(pPage)) 
    11321127            { 
    11331128                /** @todo r=bird: Are we actually handling dirty and access bits for pages with access handlers correctly? No. */ 
    1134                 if (    PGM_PAGE_GET_HNDL_PHYS_STATE(pPage) <= PGM_PAGE_HNDL_PHYS_STATE_WRITE 
    1135                     &&  !(HCPhys & MM_RAM_FLAGS_VIRTUAL_ALL)) 
     1129                if (!PGM_PAGE_HAVE_ACTIVE_ALL_HANDLERS(pPage)) 
    11361130                    PteDst.u = (PteSrc.u & ~(X86_PTE_PAE_PG_MASK | X86_PTE_AVL_MASK | X86_PTE_PAT | X86_PTE_PCD | X86_PTE_PWT | X86_PTE_RW)) 
    11371131                             | (HCPhys & X86_PTE_PAE_PG_MASK); 
  • trunk/src/VBox/VMM/VMMAll/PGMAllGst.h

    r6913 r6927  
    657657#endif 
    658658 
    659     unsigned    fFlags; 
    660     switch (pCur->enmType) 
    661     { 
    662         case PGMVIRTHANDLERTYPE_WRITE:      fFlags = MM_RAM_FLAGS_VIRTUAL_HANDLER | MM_RAM_FLAGS_VIRTUAL_WRITE; break; 
    663         case PGMVIRTHANDLERTYPE_ALL:        fFlags = MM_RAM_FLAGS_VIRTUAL_HANDLER | MM_RAM_FLAGS_VIRTUAL_ALL; break; 
    664         /* hypervisor handlers need no flags and wouldn't have nowhere to put them in any case. */ 
    665         case PGMVIRTHANDLERTYPE_HYPERVISOR: 
    666             return 0; 
    667     } 
    668  
    669659    unsigned    offPage = GCPtr & PAGE_OFFSET_MASK; 
    670660    unsigned    iPage = 0; 
  • trunk/src/VBox/VMM/VMMAll/PGMAllHandler.cpp

    r6913 r6927  
    10261026        *piPage = pCur - &(*ppVirt)->aPhysToVirt[0]; 
    10271027 
    1028         LogFlow(("PHYS2VIRT: found match for %VGp -> %VGv *piPage=%#x\n", 
    1029                  GCPhys, (*ppVirt)->GCPtr, *piPage)); 
     1028        LogFlow(("PHYS2VIRT: found match for %VGp -> %VGv *piPage=%#x\n", GCPhys, (*ppVirt)->GCPtr, *piPage)); 
    10301029        STAM_PROFILE_STOP(CTXSUFF(&pVM->pgm.s.StatVirtHandleSearchByPhys), a); 
    10311030        return VINF_SUCCESS; 
     
    10411040 * Deal with aliases in phys2virt. 
    10421041 * 
     1042 * As pointed out by the various todos, this currently only deals with 
     1043 * aliases where the two ranges match 100%. 
     1044 * 
    10431045 * @param   pVM             The VM handle. 
    10441046 * @param   pPhys2Virt      The node we failed insert. 
     
    10501052     */ 
    10511053    /** @todo Deal with partial overlapping. (Unlikly situation, so I'm too lazy to do anything about it now.) */ 
     1054    /** @todo check if the current head node covers the ground we do. This is highly unlikely 
     1055     * and I'm too lazy to implement this now as it will require sorting the list and stuff like that. */ 
    10521056    PPGMPHYS2VIRTHANDLER pHead = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTXSUFF(pTrees)->PhysToVirtHandlers, pPhys2Virt->Core.Key); 
    1053     if (!pHead) 
    1054     { 
    1055         /** @todo do something clever here... */ 
    1056 #ifdef IN_RING3 
    1057         LogRel(("pgmHandlerVirtualInsertAliased: %VGp-%VGp\n", pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast)); 
    1058 #endif 
    1059         pPhys2Virt->offNextAlias = 0; 
    1060         return; 
    1061     } 
    10621057#ifdef VBOX_STRICT_PGM_HANDLER_VIRTUAL 
    10631058    AssertReleaseMsg(pHead != pPhys2Virt, ("%VGp-%VGp offVirtHandler=%#RX32\n", 
    10641059                                           pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast, pPhys2Virt->offVirtHandler)); 
    10651060#endif 
    1066  
    1067     /** @todo check if the current head node covers the ground we do. This is highly unlikely 
    1068      * and I'm too lazy to implement this now as it will require sorting the list and stuff like that. */ 
     1061    if (RT_UNLIKELY(!pHead || pHead->Core.KeyLast != pPhys2Virt->Core.KeyLast)) 
     1062    { 
     1063        /** @todo do something clever here... */ 
     1064        LogRel(("pgmHandlerVirtualInsertAliased: %VGp-%VGp\n", pPhys2Virt->Core.Key, pPhys2Virt->Core.KeyLast)); 
     1065        pPhys2Virt->offNextAlias = 0; 
     1066        return; 
     1067    } 
    10691068 
    10701069    /* 
     
    10881087 * Resets one virtual handler range. 
    10891088 * 
     1089 * This is called by HandlerVirtualUpdate when it has detected some kind of 
     1090 * problem and have started clearing the virtual handler page states (or 
     1091 * when there have been registration/deregistrations). For this reason this 
     1092 * function will only update the page status if it's lower than desired. 
     1093 * 
    10901094 * @returns 0 
    10911095 * @param   pNode   Pointer to a PGMVIRTHANDLER. 
     
    10981102 
    10991103    /* 
    1100      * Calc flags. 
    1101      */ 
    1102     Assert(pCur->enmType != PGMVIRTHANDLERTYPE_HYPERVISOR); 
    1103     unsigned        fFlags; 
    1104     switch (pCur->enmType) 
    1105     { 
    1106         case PGMVIRTHANDLERTYPE_WRITE:  fFlags = MM_RAM_FLAGS_VIRTUAL_HANDLER | MM_RAM_FLAGS_VIRTUAL_WRITE; break; 
    1107         case PGMVIRTHANDLERTYPE_ALL:    fFlags = MM_RAM_FLAGS_VIRTUAL_HANDLER | MM_RAM_FLAGS_VIRTUAL_ALL; break; 
    1108         /* hypervisor handlers need no flags and wouldn't have nowhere to put them in any case. */ 
    1109         case PGMVIRTHANDLERTYPE_HYPERVISOR: 
    1110             return 0; 
    1111         default: 
    1112             AssertMsgFailed(("Invalid type %d\n", pCur->enmType)); 
    1113             return 0; 
    1114     } 
    1115  
    1116     /* 
    1117      * Iterate the pages and apply the flags. 
    1118      */ 
     1104     * Iterate the pages and apply the new state. 
     1105     */ 
     1106    unsigned        uState   = pgmHandlerVirtualCalcState(pCur); 
    11191107    PPGMRAMRANGE    pRamHint = NULL; 
    11201108    RTGCUINTPTR     offPage  = ((RTGCUINTPTR)pCur->GCPtr & PAGE_OFFSET_MASK); 
     
    11251113        if (pPhys2Virt->Core.Key != NIL_RTGCPHYS) 
    11261114        { 
    1127             /* Update the flags. */ 
    1128             int rc = pgmRamFlagsSetByGCPhysWithHint(&pVM->pgm.s, pPhys2Virt->Core.Key, fFlags, &pRamHint); 
    1129             AssertRC(rc); 
    1130  
    1131             /* Need to insert the page in the Phys2Virt lookup tree? */ 
     1115            /* 
     1116             * Update the page state wrt virtual handlers. 
     1117             */ 
     1118            PPGMPAGE pPage; 
     1119            int rc = pgmPhysGetPageWithHintEx(&pVM->pgm.s, pPhys2Virt->Core.Key, &pPage, &pRamHint); 
     1120            if (    RT_SUCCESS(rc) 
     1121                &&  PGM_PAGE_GET_HNDL_VIRT_STATE(pPage) < uState) 
     1122                PGM_PAGE_SET_HNDL_VIRT_STATE(pPage, uState); 
     1123            else 
     1124                AssertRC(rc); 
     1125 
     1126            /* 
     1127             * Need to insert the page in the Phys2Virt lookup tree? 
     1128             */ 
    11321129            if (pPhys2Virt->Core.KeyLast == NIL_RTGCPHYS) 
    11331130            { 
     
    12001197typedef struct PGMAHAFIS 
    12011198{ 
     1199    /** The current physical address. */ 
     1200    RTGCPHYS    GCPhys; 
     1201    /** The state we've calculated. */ 
     1202    unsigned    uVirtStateFound; 
     1203    /** The state we're matching up to. */ 
     1204    unsigned    uVirtState; 
     1205    /** Number of errors. */ 
     1206    unsigned    cErrors; 
    12021207    /** The VM handle. */ 
    12031208    PVM         pVM; 
    1204     /** Number of errors. */ 
    1205     unsigned    cErrors; 
    1206     /** The flags we've found. */ 
    1207     unsigned    fFlagsFound; 
    1208     /** The flags we're matching up to. 
    1209      * This is also on the stack as a const, thus only valid during enumeration. */ 
    1210     unsigned    fFlags; 
    1211     /** The current physical address. */ 
    1212     RTGCPHYS    GCPhys; 
    12131209} PGMAHAFIS, *PPGMAHAFIS; 
    12141210 
     1211 
     1212#if 0 /* unused */ 
    12151213/** 
    12161214 * Verify virtual handler by matching physical address. 
     
    12201218 * @param   pvUser  Pointer to user parameter. 
    12211219 */ 
    1222 static DECLCALLBACK(int) pgmVirtHandlerVerifyOneByPhysAddr(PAVLROGCPTRNODECORE pNode, void *pvUser) 
     1220static DECLCALLBACK(int) pgmHandlerVirtualVerifyOneByPhysAddr(PAVLROGCPTRNODECORE pNode, void *pvUser) 
    12231221{ 
    12241222    PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)pNode; 
     
    12291227        if ((pCur->aPhysToVirt[iPage].Core.Key & X86_PTE_PAE_PG_MASK) == pState->GCPhys) 
    12301228        { 
    1231             switch (pCur->enmType) 
     1229            unsigned uState = pgmHandlerVirtualCalcState(pCur); 
     1230            if (pState->uVirtState < uState) 
    12321231            { 
    1233                 case PGMVIRTHANDLERTYPE_WRITE:      pState->fFlagsFound |= MM_RAM_FLAGS_VIRTUAL_HANDLER | MM_RAM_FLAGS_VIRTUAL_WRITE; break; 
    1234                 case PGMVIRTHANDLERTYPE_ALL:        pState->fFlagsFound |= MM_RAM_FLAGS_VIRTUAL_HANDLER | MM_RAM_FLAGS_VIRTUAL_ALL; break; 
    1235                 /* hypervisor handlers need no flags and wouldn't have nowhere to put them in any case. */ 
    1236                 case PGMVIRTHANDLERTYPE_HYPERVISOR: 
    1237                     return 0; 
     1232                error 
    12381233            } 
    1239             if (    (pState->fFlags & (MM_RAM_FLAGS_VIRTUAL_HANDLER  | MM_RAM_FLAGS_VIRTUAL_WRITE  | MM_RAM_FLAGS_VIRTUAL_ALL)) 
    1240                 ==  pState->fFlagsFound
    1241                 break; 
     1234 
     1235            if (pState->uVirtState == uState
     1236                break; //?? 
    12421237        } 
    12431238    } 
    12441239    return 0; 
    12451240} 
    1246  
    1247  
    1248 /** 
    1249  * Verify a virtual handler. 
     1241#endif /* unused */ 
     1242 
     1243 
     1244/** 
     1245 * Verify a virtual handler (enumeration callback). 
     1246 * 
     1247 * Called by PGMAssertHandlerAndFlagsInSync to check the sanity of all 
     1248 * the virtual handlers, esp. that the physical addresses matches up. 
    12501249 * 
    12511250 * @returns 0 
    12521251 * @param   pNode   Pointer to a PGMVIRTHANDLER. 
    1253  * @param   pvUser  Pointer to user parameter
    1254  */ 
    1255 static DECLCALLBACK(int) pgmVirtHandlerVerifyOne(PAVLROGCPTRNODECORE pNode, void *pvUser) 
     1252 * @param   pvUser  Pointer to a PPGMAHAFIS structure
     1253 */ 
     1254static DECLCALLBACK(int) pgmHandlerVirtualVerifyOne(PAVLROGCPTRNODECORE pNode, void *pvUser) 
    12561255{ 
    12571256    PPGMVIRTHANDLER pVirt   = (PPGMVIRTHANDLER)pNode; 
    1258     PPGMAHAFIS      pState = (PPGMAHAFIS)pvUser; 
     1257    PPGMAHAFIS      pState = (PPGMAHAFIS)pvUser; 
    12591258    PVM             pVM     = pState->pVM; 
    12601259 
    1261     if (    pVirt->aPhysToVirt[0].Core.Key != NIL_RTGCPHYS 
    1262         &&  (pVirt->aPhysToVirt[0].Core.Key & PAGE_OFFSET_MASK) != ((RTGCUINTPTR)pVirt->GCPtr & PAGE_OFFSET_MASK)) 
    1263     { 
    1264         AssertMsgFailed(("virt handler phys out has incorrect key! %VGp %VGv %s\n", 
     1260    /* 
     1261     * Validate the type and calc state. 
     1262     */ 
     1263    switch (pVirt->enmType) 
     1264    { 
     1265        case PGMVIRTHANDLERTYPE_WRITE: 
     1266        case PGMVIRTHANDLERTYPE_ALL: 
     1267            break; 
     1268        default: 
     1269            AssertMsgFailed(("unknown/wrong enmType=%d\n", pVirt->enmType)); 
     1270            pState->cErrors++; 
     1271            return 0; 
     1272    } 
     1273    const unsigned uState = pgmHandlerVirtualCalcState(pVirt); 
     1274 
     1275    /* 
     1276     * Check key alignment. 
     1277     */ 
     1278    if (    (pVirt->aPhysToVirt[0].Core.Key & PAGE_OFFSET_MASK) != ((RTGCUINTPTR)pVirt->GCPtr & PAGE_OFFSET_MASK) 
     1279        &&  pVirt->aPhysToVirt[0].Core.Key != NIL_RTGCPHYS) 
     1280    { 
     1281        AssertMsgFailed(("virt handler phys has incorrect key! %VGp %VGv %s\n", 
    12651282                         pVirt->aPhysToVirt[0].Core.Key, pVirt->GCPtr, HCSTRING(pVirt->pszDesc))); 
    12661283        pState->cErrors++; 
    12671284    } 
    12681285 
    1269     /* 
    1270      * Calc flags. 
    1271      */ 
    1272     unsigned    fFlags; 
    1273     switch (pVirt->enmType) 
    1274     { 
    1275         case PGMVIRTHANDLERTYPE_WRITE:      fFlags = MM_RAM_FLAGS_VIRTUAL_HANDLER | MM_RAM_FLAGS_VIRTUAL_WRITE; break; 
    1276         case PGMVIRTHANDLERTYPE_ALL:        fFlags = MM_RAM_FLAGS_VIRTUAL_HANDLER | MM_RAM_FLAGS_VIRTUAL_ALL; break; 
    1277         /* hypervisor handlers need no flags and wouldn't have nowhere to put them in any case. */ 
    1278         case PGMVIRTHANDLERTYPE_HYPERVISOR: 
    1279             return 0; 
    1280         default: 
    1281             AssertMsgFailed(("unknown enmType=%d\n", pVirt->enmType)); 
    1282             return 0; 
    1283     } 
    1284  
    1285     /* 
    1286      * Check pages against flags. 
     1286    if (    (pVirt->aPhysToVirt[pVirt->cPages - 1].Core.KeyLast & PAGE_OFFSET_MASK) != ((RTGCUINTPTR)pVirt->GCPtrLast & PAGE_OFFSET_MASK) 
     1287        &&  pVirt->aPhysToVirt[pVirt->cPages - 1].Core.Key != NIL_RTGCPHYS) 
     1288    { 
     1289        AssertMsgFailed(("virt handler phys has incorrect key! %VGp %VGv %s\n", 
     1290                         pVirt->aPhysToVirt[pVirt->cPages - 1].Core.KeyLast, pVirt->GCPtrLast, HCSTRING(pVirt->pszDesc))); 
     1291        pState->cErrors++; 
     1292    } 
     1293 
     1294    /* 
     1295     * Check pages for sanity and state. 
    12871296     */ 
    12881297    RTGCUINTPTR   GCPtr = (RTGCUINTPTR)pVirt->GCPtr; 
     
    13221331        } 
    13231332 
    1324         if ((pPage->HCPhys & fFlags) != fFlags) /** @todo PAGE FLAGS */ 
    1325         { 
    1326             AssertMsgFailed(("virt handler flags mismatch. HCPhys=%VHp fFlags=%#x GCPhysGst=%VGp iPage=%#x %VGv %s\n", 
    1327                              pPage->HCPhys, fFlags, GCPhysGst, iPage, GCPtr, HCSTRING(pVirt->pszDesc))); 
     1333        if (PGM_PAGE_GET_HNDL_VIRT_STATE(pPage) < uState) 
     1334        { 
     1335            AssertMsgFailed(("virt handler state mismatch. HCPhys=%VHp GCPhysGst=%VGp iPage=%#x %VGv state=%d expected>=%d %s\n", 
     1336                             pPage->HCPhys, GCPhysGst, iPage, GCPtr, PGM_PAGE_GET_HNDL_VIRT_STATE(pPage), uState, HCSTRING(pVirt->pszDesc))); 
    13281337            pState->cErrors++; 
    13291338            continue; 
     
    13461355    PPGM        pPGM = &pVM->pgm.s; 
    13471356    PGMAHAFIS   State; 
     1357    State.GCPhys = 0; 
     1358    State.uVirtState = 0; 
     1359    State.uVirtStateFound = 0; 
    13481360    State.cErrors = 0; 
    1349     State.pVM     = pVM; 
     1361    State.pVM = pVM; 
    13501362 
    13511363    /* 
     
    13611373            { 
    13621374                State.GCPhys = pRam->GCPhys + (iPage << PAGE_SHIFT); 
    1363                 State.fFlagsFound = 0; /* build flags and compare. */ 
    13641375 
    13651376                /* 
     
    14241435                } 
    14251436 
    1426                 /* virtual flags. */ 
     1437                /* 
     1438                 * Virtual handlers. 
     1439                 */ 
    14271440                if (PGM_PAGE_HAVE_ACTIVE_VIRTUAL_HANDLERS(pPage)) 
    14281441                { 
    1429                     State.fFlags = pPage->HCPhys & (MM_RAM_FLAGS_VIRTUAL_HANDLER  | MM_RAM_FLAGS_VIRTUAL_WRITE  | MM_RAM_FLAGS_VIRTUAL_ALL); /// @todo PAGE FLAGS 
    1430                     RTAvlroGCPtrDoWithAll(CTXSUFF(&pVM->pgm.s.pTrees)->VirtHandlers, true, pgmVirtHandlerVerifyOneByPhysAddr, &State); 
    1431                     if (State.fFlags !=  State.fFlagsFound) 
     1442                    State.uVirtState = PGM_PAGE_GET_HNDL_VIRT_STATE(pPage); 
     1443#if 1 
     1444                    /* locate all the matching physical ranges. */ 
     1445                    State.uVirtStateFound = PGM_PAGE_HNDL_VIRT_STATE_NONE; 
     1446                    RTGCPHYS GCPhysKey = State.GCPhys; 
     1447                    for (;;) 
    14321448                    { 
    1433                         AssertMsgFailed(("ram range vs virt handler flags mismatch. GCPhys=%RGp fFlags=%#x fFlagsFound=%#x\n", 
    1434                                          State.GCPhys, State.fFlags, State.fFlagsFound)); 
     1449                        PPGMPHYS2VIRTHANDLER pPhys2Virt = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGetBestFit(&CTXSUFF(pVM->pgm.s.pTrees)->PhysToVirtHandlers, 
     1450                                                                                                        GCPhysKey, true /* above-or-equal */); 
     1451                        if (    !pPhys2Virt 
     1452                            ||  (pPhys2Virt->Core.Key & X86_PTE_PAE_PG_MASK) != State.GCPhys) 
     1453                            break; 
     1454 
     1455                        /* the head */ 
     1456                        GCPhysKey = pPhys2Virt->Core.KeyLast; 
     1457                        PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)((uintptr_t)pPhys2Virt + pPhys2Virt->offVirtHandler); 
     1458                        unsigned uState = pgmHandlerVirtualCalcState(pCur); 
     1459                        State.uVirtStateFound = RT_MAX(State.uVirtStateFound, uState); 
     1460 
     1461                        /* any aliases */ 
     1462                        while (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK) 
     1463                        { 
     1464                            pPhys2Virt = (PPGMPHYS2VIRTHANDLER)((uintptr_t)pPhys2Virt + (pPhys2Virt->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK)); 
     1465                            pCur = (PPGMVIRTHANDLER)((uintptr_t)pPhys2Virt + pPhys2Virt->offVirtHandler); 
     1466                            uState = pgmHandlerVirtualCalcState(pCur); 
     1467                            State.uVirtStateFound = RT_MAX(State.uVirtStateFound, uState); 
     1468                        } 
     1469 
     1470                        /* done? */ 
     1471                        if ((GCPhysKey & X86_PTE_PAE_PG_MASK) != State.GCPhys) 
     1472                            break; 
     1473                    } 
     1474#else 
     1475                    /* very slow */ 
     1476                    RTAvlroGCPtrDoWithAll(CTXSUFF(&pVM->pgm.s.pTrees)->VirtHandlers, true, pgmHandlerVirtualVerifyOneByPhysAddr, &State); 
     1477#endif 
     1478                    if (State.uVirtState != State.uVirtStateFound) 
     1479                    { 
     1480                        AssertMsgFailed(("ram range vs virt handler flags mismatch. GCPhys=%RGp uVirtState=%#x uVirtStateFound=%#x\n", 
     1481                                         State.GCPhys, State.uVirtState, State.uVirtStateFound)); 
    14351482                        State.cErrors++; 
    14361483                    } 
    1437  
    14381484                } 
    14391485            } 
     
    14421488 
    14431489    /* 
    1444      * Check that the physical addresses of the virtual handlers matches up. 
    1445      */ 
    1446     RTAvlroGCPtrDoWithAll(CTXSUFF(&pVM->pgm.s.pTrees)->VirtHandlers, true, pgmVirtHandlerVerifyOne, &State); 
     1490     * Check that the physical addresses of the virtual handlers matches up 
     1491     * and that they are otherwise sane. 
     1492     */ 
     1493    RTAvlroGCPtrDoWithAll(CTXSUFF(&pVM->pgm.s.pTrees)->VirtHandlers, true, pgmHandlerVirtualVerifyOne, &State); 
    14471494 
    14481495    /* 
  • trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp

    r6902 r6927  
    11791179                        { 
    11801180                            memcpy(pvBuf, pvSrc, cbRead); 
    1181                             break
     1181                            goto end
    11821182                        } 
    11831183                        memcpy(pvBuf, pvSrc, cb); 
    11841184                    } 
    11851185                    else if (cb >= cbRead) 
    1186                         break; 
     1186                        goto end; 
     1187                } 
     1188                /* 
     1189                 * Virtual handlers. 
     1190                 */ 
     1191                else if (   RT_UNLIKELY(PGM_PAGE_GET_HNDL_VIRT_STATE(pPage) >= PGM_PAGE_HNDL_VIRT_STATE_ALL) 
     1192                         && !(pPage->HCPhys & MM_RAM_FLAGS_MMIO)) /// @todo PAGE FLAGS 
     1193                { 
     1194                    int rc = VINF_PGM_HANDLER_DO_DEFAULT; 
     1195                    cb = PAGE_SIZE - (off & PAGE_OFFSET_MASK); 
     1196#ifdef IN_RING3 /** @todo deal with this in GC and R0! */ 
     1197                    /* Search the whole tree for matching physical addresses (rather expensive!) */ 
     1198                    PPGMVIRTHANDLER pNode; 
     1199                    unsigned iPage; 
     1200                    int rc2 = pgmHandlerVirtualFindByPhysAddr(pVM, GCPhys, &pNode, &iPage); 
     1201                    if (VBOX_SUCCESS(rc2) && pNode->pfnHandlerHC) 
     1202                    { 
     1203                        size_t cbRange = pNode->Core.KeyLast - GCPhys + 1; 
     1204                        if (cbRange < cb) 
     1205                            cb = cbRange; 
     1206                        if (cb > cbRead) 
     1207                            cb = cbRead; 
     1208                        RTGCUINTPTR GCPtr = ((RTGCUINTPTR)pNode->GCPtr & PAGE_BASE_GC_MASK) 
     1209                                          + (iPage << PAGE_SHIFT) + (off & PAGE_OFFSET_MASK); 
     1210 
     1211                        void *pvSrc = PGMRAMRANGE_GETHCPTR(pRam, off) 
     1212 
     1213                        /** @note Dangerous assumption that HC handlers don't do anything that really requires an EMT lock! */ 
     1214                        rc = pNode->pfnHandlerHC(pVM, (RTGCPTR)GCPtr, pvSrc, pvBuf, cb, PGMACCESSTYPE_READ, 0); 
     1215                    } 
     1216#endif /* IN_RING3 */ 
     1217                    if (rc == VINF_PGM_HANDLER_DO_DEFAULT) 
     1218                    { 
     1219#ifdef IN_GC 
     1220                        void *pvSrc = NULL; 
     1221                        PGMGCDynMapHCPage(pVM, PGM_PAGE_GET_HCPHYS(pPage), &pvSrc); 
     1222                        pvSrc = (char *)pvSrc + (off & PAGE_OFFSET_MASK); 
     1223#else 
     1224                        void *pvSrc = PGMRAMRANGE_GETHCPTR(pRam, off) 
     1225#endif 
     1226                        if (cb >= cbRead) 
     1227                        { 
     1228                            memcpy(pvBuf, pvSrc, cbRead); 
     1229                            goto end; 
     1230                        } 
     1231                        memcpy(pvBuf, pvSrc, cb); 
     1232                    } 
     1233                    else if (cb >= cbRead) 
     1234                        goto end; 
    11871235                } 
    11881236                else 
    11891237                { 
    1190                     switch (pPage->HCPhys & (MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_VIRTUAL_ALL | MM_RAM_FLAGS_ROM)) /** @todo PAGE FLAGS */ 
     1238                    switch (pPage->HCPhys & (MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_ROM)) /** @todo PAGE FLAGS */ 
    11911239                    { 
    11921240                        /* 
     
    11981246                        //case MM_RAM_FLAGS_ROM | MM_RAM_FLAGS_MMIO2: /* = shadow */ - //MMIO2 isn't in the mask. 
    11991247                        case MM_RAM_FLAGS_MMIO2: // MMIO2 isn't in the mask. 
    1200                         case MM_RAM_FLAGS_VIRTUAL_WRITE: 
    12011248                        { 
    12021249#ifdef IN_GC 
     
    12341281                            break; 
    12351282 
    1236                         case MM_RAM_FLAGS_VIRTUAL_ALL: 
    1237                         { 
    1238                             int rc = VINF_PGM_HANDLER_DO_DEFAULT; 
    1239                             cb = PAGE_SIZE - (off & PAGE_OFFSET_MASK); 
    1240 #ifdef IN_RING3 /** @todo deal with this in GC and R0! */ 
    1241                             /* Search the whole tree for matching physical addresses (rather expensive!) */ 
    1242                             PPGMVIRTHANDLER pNode; 
    1243                             unsigned iPage; 
    1244                             int rc2 = pgmHandlerVirtualFindByPhysAddr(pVM, GCPhys, &pNode, &iPage); 
    1245                             if (VBOX_SUCCESS(rc2) && pNode->pfnHandlerHC) 
    1246                             { 
    1247                                 size_t cbRange = pNode->Core.KeyLast - GCPhys + 1; 
    1248                                 if (cbRange < cb) 
    1249                                     cb = cbRange; 
    1250                                 if (cb > cbRead) 
    1251                                     cb = cbRead; 
    1252                                 RTGCUINTPTR GCPtr = ((RTGCUINTPTR)pNode->GCPtr & PAGE_BASE_GC_MASK) 
    1253                                                   + (iPage << PAGE_SHIFT) + (off & PAGE_OFFSET_MASK); 
    1254  
    1255                                 void *pvSrc = PGMRAMRANGE_GETHCPTR(pRam, off) 
    1256  
    1257                                 /** @note Dangerous assumption that HC handlers don't do anything that really requires an EMT lock! */ 
    1258                                 rc = pNode->pfnHandlerHC(pVM, (RTGCPTR)GCPtr, pvSrc, pvBuf, cb, PGMACCESSTYPE_READ, 0); 
    1259                             } 
    1260 #endif /* IN_RING3 */ 
    1261                             if (rc == VINF_PGM_HANDLER_DO_DEFAULT) 
    1262                             { 
    1263 #ifdef IN_GC 
    1264                                 void *pvSrc = NULL; 
    1265                                 PGMGCDynMapHCPage(pVM, PGM_PAGE_GET_HCPHYS(pPage), &pvSrc); 
    1266                                 pvSrc = (char *)pvSrc + (off & PAGE_OFFSET_MASK); 
    1267 #else 
    1268                                 void *pvSrc = PGMRAMRANGE_GETHCPTR(pRam, off) 
    1269 #endif 
    1270                                 if (cb >= cbRead) 
    1271                                 { 
    1272                                     memcpy(pvBuf, pvSrc, cbRead); 
    1273                                     goto end; 
    1274                                 } 
    1275                                 memcpy(pvBuf, pvSrc, cb); 
    1276                             } 
    1277                             else if (cb >= cbRead) 
    1278                                 goto end; 
    1279                             break; 
    1280                         } 
    1281  
    12821283                        /* 
    12831284                         * The rest needs to be taken more carefully. 
     
    12931294                            AssertReleaseMsgFailed(("Unknown read at %VGp size %d implement the complex physical reading case %x\n", 
    12941295                                                    GCPhys, cbRead, 
    1295                                                     pPage->HCPhys & (MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_VIRTUAL_ALL | MM_RAM_FLAGS_ROM))); /** @todo PAGE FLAGS */ 
     1296                                                    pPage->HCPhys & (MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_ROM))); /** @todo PAGE FLAGS */ 
    12961297                            cb = PAGE_SIZE - (off & PAGE_OFFSET_MASK); 
    12971298                            break; 
     
    14101411                /* temporary hack, will reogranize is later. */ 
    14111412                /* 
     1413                 * Virtual handlers 
     1414                 */ 
     1415                if (    PGM_PAGE_HAVE_ACTIVE_VIRTUAL_HANDLERS(pPage) 
     1416                    && !(pPage->HCPhys & MM_RAM_FLAGS_MMIO)) /// @todo PAGE FLAGS 
     1417                { 
     1418                    if (PGM_PAGE_HAVE_ACTIVE_PHYSICAL_HANDLERS(pPage)) 
     1419                    { 
     1420                        /* 
     1421                         * Physical write handler + virtual write handler. 
     1422                         * Consider this a quick workaround for the CSAM + shadow caching problem. 
     1423                         * 
     1424                         * We hand it to the shadow caching first since it requires the unchanged 
     1425                         * data. CSAM will have to put up with it already being changed. 
     1426                         */ 
     1427                        int rc = VINF_PGM_HANDLER_DO_DEFAULT; 
     1428                        cb = PAGE_SIZE - (off & PAGE_OFFSET_MASK); 
     1429#ifdef IN_RING3 /** @todo deal with this in GC and R0! */ 
     1430                        /* 1. The physical handler */ 
     1431                        PPGMPHYSHANDLER pPhysNode = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.pTreesHC->PhysHandlers, GCPhys); 
     1432                        if (pPhysNode && pPhysNode->pfnHandlerR3) 
     1433                        { 
     1434                            size_t cbRange = pPhysNode->Core.KeyLast - GCPhys + 1; 
     1435                            if (cbRange < cb) 
     1436                                cb = cbRange; 
     1437                            if (cb > cbWrite) 
     1438                                cb = cbWrite; 
     1439 
     1440                            void *pvDst = PGMRAMRANGE_GETHCPTR(pRam, off) 
     1441 
     1442                            /** @note Dangerous assumption that HC handlers don't do anything that really requires an EMT lock! */ 
     1443                            rc = pPhysNode->pfnHandlerR3(pVM, GCPhys, pvDst, (void *)pvBuf, cb, PGMACCESSTYPE_WRITE, pPhysNode->pvUserR3); 
     1444                        } 
     1445 
     1446                        /* 2. The virtual handler (will see incorrect data) */ 
     1447                        PPGMVIRTHANDLER pVirtNode; 
     1448                        unsigned iPage; 
     1449                        int rc2 = pgmHandlerVirtualFindByPhysAddr(pVM, GCPhys, &pVirtNode, &iPage); 
     1450                        if (VBOX_SUCCESS(rc2) && pVirtNode->pfnHandlerHC) 
     1451                        { 
     1452                            size_t cbRange = pVirtNode->Core.KeyLast - GCPhys + 1; 
     1453                            if (cbRange < cb) 
     1454                                cb = cbRange; 
     1455                            if (cb > cbWrite) 
     1456                                cb = cbWrite; 
     1457                            RTGCUINTPTR GCPtr = ((RTGCUINTPTR)pVirtNode->GCPtr & PAGE_BASE_GC_MASK) 
     1458                                              + (iPage << PAGE_SHIFT) + (off & PAGE_OFFSET_MASK); 
     1459 
     1460                            void *pvDst = PGMRAMRANGE_GETHCPTR(pRam, off) 
     1461 
     1462                            /** @note Dangerous assumption that HC handlers don't do anything that really requires an EMT lock! */ 
     1463                            rc2 = pVirtNode->pfnHand