VirtualBox

Changeset 41766 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Jun 15, 2012 6:36:19 PM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
78583
Message:

VMM/EM: Try read cbMaxRead when disassembling.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/EMAll.cpp

    r41760 r41766  
    6666#endif
    6767
    68 /** Used to pass information during instruction disassembly. */
    69 typedef struct
    70 {
    71     PVM         pVM;
    72     PVMCPU      pVCpu;
    73     RTGCPTR     GCPtr;
    74     uint8_t     aOpcode[8];
    75 } EMDISSTATE, *PEMDISSTATE;
    7668
    7769/*******************************************************************************
     
    286278static DECLCALLBACK(int) emReadBytes(PDISCPUSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead)
    287279{
    288     PEMDISSTATE   pState = (PEMDISSTATE)pDis->pvUser;
    289 # ifndef IN_RING0
    290     PVM           pVM    = pState->pVM;
     280    PVMCPU      pVCpu    = (PVMCPU)pDis->pvUser;
     281#if defined(IN_RC) || defined(IN_RING3)
     282    PVM         pVM      = pVCpu->CTX_SUFF(pVM);
     283#endif
     284    RTUINTPTR   uSrcAddr = pDis->uInstrAddr + offInstr;
     285    int         rc;
     286
     287    /*
     288     * Figure how much we can or must read.
     289     */
     290    size_t      cbToRead = PAGE_SIZE - (uSrcAddr & PAGE_OFFSET_MASK);
     291    if (cbToRead > cbMaxRead)
     292        cbToRead = cbMaxRead;
     293    else if (cbToRead < cbMinRead)
     294        cbToRead = cbMinRead;
     295
     296#if defined(IN_RC) || defined(IN_RING3)
     297    /*
     298     * We might be called upon to interpret an instruction in a patch.
     299     */
     300    if (PATMIsPatchGCAddr(pVCpu->CTX_SUFF(pVM), uSrcAddr))
     301    {
     302# ifdef IN_RC
     303        memcpy(&pDis->abInstr[offInstr], (void *)(uintptr_t)uSrcAddr, cbToRead);
     304# else
     305        memcpy(&pDis->abInstr[offInstr], PATMR3GCPtrToHCPtr(pVCpu->CTX_SUFF(pVM), uSrcAddr), cbToRead);
    291306# endif
    292     PVMCPU        pVCpu  = pState->pVCpu;
    293     /** @todo Rewrite this to make full use of the abInstr buffer and drop our extra
    294      *        caching buffer.  Just playing safe at first... */
    295     uint8_t      *pbDst    = &pDis->abInstr[offInstr];
    296     RTUINTPTR     uSrcAddr = pDis->uInstrAddr + offInstr;
    297     size_t        cbToRead = cbMinRead;
    298 
    299 # ifdef IN_RING0
    300     int           rc;
    301 
    302     if (    pState->GCPtr
    303         &&  uSrcAddr + cbToRead <= pState->GCPtr + sizeof(pState->aOpcode))
    304     {
    305         unsigned offset = uSrcAddr - pState->GCPtr;
    306         Assert(uSrcAddr >= pState->GCPtr);
    307 
    308         for (unsigned i = 0; i < cbToRead; i++)
    309             pbDst[i] = pState->aOpcode[offset + i];
    310         pDis->cbCachedInstr = offInstr + cbToRead;
    311         return VINF_SUCCESS;
    312     }
    313 
    314     rc = PGMPhysSimpleReadGCPtr(pVCpu, pbDst, uSrcAddr, cbToRead);
    315     AssertMsgRC(rc, ("PGMPhysSimpleReadGCPtr failed for uSrcAddr=%RTptr cbToRead=%x rc=%d\n", uSrcAddr, cbToRead, rc));
    316 
    317 # elif defined(IN_RING3)
    318     if (!PATMIsPatchGCAddr(pVM, uSrcAddr))
    319     {
    320         int rc = PGMPhysSimpleReadGCPtr(pVCpu, pbDst, uSrcAddr, cbToRead);
    321         AssertRC(rc);
     307        rc = VINF_SUCCESS;
    322308    }
    323309    else
    324         memcpy(pbDst, PATMR3GCPtrToHCPtr(pVM, uSrcAddr), cbToRead);
    325 
    326 # elif defined(IN_RC)
    327     if (!PATMIsPatchGCAddr(pVM, uSrcAddr))
    328     {
    329         int rc = MMGCRamRead(pVM, pbDst, (void *)(uintptr_t)uSrcAddr, cbToRead);
     310#endif
     311    {
     312# ifdef IN_RC
     313        /*
     314         * Try access it thru the shadow page tables first. Fall back on the
     315         * slower PGM method if it fails because the TLB or page table was
     316         * modified recently.
     317         */
     318        rc = MMGCRamRead(pVCpu->pVMRC, &pDis->abInstr[offInstr], (void *)(uintptr_t)uSrcAddr, cbToRead);
     319        if (rc == VERR_ACCESS_DENIED && cbToRead > cbMinRead)
     320        {
     321            cbToRead = cbMinRead;
     322            rc = MMGCRamRead(pVCpu->pVMRC, &pDis->abInstr[offInstr], (void *)(uintptr_t)uSrcAddr, cbToRead);
     323        }
    330324        if (rc == VERR_ACCESS_DENIED)
     325#endif
    331326        {
    332             /* Recently flushed; access the data manually. */
    333             rc = PGMPhysSimpleReadGCPtr(pVCpu, pbDst, uSrcAddr, cbToRead);
    334             AssertRC(rc);
     327            rc = PGMPhysSimpleReadGCPtr(pVCpu, &pDis->abInstr[offInstr], uSrcAddr, cbToRead);
     328            if (RT_FAILURE(rc))
     329            {
     330                if (cbToRead > cbMinRead)
     331                {
     332                    cbToRead = cbMinRead;
     333                    rc = PGMPhysSimpleReadGCPtr(pVCpu, &pDis->abInstr[offInstr], uSrcAddr, cbToRead);
     334                }
     335                if (RT_FAILURE(rc))
     336                {
     337#ifndef IN_RC
     338                    /*
     339                     * If we fail to find the page via the guest's page tables
     340                     * we invalidate the page in the host TLB (pertaining to
     341                     * the guest in the NestedPaging case). See #6043.
     342                     */
     343                    if (rc == VERR_PAGE_TABLE_NOT_PRESENT || rc == VERR_PAGE_NOT_PRESENT)
     344                    {
     345                        HWACCMInvalidatePage(pVCpu, uSrcAddr);
     346                        if (((uSrcAddr + cbToRead - 1) >> PAGE_SHIFT) !=  (uSrcAddr >> PAGE_SHIFT))
     347                            HWACCMInvalidatePage(pVCpu, uSrcAddr + cbToRead - 1);
     348                    }
     349#endif
     350                }
     351            }
    335352        }
    336353    }
    337     else /* the hypervisor region is always present. */
    338         memcpy(pbDst, (RTRCPTR)(uintptr_t)uSrcAddr, cbToRead);
    339 
    340 # endif /* IN_RING3 */
     354
    341355    pDis->cbCachedInstr = offInstr + cbToRead;
    342     return VINF_SUCCESS;
    343 }
    344 
    345 #ifndef IN_RC
     356    return rc;
     357}
     358
    346359
    347360DECLINLINE(int) emDisCoreOne(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, RTGCUINTPTR InstrGC, uint32_t *pOpsize)
    348361{
    349     EMDISSTATE State;
    350 
    351     State.pVM   = pVM;
    352     State.pVCpu = pVCpu;
    353     int rc = PGMPhysSimpleReadGCPtr(pVCpu, &State.aOpcode, InstrGC, sizeof(State.aOpcode));
    354     if (RT_SUCCESS(rc))
    355     {
    356         State.GCPtr = InstrGC;
    357     }
    358     else
    359     {
    360         if (PAGE_ADDRESS(InstrGC) == PAGE_ADDRESS(InstrGC + sizeof(State.aOpcode) - 1))
    361         {
    362             /*
    363              * If we fail to find the page via the guest's page tables we invalidate the page
    364              * in the host TLB (pertaining to the guest in the NestedPaging case). See #6043
    365              */
    366             if (rc == VERR_PAGE_TABLE_NOT_PRESENT || rc == VERR_PAGE_NOT_PRESENT)
    367                 HWACCMInvalidatePage(pVCpu, InstrGC);
    368 
    369            Log(("emDisCoreOne: read failed with %d\n", rc));
    370            return rc;
    371         }
    372         State.GCPtr = NIL_RTGCPTR;
    373     }
    374     return DISInstrWithReader(InstrGC, (DISCPUMODE)pDis->uCpuMode, emReadBytes, &State, pDis, pOpsize);
    375 }
    376 
    377 #else /* IN_RC */
    378 
    379 DECLINLINE(int) emDisCoreOne(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, RTGCUINTPTR InstrGC, uint32_t *pOpsize)
    380 {
    381     EMDISSTATE State;
    382 
    383     State.pVM   = pVM;
    384     State.pVCpu = pVCpu;
    385     State.GCPtr = InstrGC;
    386 
    387     return DISInstrWithReader(InstrGC, (DISCPUMODE)pDis->uCpuMode, emReadBytes, &State, pDis, pOpsize);
    388 }
    389 
    390 #endif /* IN_RC */
     362    return DISInstrWithReader(InstrGC, (DISCPUMODE)pDis->uCpuMode, emReadBytes, pVCpu, pDis, pOpsize);
     363}
    391364
    392365
     
    435408VMMDECL(int) EMInterpretDisasOneEx(PVM pVM, PVMCPU pVCpu, RTGCUINTPTR GCPtrInstr, PCCPUMCTXCORE pCtxCore, PDISCPUSTATE pDis, unsigned *pcbInstr)
    436409{
    437     int        rc;
    438     EMDISSTATE State;
    439 
    440     State.pVM   = pVM;
    441     State.pVCpu = pVCpu;
    442 
    443 #ifdef IN_RC
    444     State.GCPtr = GCPtrInstr;
    445 #else /* ring 0/3 */
    446     rc = PGMPhysSimpleReadGCPtr(pVCpu, &State.aOpcode, GCPtrInstr, sizeof(State.aOpcode));
    447     if (RT_SUCCESS(rc))
    448     {
    449         State.GCPtr = GCPtrInstr;
    450     }
    451     else
    452     {
    453         if (PAGE_ADDRESS(GCPtrInstr) == PAGE_ADDRESS(GCPtrInstr + sizeof(State.aOpcode) - 1))
    454         {
    455             /*
    456              * If we fail to find the page via the guest's page tables we invalidate the page
    457              * in the host TLB (pertaining to the guest in the NestedPaging case). See #6043
    458              */
    459             if (rc == VERR_PAGE_TABLE_NOT_PRESENT || rc == VERR_PAGE_NOT_PRESENT)
    460                 HWACCMInvalidatePage(pVCpu, GCPtrInstr);
    461 
    462            Log(("EMInterpretDisasOneEx: read failed with %d\n", rc));
    463            return rc;
    464         }
    465         State.GCPtr = NIL_RTGCPTR;
    466     }
    467 #endif
    468 
    469410    DISCPUMODE enmCpuMode = SELMGetCpuModeFromSelector(pVCpu, pCtxCore->eflags, pCtxCore->cs, (PCPUMSELREGHID)&pCtxCore->csHid);
    470     rc = DISInstrWithReader(GCPtrInstr, enmCpuMode, emReadBytes, &State, pDis, pcbInstr);
     411    int rc = DISInstrWithReader(GCPtrInstr, enmCpuMode, emReadBytes, pVCpu, pDis, pcbInstr);
    471412    if (RT_SUCCESS(rc))
    472413        return VINF_SUCCESS;
  • trunk/src/VBox/VMM/VMMRC/MMRamRC.cpp

    r39402 r41766  
    7979 * @param   pDst        Where to store the read data.
    8080 * @param   pSrc        Pointer to the data to read.
    81  * @param   cb          Size of data to read, only 1/2/4/8 is valid.
     81 * @param   cb          Size of data to read.
    8282 */
    8383VMMRCDECL(int) MMGCRamRead(PVM pVM, void *pDst, void *pSrc, size_t cb)
     
    8686    PVMCPU pVCpu = VMMGetCpu0(pVM);
    8787
    88     TRPMSaveTrap(pVCpu);  /* save the current trap info, because it will get trashed if our access failed. */
     88    /*
     89     * Save the current trap info, because it will get trashed if our access failed.
     90     */
     91    TRPMSaveTrap(pVCpu);
    8992
     93    /*
     94     * Need to serve the request in a silly loop because the assembly code wasn't
     95     * written for abrbitrary sizes, only 1/2/4/8.
     96     */
    9097    MMGCRamRegisterTrapHandler(pVM);
    91     rc = MMGCRamReadNoTrapHandler(pDst, pSrc, cb);
     98    for (;;)
     99    {
     100        size_t cbThisRead;
     101        switch (cb)
     102        {
     103            case 1: cbThisRead = 1; break;
     104            case 2: cbThisRead = 2; break;
     105            case 3: cbThisRead = 2; break;
     106            case 4: cbThisRead = 4; break;
     107            case 5: cbThisRead = 4; break;
     108            case 6: cbThisRead = 4; break;
     109            case 7: cbThisRead = 4; break;
     110            default:
     111            case 8: cbThisRead = 8; break;
     112        }
     113        rc = MMGCRamReadNoTrapHandler(pDst, pSrc, cbThisRead);
     114        if (RT_FAILURE(rc) || cbThisRead == cb)
     115            break;
     116
     117        /* advance */
     118        cb   -= cbThisRead;
     119        pDst  = (uint8_t *)pDst + cbThisRead;
     120        pSrc  = (uint8_t *)pSrc + cbThisRead;
     121    }
    92122    MMGCRamDeregisterTrapHandler(pVM);
     123
    93124    if (RT_FAILURE(rc))
    94125        TRPMRestoreTrap(pVCpu);
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette