VirtualBox

Changeset 100222 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Jun 20, 2023 2:40:48 AM (20 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
157932
Message:

VMM/IEM: More recompilation code. bugref:10369

Location:
trunk/src/VBox/VMM/VMMAll
Files:
4 edited

Legend:

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

    r100060 r100222  
    1048710487
    1048810488
     10489/**
     10490 * Code common to IEMExecLots and IEMExecRecompilerThreaded that attempts to
     10491 * inject a pending TRPM trap.
     10492 */
     10493VBOXSTRICTRC iemExecInjectPendingTrap(PVMCPUCC pVCpu)
     10494{
     10495    Assert(TRPMHasTrap(pVCpu));
     10496
     10497    if (   !CPUMIsInInterruptShadow(&pVCpu->cpum.GstCtx)
     10498        && !CPUMAreInterruptsInhibitedByNmi(&pVCpu->cpum.GstCtx))
     10499    {
     10500        /** @todo Can we centralize this under CPUMCanInjectInterrupt()? */
     10501#if defined(VBOX_WITH_NESTED_HWVIRT_SVM) || defined(VBOX_WITH_NESTED_HWVIRT_VMX)
     10502        bool fIntrEnabled = CPUMGetGuestGif(&pVCpu->cpum.GstCtx);
     10503        if (fIntrEnabled)
     10504        {
     10505            if (!CPUMIsGuestInNestedHwvirtMode(IEM_GET_CTX(pVCpu)))
     10506                fIntrEnabled = pVCpu->cpum.GstCtx.eflags.Bits.u1IF;
     10507            else if (CPUMIsGuestInVmxNonRootMode(IEM_GET_CTX(pVCpu)))
     10508                fIntrEnabled = CPUMIsGuestVmxPhysIntrEnabled(IEM_GET_CTX(pVCpu));
     10509            else
     10510            {
     10511                Assert(CPUMIsGuestInSvmNestedHwVirtMode(IEM_GET_CTX(pVCpu)));
     10512                fIntrEnabled = CPUMIsGuestSvmPhysIntrEnabled(pVCpu, IEM_GET_CTX(pVCpu));
     10513            }
     10514        }
     10515#else
     10516        bool fIntrEnabled = pVCpu->cpum.GstCtx.eflags.Bits.u1IF;
     10517#endif
     10518        if (fIntrEnabled)
     10519        {
     10520            uint8_t     u8TrapNo;
     10521            TRPMEVENT   enmType;
     10522            uint32_t    uErrCode;
     10523            RTGCPTR     uCr2;
     10524            int rc2 = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrCode, &uCr2, NULL /*pu8InstLen*/, NULL /*fIcebp*/);
     10525            AssertRC(rc2);
     10526            Assert(enmType == TRPM_HARDWARE_INT);
     10527            VBOXSTRICTRC rcStrict = IEMInjectTrap(pVCpu, u8TrapNo, enmType, (uint16_t)uErrCode, uCr2, 0 /*cbInstr*/);
     10528
     10529            TRPMResetTrap(pVCpu);
     10530
     10531#if defined(VBOX_WITH_NESTED_HWVIRT_SVM) || defined(VBOX_WITH_NESTED_HWVIRT_VMX)
     10532            /* Injecting an event may cause a VM-exit. */
     10533            if (   rcStrict != VINF_SUCCESS
     10534                && rcStrict != VINF_IEM_RAISED_XCPT)
     10535                return iemExecStatusCodeFiddling(pVCpu, rcStrict);
     10536#else
     10537            NOREF(rcStrict);
     10538#endif
     10539        }
     10540    }
     10541
     10542    return VINF_SUCCESS;
     10543}
     10544
     10545
    1048910546VMMDECL(VBOXSTRICTRC) IEMExecLots(PVMCPUCC pVCpu, uint32_t cMaxInstructions, uint32_t cPollRate, uint32_t *pcInstructions)
    1049010547{
     
    1050210559    else
    1050310560    {
    10504         if (   !CPUMIsInInterruptShadow(&pVCpu->cpum.GstCtx)
    10505             && !CPUMAreInterruptsInhibitedByNmi(&pVCpu->cpum.GstCtx))
    10506         {
    10507             /** @todo Can we centralize this under CPUMCanInjectInterrupt()? */
    10508 #if defined(VBOX_WITH_NESTED_HWVIRT_SVM) || defined(VBOX_WITH_NESTED_HWVIRT_VMX)
    10509             bool fIntrEnabled = CPUMGetGuestGif(&pVCpu->cpum.GstCtx);
    10510             if (fIntrEnabled)
    10511             {
    10512                 if (!CPUMIsGuestInNestedHwvirtMode(IEM_GET_CTX(pVCpu)))
    10513                     fIntrEnabled = pVCpu->cpum.GstCtx.eflags.Bits.u1IF;
    10514                 else if (CPUMIsGuestInVmxNonRootMode(IEM_GET_CTX(pVCpu)))
    10515                     fIntrEnabled = CPUMIsGuestVmxPhysIntrEnabled(IEM_GET_CTX(pVCpu));
    10516                 else
    10517                 {
    10518                     Assert(CPUMIsGuestInSvmNestedHwVirtMode(IEM_GET_CTX(pVCpu)));
    10519                     fIntrEnabled = CPUMIsGuestSvmPhysIntrEnabled(pVCpu, IEM_GET_CTX(pVCpu));
    10520                 }
    10521             }
    10522 #else
    10523             bool fIntrEnabled = pVCpu->cpum.GstCtx.eflags.Bits.u1IF;
    10524 #endif
    10525             if (fIntrEnabled)
    10526             {
    10527                 uint8_t     u8TrapNo;
    10528                 TRPMEVENT   enmType;
    10529                 uint32_t    uErrCode;
    10530                 RTGCPTR     uCr2;
    10531                 int rc2 = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrCode, &uCr2, NULL /*pu8InstLen*/, NULL /*fIcebp*/);
    10532                 AssertRC(rc2);
    10533                 Assert(enmType == TRPM_HARDWARE_INT);
    10534                 VBOXSTRICTRC rcStrict = IEMInjectTrap(pVCpu, u8TrapNo, enmType, (uint16_t)uErrCode, uCr2, 0 /*cbInstr*/);
    10535 
    10536                 TRPMResetTrap(pVCpu);
    10537 
    10538 #if defined(VBOX_WITH_NESTED_HWVIRT_SVM) || defined(VBOX_WITH_NESTED_HWVIRT_VMX)
    10539                 /* Injecting an event may cause a VM-exit. */
    10540                 if (   rcStrict != VINF_SUCCESS
    10541                     && rcStrict != VINF_IEM_RAISED_XCPT)
    10542                     return iemExecStatusCodeFiddling(pVCpu, rcStrict);
    10543 #else
    10544                 NOREF(rcStrict);
    10545 #endif
    10546             }
    10547         }
     10561        VBOXSTRICTRC rcStrict = iemExecInjectPendingTrap(pVCpu);
     10562        if (RT_LIKELY(rcStrict == VINF_SUCCESS))
     10563        { /*likely */ }
     10564        else
     10565            return rcStrict;
    1054810566    }
    1054910567
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp

    r100108 r100222  
    314314 * @{
    315315 */
     316
     317
     318/**
     319 * Implements a pop [mem16].
     320 */
     321IEM_CIMPL_DEF_2(iemCImpl_pop_mem16, uint16_t, iEffSeg, RTGCPTR, GCPtrEffDst)
     322{
     323    uint16_t  u16Value;
     324    RTUINT64U TmpRsp;
     325    TmpRsp.u = pVCpu->cpum.GstCtx.rsp;
     326    VBOXSTRICTRC rcStrict = iemMemStackPopU16Ex(pVCpu, &u16Value, &TmpRsp);
     327    if (rcStrict == VINF_SUCCESS)
     328    {
     329        rcStrict = iemMemStoreDataU16(pVCpu, iEffSeg, GCPtrEffDst, u16Value);
     330        if (rcStrict == VINF_SUCCESS)
     331        {
     332            pVCpu->cpum.GstCtx.rsp = TmpRsp.u;
     333            return iemRegAddToRipAndFinishingClearingRF(pVCpu, cbInstr);
     334        }
     335    }
     336    return rcStrict;
     337
     338}
     339
     340
     341/**
     342 * Implements a pop [mem32].
     343 */
     344IEM_CIMPL_DEF_2(iemCImpl_pop_mem32, uint16_t, iEffSeg, RTGCPTR, GCPtrEffDst)
     345{
     346    uint32_t  u32Value;
     347    RTUINT64U TmpRsp;
     348    TmpRsp.u = pVCpu->cpum.GstCtx.rsp;
     349    VBOXSTRICTRC rcStrict = iemMemStackPopU32Ex(pVCpu, &u32Value, &TmpRsp);
     350    if (rcStrict == VINF_SUCCESS)
     351    {
     352        rcStrict = iemMemStoreDataU32(pVCpu, iEffSeg, GCPtrEffDst, u32Value);
     353        if (rcStrict == VINF_SUCCESS)
     354        {
     355            pVCpu->cpum.GstCtx.rsp = TmpRsp.u;
     356            return iemRegAddToRipAndFinishingClearingRF(pVCpu, cbInstr);
     357        }
     358    }
     359    return rcStrict;
     360
     361}
     362
     363
     364/**
     365 * Implements a pop [mem64].
     366 */
     367IEM_CIMPL_DEF_2(iemCImpl_pop_mem64, uint16_t, iEffSeg, RTGCPTR, GCPtrEffDst)
     368{
     369    uint64_t  u64Value;
     370    RTUINT64U TmpRsp;
     371    TmpRsp.u = pVCpu->cpum.GstCtx.rsp;
     372    VBOXSTRICTRC rcStrict = iemMemStackPopU64Ex(pVCpu, &u64Value, &TmpRsp);
     373    if (rcStrict == VINF_SUCCESS)
     374    {
     375        rcStrict = iemMemStoreDataU64(pVCpu, iEffSeg, GCPtrEffDst, u64Value);
     376        if (rcStrict == VINF_SUCCESS)
     377        {
     378            pVCpu->cpum.GstCtx.rsp = TmpRsp.u;
     379            return iemRegAddToRipAndFinishingClearingRF(pVCpu, cbInstr);
     380        }
     381    }
     382    return rcStrict;
     383
     384}
     385
    316386
    317387/**
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsOneByte.cpp.h

    r100148 r100222  
    52145214    IEMOP_HLP_DEFAULT_64BIT_OP_SIZE(); /* The common code does this differently. */
    52155215
    5216 #ifndef TST_IEM_CHECK_MC
     5216#if 1 /* This can be compiled, optimize later if needed. */
     5217    switch (pVCpu->iem.s.enmEffOpSize)
     5218    {
     5219        case IEMMODE_16BIT:
     5220        {
     5221            IEM_MC_BEGIN(2, 0);
     5222            IEM_MC_ARG_CONST(uint8_t,       iEffSeg, /*=*/ pVCpu->iem.s.iEffSeg, 0);
     5223            IEM_MC_ARG(      RTGCPTR,       GCPtrEffDst,                         1);
     5224            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 2 << 8);
     5225            IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
     5226            IEM_MC_CALL_CIMPL_2(0, iemCImpl_pop_mem16, iEffSeg, GCPtrEffDst);
     5227            IEM_MC_END();
     5228        }
     5229
     5230        case IEMMODE_32BIT:
     5231        {
     5232            IEM_MC_BEGIN(2, 0);
     5233            IEM_MC_ARG_CONST(uint8_t,       iEffSeg, /*=*/ pVCpu->iem.s.iEffSeg, 0);
     5234            IEM_MC_ARG(      RTGCPTR,       GCPtrEffDst,                         1);
     5235            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 4 << 8);
     5236            IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
     5237            IEM_MC_CALL_CIMPL_2(0, iemCImpl_pop_mem32, iEffSeg, GCPtrEffDst);
     5238            IEM_MC_END();
     5239        }
     5240
     5241        case IEMMODE_64BIT:
     5242        {
     5243            IEM_MC_BEGIN(2, 0);
     5244            IEM_MC_ARG_CONST(uint8_t,       iEffSeg, /*=*/ pVCpu->iem.s.iEffSeg, 0);
     5245            IEM_MC_ARG(      RTGCPTR,       GCPtrEffDst,                         1);
     5246            IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 8 << 8);
     5247            IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
     5248            IEM_MC_CALL_CIMPL_2(0, iemCImpl_pop_mem64, iEffSeg, GCPtrEffDst);
     5249            IEM_MC_END();
     5250        }
     5251
     5252        IEM_NOT_REACHED_DEFAULT_CASE_RET();
     5253    }
     5254
     5255#else
     5256# ifndef TST_IEM_CHECK_MC
    52175257    /* Calc effective address with modified ESP. */
    52185258/** @todo testcase */
     
    52715311    return rcStrict;
    52725312
    5273 #else
     5313# else
    52745314    return VERR_IEM_IPE_2;
     5315# endif
    52755316#endif
    52765317}
  • trunk/src/VBox/VMM/VMMAll/IEMAllThreadedRecompiler.cpp

    r100202 r100222  
    3131*********************************************************************************************************************************/
    3232#ifndef LOG_GROUP /* defined when included by tstIEMCheckMc.cpp */
    33 # define LOG_GROUP LOG_GROUP_IEM
     33# define LOG_GROUP LOG_GROUP_IEM_RE_THREADED
    3434#endif
    3535#define VMCPU_INCL_CPUM_GST_CTX
     
    306306 * Translation block management.
    307307 */
     308typedef struct IEMTBCACHE
     309{
     310    uint32_t cHash;
     311    uint32_t uHashMask;
     312    PIEMTB   apHash[_64K];
     313} IEMTBCACHE;
     314
     315static IEMTBCACHE g_TbCache = { _64K, 0xffff, }; /**< Quick and dirty. */
     316
     317#define IEMTBCACHE_HASH(a_paCache, a_fTbFlags, a_GCPhysPc) \
     318    ( ((uint32_t)(a_GCPhysPc) ^ (a_fTbFlags)) & (a_paCache)->uHashMask)
     319
    308320
    309321/**
     
    374386
    375387
    376 static PIEMTB iemThreadedTbLookup(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhysPc, uint64_t uPc, uint32_t fExtraFlags)
    377 {
    378     RT_NOREF(pVM, pVCpu, GCPhysPc, uPc, fExtraFlags);
    379     return NULL;
     388static PIEMTB iemThreadedTbLookup(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhysPc, uint32_t fExtraFlags)
     389{
     390    uint32_t const fFlags  = (pVCpu->iem.s.fExec & IEMTB_F_IEM_F_MASK) | fExtraFlags | IEMTB_F_STATE_READY;
     391    uint32_t const idxHash = IEMTBCACHE_HASH(&g_TbCache, fFlags, GCPhysPc);
     392    Log10(("TB lookup: idxHash=%#x fFlags=%#x GCPhysPc=%RGp\n", idxHash, fFlags, GCPhysPc));
     393    PIEMTB pTb = g_TbCache.apHash[idxHash];
     394    while (pTb)
     395    {
     396        if (pTb->GCPhysPc == GCPhysPc)
     397        {
     398            if (pTb->fFlags == fFlags)
     399            {
     400                if (pTb->x86.fAttr == (uint16_t)pVCpu->cpum.GstCtx.cs.Attr.u)
     401                {
     402#ifdef VBOX_WITH_STATISTICS
     403                    pVCpu->iem.s.cTbLookupHits++;
     404                    return pTb;
     405#endif
     406                }
     407                Log11(("TB miss: CS: %#x, wanted %#x\n", pTb->x86.fAttr, (uint16_t)pVCpu->cpum.GstCtx.cs.Attr.u));
     408            }
     409            else
     410                Log11(("TB miss: fFlags: %#x, wanted %#x\n", pTb->fFlags, fFlags));
     411        }
     412        else
     413            Log11(("TB miss: GCPhysPc: %#x, wanted %#x\n", pTb->GCPhysPc, GCPhysPc));
     414
     415        pTb = pTb->pNext;
     416    }
     417    RT_NOREF(pVM);
     418    pVCpu->iem.s.cTbLookupMisses++;
     419    return pTb;
     420}
     421
     422
     423static void iemThreadedTbAdd(PVMCC pVM, PVMCPUCC pVCpu, PIEMTB pTb)
     424{
     425    uint32_t const idxHash = IEMTBCACHE_HASH(&g_TbCache, pTb->fFlags, pTb->GCPhysPc);
     426    pTb->pNext = g_TbCache.apHash[idxHash];
     427    g_TbCache.apHash[idxHash] = pTb;
     428    Log12(("TB added: %p %RGp LB %#x fl=%#x idxHash=%#x\n", pTb, pTb->GCPhysPc, pTb->cbPC, pTb->fFlags, idxHash));
     429    RT_NOREF(pVM, pVCpu);
    380430}
    381431
     
    593643            Assert(pTb->Thrd.cCalls > cCallsPrev);
    594644            Assert(cCallsPrev - pTb->Thrd.cCalls < 5);
    595 
    596645        }
    597646        else if (pTb->Thrd.cCalls > 0)
    598         {
    599647            break;
    600         }
    601648        else
    602649        {
     
    617664     * Complete the TB and link it.
    618665     */
     666    pTb->fFlags = (pTb->fFlags & ~IEMTB_F_STATE_MASK) | IEMTB_F_STATE_READY;
     667    iemThreadedTbAdd(pVM, pVCpu, pTb);
    619668
    620669#ifdef IEM_COMPILE_ONLY_MODE
     
    672721 * This is called when the PC doesn't match the current pbInstrBuf.
    673722 */
    674 static uint64_t iemGetPcWithPhysAndCodeMissed(PVMCPUCC pVCpu, uint64_t const uPc, PRTGCPHYS pPhys)
     723static RTGCPHYS iemGetPcWithPhysAndCodeMissed(PVMCPUCC pVCpu, uint64_t const uPc)
    675724{
    676725    /** @todo see iemOpcodeFetchBytesJmp */
     
    682731    pVCpu->iem.s.cbInstrBufTotal  = 0;
    683732
    684     RT_NOREF(uPc, pPhys);
    685     return 0;
     733    uint8_t bIgn;
     734    iemOpcodeFetchBytesJmp(pVCpu, 1, &bIgn);
     735
     736    uint64_t off = uPc - pVCpu->iem.s.uInstrBufPc;
     737    if (off < pVCpu->iem.s.cbInstrBufTotal)
     738    {
     739        pVCpu->iem.s.offInstrNextByte = (uint32_t)off;
     740        pVCpu->iem.s.offCurInstrStart = (uint16_t)off;
     741        if ((uint16_t)off + 15 <= pVCpu->iem.s.cbInstrBufTotal)
     742            pVCpu->iem.s.cbInstrBuf = (uint16_t)off + 15;
     743        else
     744            pVCpu->iem.s.cbInstrBuf = pVCpu->iem.s.cbInstrBufTotal;
     745
     746        return pVCpu->iem.s.GCPhysInstrBuf + off;
     747    }
     748
     749    AssertFailed();
     750    RT_NOREF(uPc);
     751    return NIL_RTGCPHYS;
    686752}
    687753
    688754
    689755/** @todo need private inline decl for throw/nothrow matching IEM_WITH_SETJMP? */
    690 DECL_FORCE_INLINE_THROW(uint64_t) iemGetPcWithPhysAndCode(PVMCPUCC pVCpu, PRTGCPHYS pPhys)
     756DECL_FORCE_INLINE_THROW(RTGCPHYS) iemGetPcWithPhysAndCode(PVMCPUCC pVCpu)
    691757{
    692758    /* Set uCurTbStartPc to RIP and calc the effective PC. */
     
    708774                pVCpu->iem.s.cbInstrBuf = pVCpu->iem.s.cbInstrBufTotal;
    709775
    710             *pPhys = pVCpu->iem.s.GCPhysInstrBuf + off;
    711             return uPc;
    712         }
    713     }
    714     return iemGetPcWithPhysAndCodeMissed(pVCpu, uPc, pPhys);
     776            return pVCpu->iem.s.GCPhysInstrBuf + off;
     777        }
     778    }
     779    return iemGetPcWithPhysAndCodeMissed(pVCpu, uPc);
    715780}
    716781
     
    747812VMMDECL(VBOXSTRICTRC) IEMExecRecompilerThreaded(PVMCC pVM, PVMCPUCC pVCpu)
    748813{
     814    /*
     815     * See if there is an interrupt pending in TRPM, inject it if we can.
     816     */
     817    if (!TRPMHasTrap(pVCpu))
     818    { /* likely */ }
     819    else
     820    {
     821        VBOXSTRICTRC rcStrict = iemExecInjectPendingTrap(pVCpu);
     822        if (RT_LIKELY(rcStrict == VINF_SUCCESS))
     823        { /*likely */ }
     824        else
     825            return rcStrict;
     826    }
     827
    749828    /*
    750829     * Init the execution environment.
     
    769848            {
    770849                /* Translate PC to physical address, we'll need this for both lookup and compilation. */
    771                 RTGCPHYS       GCPhysPc;
    772                 uint64_t const uPc         = iemGetPcWithPhysAndCode(pVCpu, &GCPhysPc);
     850                RTGCPHYS const GCPhysPc    = iemGetPcWithPhysAndCode(pVCpu);
    773851                uint32_t const fExtraFlags = iemGetTbFlagsForCurrentPc(pVCpu);
    774852
    775                 pTb = iemThreadedTbLookup(pVM, pVCpu, GCPhysPc, uPc, fExtraFlags);
     853                pTb = iemThreadedTbLookup(pVM, pVCpu, GCPhysPc, fExtraFlags);
    776854                if (pTb)
    777855                    rcStrict = iemThreadedTbExec(pVCpu, pTb);
     
    779857                    rcStrict = iemThreadedCompile(pVM, pVCpu, GCPhysPc, fExtraFlags);
    780858                if (rcStrict == VINF_SUCCESS)
    781                 { /* likely */ }
     859                {
     860                    Assert(pVCpu->iem.s.cActiveMappings == 0);
     861
     862                    uint64_t fCpu = pVCpu->fLocalForcedActions;
     863                    fCpu &= VMCPU_FF_ALL_MASK & ~(  VMCPU_FF_PGM_SYNC_CR3
     864                                                  | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL
     865                                                  | VMCPU_FF_TLB_FLUSH
     866                                                  | VMCPU_FF_UNHALT );
     867                    if (!fCpu)
     868                    {
     869                        /* likely */
     870                    }
     871                    else
     872                        return VINF_SUCCESS;
     873                }
    782874                else
    783875                    return rcStrict;
     
    788880        {
    789881            pVCpu->iem.s.cLongJumps++;
     882            if (pVCpu->iem.s.cActiveMappings > 0)
     883                iemMemRollback(pVCpu);
    790884            if (pTb)
    791885                return rcStrict;
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