VirtualBox

Changeset 6927 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Feb 12, 2008 8:44:35 PM (17 years 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.

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

Legend:

Unmodified
Added
Removed
  • 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->pfnHandlerHC(pVM, (RTGCPTR)GCPtr, pvDst, (void *)pvBuf, cb, PGMACCESSTYPE_WRITE, 0);
     1464                            if (    (   rc2 != VINF_PGM_HANDLER_DO_DEFAULT
     1465                                     && rc == VINF_PGM_HANDLER_DO_DEFAULT)
     1466                                ||  (   VBOX_FAILURE(rc2)
     1467                                     && VBOX_SUCCESS(rc)))
     1468                                rc = rc2;
     1469                        }
     1470#endif /* IN_RING3 */
     1471                        if (rc == VINF_PGM_HANDLER_DO_DEFAULT)
     1472                        {
     1473#ifdef IN_GC
     1474                            void *pvDst = NULL;
     1475                            PGMGCDynMapHCPage(pVM, PGM_PAGE_GET_HCPHYS(pPage), &pvDst);
     1476                            pvDst = (char *)pvDst + (off & PAGE_OFFSET_MASK);
     1477#else
     1478                            void *pvDst = PGMRAMRANGE_GETHCPTR(pRam, off)
     1479#endif
     1480                            if (cb >= cbWrite)
     1481                            {
     1482                                memcpy(pvDst, pvBuf, cbWrite);
     1483                                goto end;
     1484                            }
     1485                            memcpy(pvDst, pvBuf, cb);
     1486                        }
     1487                        else if (cb >= cbWrite)
     1488                            goto end;
     1489                    }
     1490                    else
     1491                    {
     1492                        int rc = VINF_PGM_HANDLER_DO_DEFAULT;
     1493                        cb = PAGE_SIZE - (off & PAGE_OFFSET_MASK);
     1494#ifdef IN_RING3
     1495/** @todo deal with this in GC and R0! */
     1496                        /* Search the whole tree for matching physical addresses (rather expensive!) */
     1497                        PPGMVIRTHANDLER pNode;
     1498                        unsigned iPage;
     1499                        int rc2 = pgmHandlerVirtualFindByPhysAddr(pVM, GCPhys, &pNode, &iPage);
     1500                        if (VBOX_SUCCESS(rc2) && pNode->pfnHandlerHC)
     1501                        {
     1502                            size_t cbRange = pNode->Core.KeyLast - GCPhys + 1;
     1503                            if (cbRange < cb)
     1504                                cb = cbRange;
     1505                            if (cb > cbWrite)
     1506                                cb = cbWrite;
     1507                            RTGCUINTPTR GCPtr = ((RTGCUINTPTR)pNode->GCPtr & PAGE_BASE_GC_MASK)
     1508                                              + (iPage << PAGE_SHIFT) + (off & PAGE_OFFSET_MASK);
     1509
     1510                            void *pvDst = PGMRAMRANGE_GETHCPTR(pRam, off)
     1511
     1512                            /** @tode Dangerous assumption that HC handlers don't do anything that really requires an EMT lock! */
     1513                            rc = pNode->pfnHandlerHC(pVM, (RTGCPTR)GCPtr, pvDst, (void *)pvBuf, cb, PGMACCESSTYPE_WRITE, 0);
     1514                        }
     1515#endif /* IN_RING3 */
     1516                        if (rc == VINF_PGM_HANDLER_DO_DEFAULT)
     1517                        {
     1518#ifdef IN_GC
     1519                            void *pvDst = NULL;
     1520                            PGMGCDynMapHCPage(pVM, PGM_PAGE_GET_HCPHYS(pPage), &pvDst);
     1521                            pvDst = (char *)pvDst + (off & PAGE_OFFSET_MASK);
     1522#else
     1523                            void *pvDst = PGMRAMRANGE_GETHCPTR(pRam, off)
     1524#endif
     1525                            if (cb >= cbWrite)
     1526                            {
     1527                                memcpy(pvDst, pvBuf, cbWrite);
     1528                                goto end;
     1529                            }
     1530                            memcpy(pvDst, pvBuf, cb);
     1531                        }
     1532                        else if (cb >= cbWrite)
     1533                            goto end;
     1534                    }
     1535                }
     1536                /*
    14121537                 * Physical handler.
    14131538                 */
    1414                 if (   RT_UNLIKELY(PGM_PAGE_GET_HNDL_PHYS_STATE(pPage) >= PGM_PAGE_HNDL_PHYS_STATE_ALL)
    1415                     && !(pPage->HCPhys & MM_RAM_FLAGS_MMIO)) /// @todo PAGE FLAGS
     1539                else if (   RT_UNLIKELY(PGM_PAGE_GET_HNDL_PHYS_STATE(pPage) >= PGM_PAGE_HNDL_PHYS_STATE_WRITE)
     1540                         && !(pPage->HCPhys & MM_RAM_FLAGS_MMIO)) /// @todo PAGE FLAGS
    14161541                {
    14171542                    int rc = VINF_PGM_HANDLER_DO_DEFAULT;
     
    14301555                        void *pvDst = PGMRAMRANGE_GETHCPTR(pRam, off)
    14311556
    1432                         /** @note Dangerous assumption that HC handlers don't do anything that really requires an EMT lock! */
     1557                        /** @todo Dangerous assumption that HC handlers don't do anything that really requires an EMT lock! */
    14331558                        rc = pNode->pfnHandlerR3(pVM, GCPhys, pvDst, (void *)pvBuf, cb, PGMACCESSTYPE_WRITE, pNode->pvUserR3);
    14341559                    }
     
    14561581                {
    14571582                    /** @todo r=bird: missing MM_RAM_FLAGS_ROM here, we shall not allow anyone to overwrite the ROM! */
    1458                     switch (pPage->HCPhys & (MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_MMIO2 | MM_RAM_FLAGS_VIRTUAL_ALL | MM_RAM_FLAGS_VIRTUAL_WRITE)) /** @todo PAGE FLAGS */
     1583                    switch (pPage->HCPhys & (MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_MMIO2)) /** @todo PAGE FLAGS */
    14591584                    {
    14601585                        /*
     
    14961621                            break;
    14971622
    1498                         case MM_RAM_FLAGS_VIRTUAL_WRITE:
    1499                             if (PGM_PAGE_HAVE_ACTIVE_PHYSICAL_HANDLERS(pPage)) /* temporary mess */
    1500                             {
    1501                                 /*
    1502                                  * Physical write handler + virtual write handler.
    1503                                  * Consider this a quick workaround for the CSAM + shadow caching problem.
    1504                                  *
    1505                                  * We hand it to the shadow caching first since it requires the unchanged
    1506                                  * data. CSAM will have to put up with it already being changed.
    1507                                  */
    1508                                 int rc = VINF_PGM_HANDLER_DO_DEFAULT;
    1509                                 cb = PAGE_SIZE - (off & PAGE_OFFSET_MASK);
    1510 #ifdef IN_RING3 /** @todo deal with this in GC and R0! */
    1511                                 /* 1. The physical handler */
    1512                                 PPGMPHYSHANDLER pPhysNode = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.pTreesHC->PhysHandlers, GCPhys);
    1513                                 if (pPhysNode && pPhysNode->pfnHandlerR3)
    1514                                 {
    1515                                     size_t cbRange = pPhysNode->Core.KeyLast - GCPhys + 1;
    1516                                     if (cbRange < cb)
    1517                                         cb = cbRange;
    1518                                     if (cb > cbWrite)
    1519                                         cb = cbWrite;
    1520 
    1521                                     void *pvDst = PGMRAMRANGE_GETHCPTR(pRam, off)
    1522 
    1523                                     /** @note Dangerous assumption that HC handlers don't do anything that really requires an EMT lock! */
    1524                                     rc = pPhysNode->pfnHandlerR3(pVM, GCPhys, pvDst, (void *)pvBuf, cb, PGMACCESSTYPE_WRITE, pPhysNode->pvUserR3);
    1525                                 }
    1526 
    1527                                 /* 2. The virtual handler (will see incorrect data) */
    1528                                 PPGMVIRTHANDLER pVirtNode;
    1529                                 unsigned iPage;
    1530                                 int rc2 = pgmHandlerVirtualFindByPhysAddr(pVM, GCPhys, &pVirtNode, &iPage);
    1531                                 if (VBOX_SUCCESS(rc2) && pVirtNode->pfnHandlerHC)
    1532                                 {
    1533                                     size_t cbRange = pVirtNode->Core.KeyLast - GCPhys + 1;
    1534                                     if (cbRange < cb)
    1535                                         cb = cbRange;
    1536                                     if (cb > cbWrite)
    1537                                         cb = cbWrite;
    1538                                     RTGCUINTPTR GCPtr = ((RTGCUINTPTR)pVirtNode->GCPtr & PAGE_BASE_GC_MASK)
    1539                                                       + (iPage << PAGE_SHIFT) + (off & PAGE_OFFSET_MASK);
    1540 
    1541                                     void *pvDst = PGMRAMRANGE_GETHCPTR(pRam, off)
    1542 
    1543                                     /** @note Dangerous assumption that HC handlers don't do anything that really requires an EMT lock! */
    1544                                     rc2 = pVirtNode->pfnHandlerHC(pVM, (RTGCPTR)GCPtr, pvDst, (void *)pvBuf, cb, PGMACCESSTYPE_WRITE, 0);
    1545                                     if (    (   rc2 != VINF_PGM_HANDLER_DO_DEFAULT
    1546                                              && rc == VINF_PGM_HANDLER_DO_DEFAULT)
    1547                                         ||  (   VBOX_FAILURE(rc2)
    1548                                              && VBOX_SUCCESS(rc)))
    1549                                         rc = rc2;
    1550                                 }
    1551 #endif /* IN_RING3 */
    1552                                 if (rc == VINF_PGM_HANDLER_DO_DEFAULT)
    1553                                 {
    1554 #ifdef IN_GC
    1555                                     void *pvDst = NULL;
    1556                                     PGMGCDynMapHCPage(pVM, PGM_PAGE_GET_HCPHYS(pPage), &pvDst);
    1557                                     pvDst = (char *)pvDst + (off & PAGE_OFFSET_MASK);
    1558 #else
    1559                                     void *pvDst = PGMRAMRANGE_GETHCPTR(pRam, off)
    1560 #endif
    1561                                     if (cb >= cbWrite)
    1562                                     {
    1563                                         memcpy(pvDst, pvBuf, cbWrite);
    1564                                         goto end;
    1565                                     }
    1566                                     memcpy(pvDst, pvBuf, cb);
    1567                                 }
    1568                                 else if (cb >= cbWrite)
    1569                                     goto end;
    1570                                 break;
    1571                             }
    1572                             /* fall thru */
    1573                         case MM_RAM_FLAGS_VIRTUAL_ALL:
    1574                         {
    1575                             int rc = VINF_PGM_HANDLER_DO_DEFAULT;
    1576                             cb = PAGE_SIZE - (off & PAGE_OFFSET_MASK);
    1577 #ifdef IN_RING3
    1578     /** @todo deal with this in GC and R0! */
    1579                             /* Search the whole tree for matching physical addresses (rather expensive!) */
    1580                             PPGMVIRTHANDLER pNode;
    1581                             unsigned iPage;
    1582                             int rc2 = pgmHandlerVirtualFindByPhysAddr(pVM, GCPhys, &pNode, &iPage);
    1583                             if (VBOX_SUCCESS(rc2) && pNode->pfnHandlerHC)
    1584                             {
    1585                                 size_t cbRange = pNode->Core.KeyLast - GCPhys + 1;
    1586                                 if (cbRange < cb)
    1587                                     cb = cbRange;
    1588                                 if (cb > cbWrite)
    1589                                     cb = cbWrite;
    1590                                 RTGCUINTPTR GCPtr = ((RTGCUINTPTR)pNode->GCPtr & PAGE_BASE_GC_MASK)
    1591                                                   + (iPage << PAGE_SHIFT) + (off & PAGE_OFFSET_MASK);
    1592 
    1593                                 void *pvDst = PGMRAMRANGE_GETHCPTR(pRam, off)
    1594 
    1595                                 /** @note Dangerous assumption that HC handlers don't do anything that really requires an EMT lock! */
    1596                                 rc = pNode->pfnHandlerHC(pVM, (RTGCPTR)GCPtr, pvDst, (void *)pvBuf, cb, PGMACCESSTYPE_WRITE, 0);
    1597                             }
    1598 #endif /* IN_RING3 */
    1599                             if (rc == VINF_PGM_HANDLER_DO_DEFAULT)
    1600                             {
    1601 #ifdef IN_GC
    1602                                 void *pvDst = NULL;
    1603                                 PGMGCDynMapHCPage(pVM, PGM_PAGE_GET_HCPHYS(pPage), &pvDst);
    1604                                 pvDst = (char *)pvDst + (off & PAGE_OFFSET_MASK);
    1605 #else
    1606                                 void *pvDst = PGMRAMRANGE_GETHCPTR(pRam, off)
    1607 #endif
    1608                                 if (cb >= cbWrite)
    1609                                 {
    1610                                     memcpy(pvDst, pvBuf, cbWrite);
    1611                                     goto end;
    1612                                 }
    1613                                 memcpy(pvDst, pvBuf, cb);
    1614                             }
    1615                             else if (cb >= cbWrite)
    1616                                 goto end;
    1617                             break;
    1618                         }
    16191623
    16201624                        /*
     
    16311635                            AssertReleaseMsgFailed(("Unknown write at %VGp size %d implement the complex physical writing case %x\n",
    16321636                                                    GCPhys, cbWrite,
    1633                                                     (pPage->HCPhys & (MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_MMIO2 | MM_RAM_FLAGS_VIRTUAL_ALL | MM_RAM_FLAGS_VIRTUAL_WRITE)))); /** @todo PAGE FLAGS */
     1637                                                    (pPage->HCPhys & (MM_RAM_FLAGS_RESERVED | MM_RAM_FLAGS_MMIO | MM_RAM_FLAGS_MMIO2)))); /** @todo PAGE FLAGS */
    16341638                            /* skip the write */
    16351639                            cb = cbWrite;
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