VirtualBox

Ignore:
Timestamp:
May 1, 2024 12:43:28 AM (9 months ago)
Author:
vboxsync
Message:

VMM/IEM: Deal with the simples direct 'linking' of TBs scenario for relative jumps, when staying with the same code page. bugref:10656

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompFuncs.h

    r104460 r104468  
    345345
    346346
     347/** Helper for iemNativeEmitFinishInstructionWithStatus. */
     348DECLINLINE(RTGCPHYS) iemNativeCallEntryToGCPhysPc(PCIEMTB pTb, PCIEMTHRDEDCALLENTRY pCallEntry)
     349{
     350    unsigned const offOpcodes = pCallEntry->offOpcode;
     351    unsigned const cRanges    = RT_MIN(pTb->cRanges, RT_ELEMENTS(pTb->aRanges));
     352    for (unsigned  idxRange   = 0; idxRange < cRanges; idxRange++)
     353    {
     354        unsigned const offRange = offOpcodes - (unsigned)pTb->aRanges[idxRange].offOpcodes;
     355        if (offRange < (unsigned)pTb->aRanges[idxRange].cbOpcodes)
     356            return iemTbGetRangePhysPageAddr(pTb, idxRange) + offRange + pTb->aRanges[idxRange].offPhysPage;
     357    }
     358    AssertFailedReturn(NIL_RTGCPHYS);
     359}
     360
     361
    347362/** The VINF_SUCCESS dummy. */
    348 template<int const a_rcNormal>
    349 DECL_FORCE_INLINE(uint32_t)
    350 iemNativeEmitFinishInstructionWithStatus(PIEMRECOMPILERSTATE pReNative, uint32_t off, PCIEMTHRDEDCALLENTRY pCallEntry)
     363template<int const a_rcNormal, bool const a_fIsJump>
     364DECL_FORCE_INLINE_THROW(uint32_t)
     365iemNativeEmitFinishInstructionWithStatus(PIEMRECOMPILERSTATE pReNative, uint32_t off, PCIEMTHRDEDCALLENTRY pCallEntry,
     366                                         int32_t const offJump)
    351367{
    352368    AssertCompile(a_rcNormal == VINF_SUCCESS || a_rcNormal == VINF_IEM_REEXEC_BREAK);
     
    362378        off = iemNativeRegFlushPendingWrites(pReNative, off);
    363379
     380        /*
     381         * Use the lookup table for getting to the next TB quickly.
     382         * Note! In this code path there can only be one entry at present.
     383         */
     384        uint8_t const  idxTbLookupFirst = IEM_TB_LOOKUP_TAB_GET_IDX(pCallEntry->uTbLookup);
     385        PCIEMTB const  pTbOrg           = pReNative->pTbOrg;
     386        Assert(idxTbLookupFirst < pTbOrg->cTbLookupEntries);
     387        Assert(IEM_TB_LOOKUP_TAB_GET_SIZE(pCallEntry->uTbLookup) == 1);
     388
     389#if 0
    364390        /* Update IEMCPU::ppTbLookupEntryR3 to get the best lookup effect. */
    365         uint8_t const  idxTbLookupFirst = IEM_TB_LOOKUP_TAB_GET_IDX(pCallEntry->uTbLookup);
    366         Assert(idxTbLookupFirst < pReNative->pTbOrg->cTbLookupEntries);
    367         PIEMTB * const ppTbLookupFirst  = IEMTB_GET_TB_LOOKUP_TAB_ENTRY(pReNative->pTbOrg, idxTbLookupFirst);
     391        PIEMTB * const ppTbLookupFirst  = IEMTB_GET_TB_LOOKUP_TAB_ENTRY(pTbOrg, idxTbLookupFirst);
    368392        Assert(IEM_TB_LOOKUP_TAB_GET_SIZE(pCallEntry->uTbLookup) == 1); /* large stuff later/never */
    369393        off = iemNativeEmitStoreImmToVCpuU64(pReNative, off, (uintptr_t)ppTbLookupFirst,
     
    371395
    372396        return iemNativeEmitJmpToNewLabel(pReNative, off, kIemNativeLabelType_ReturnBreak);
     397
     398#else
     399        /* Load the index as argument #1 for the helper call at the given label. */
     400        off = iemNativeEmitLoadGpr8Imm(pReNative, off, IEMNATIVE_CALL_ARG1_GREG, idxTbLookupFirst);
     401
     402        /*
     403         * Figure out the physical address of the current instruction and see
     404         * whether the next instruction we're about to execute is in the same
     405         * page so we by can optimistically skip TLB loading.
     406         *
     407         * - This is safe for all cases in FLAT mode.
     408         * - In segmentmented modes it is complicated, given that a negative
     409         *   jump may underflow EIP and a forward jump may overflow or run into
     410         *   CS.LIM and triggering a #GP.  The only thing we can get away with
     411         *   now at compile time is forward jumps w/o CS.LIM checks, since the
     412         *   lack of CS.LIM checks means we're good for the entire physical page
     413         *   we're executing on and another 15 bytes before we run into CS.LIM.
     414         */
     415        if (   IEM_F_MODE_X86_IS_FLAT(pReNative->fExec)
     416            || !(pTbOrg->fFlags & IEMTB_F_CS_LIM_CHECKS) )
     417        {
     418            RTGCPHYS const GCPhysPcCurrent = iemNativeCallEntryToGCPhysPc(pTbOrg, pCallEntry);
     419            RTGCPHYS const GCPhysPcNext    = GCPhysPcCurrent + pCallEntry->cbOpcode + (int64_t)(a_fIsJump ? offJump : 0);
     420            if (   (GCPhysPcNext >> GUEST_PAGE_SHIFT) == (GCPhysPcCurrent >> GUEST_PAGE_SHIFT)
     421                && GUEST_PAGE_SIZE - (GCPhysPcCurrent & GUEST_PAGE_OFFSET_MASK) >= pCallEntry->cbOpcode /* 0xfff: je -56h */ )
     422
     423            {
     424                /* Load the next GCPhysPc into the 3rd argument for the helper call. */
     425                off = iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_CALL_ARG3_GREG, GCPhysPcNext);
     426
     427                /* Load the key lookup flags into the 2nd argument for the helper call.
     428                   - This is safe wrt CS limit checking since we're only here for FLAT modes.
     429                   - ASSUMING that this isn't a STI or POPF instruction, we can exclude any
     430                     interrupt shadow.
     431                   - The NMI inhibiting is more questionable, though... */
     432                /** @todo We don't implement NMI blocking atm, except via VT-x/AMD-V.
     433                 *        Should we copy it into fExec to simplify this? OTOH, it's just a
     434                 *        couple of extra instructions if EFLAGS are already in a register. */
     435                off = iemNativeEmitLoadGprImm64(pReNative, off, IEMNATIVE_CALL_ARG2_GREG,
     436                                                (pReNative->fExec & IEMTB_F_KEY_MASK) | IEMTB_F_TYPE_NATIVE);
     437
     438                if (pReNative->idxLastCheckIrqCallNo != UINT32_MAX)
     439                    return iemNativeEmitJmpToNewLabel(pReNative, off, kIemNativeLabelType_ReturnBreakViaLookup);
     440                return iemNativeEmitJmpToNewLabel(pReNative, off, kIemNativeLabelType_ReturnBreakViaLookupWithIrq);
     441            }
     442        }
     443        if (pReNative->idxLastCheckIrqCallNo != UINT32_MAX)
     444            return iemNativeEmitJmpToNewLabel(pReNative, off, kIemNativeLabelType_ReturnBreakViaLookupWithTlb);
     445        return iemNativeEmitJmpToNewLabel(pReNative, off, kIemNativeLabelType_ReturnBreakViaLookupWithTlbAndIrq);
     446#endif
    373447    }
    374448    return off;
     
    378452#define IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC64(a_cbInstr, a_rcNormal) \
    379453    off = iemNativeEmitAddToRip64AndFinishingNoFlags(pReNative, off, (a_cbInstr)); \
    380     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     454    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, false /*a_fIsJump*/>(pReNative, off, pCallEntry, 0)
    381455
    382456#define IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC64_WITH_FLAGS(a_cbInstr, a_rcNormal) \
    383457    off = iemNativeEmitAddToRip64AndFinishingNoFlags(pReNative, off, (a_cbInstr)); \
    384458    off = iemNativeEmitFinishInstructionFlagsCheck(pReNative, off); \
    385     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     459    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, false /*a_fIsJump*/>(pReNative, off, pCallEntry, 0)
    386460
    387461/** Same as iemRegAddToRip64AndFinishingNoFlags. */
     
    425499#define IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC32(a_cbInstr, a_rcNormal) \
    426500    off = iemNativeEmitAddToEip32AndFinishingNoFlags(pReNative, off, (a_cbInstr)); \
    427     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     501    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, false /*a_fIsJump*/>(pReNative, off, pCallEntry, 0)
    428502
    429503#define IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC32_WITH_FLAGS(a_cbInstr, a_rcNormal) \
    430504    off = iemNativeEmitAddToEip32AndFinishingNoFlags(pReNative, off, (a_cbInstr)); \
    431505    off = iemNativeEmitFinishInstructionFlagsCheck(pReNative, off); \
    432     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     506    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, false /*a_fIsJump*/>(pReNative, off, pCallEntry, 0)
    433507
    434508/** Same as iemRegAddToEip32AndFinishingNoFlags. */
     
    472546#define IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC16(a_cbInstr, a_rcNormal) \
    473547    off = iemNativeEmitAddToIp16AndFinishingNoFlags(pReNative, off, (a_cbInstr)); \
    474     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     548    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, false /*a_fIsJump*/>(pReNative, off, pCallEntry, 0)
    475549
    476550#define IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC16_WITH_FLAGS(a_cbInstr, a_rcNormal) \
    477551    off = iemNativeEmitAddToIp16AndFinishingNoFlags(pReNative, off, (a_cbInstr)); \
    478552    off = iemNativeEmitFinishInstructionFlagsCheck(pReNative, off); \
    479     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     553    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, false /*a_fIsJump*/>(pReNative, off, pCallEntry, 0)
    480554
    481555/** Same as iemRegAddToIp16AndFinishingNoFlags. */
     
    526600    off = iemNativeEmitRip64RelativeJumpAndFinishingNoFlags(pReNative, off, (a_cbInstr), (int8_t)(a_i8), \
    527601                                                            (a_enmEffOpSize), pCallEntry->idxInstr); \
    528     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     602    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, true /*a_fIsJump*/>(pReNative, off, pCallEntry, (int8_t)(a_i8))
    529603
    530604#define IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC64_WITH_FLAGS(a_i8, a_cbInstr, a_enmEffOpSize, a_rcNormal) \
     
    532606                                                            (a_enmEffOpSize), pCallEntry->idxInstr); \
    533607    off = iemNativeEmitFinishInstructionFlagsCheck(pReNative, off); \
    534     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     608    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, true /*a_fIsJump*/>(pReNative, off, pCallEntry, (int8_t)(a_i8))
    535609
    536610#define IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC64(a_i16, a_cbInstr, a_rcNormal) \
    537611    off = iemNativeEmitRip64RelativeJumpAndFinishingNoFlags(pReNative, off, (a_cbInstr), (int16_t)(a_i16), \
    538612                                                            IEMMODE_16BIT, pCallEntry->idxInstr); \
    539     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     613    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, true /*a_fIsJump*/>(pReNative, off, pCallEntry, (int16_t)(a_i16))
    540614
    541615#define IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC64_WITH_FLAGS(a_i16, a_cbInstr, a_rcNormal) \
     
    543617                                                                IEMMODE_16BIT, pCallEntry->idxInstr); \
    544618    off = iemNativeEmitFinishInstructionFlagsCheck(pReNative, off); \
    545     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     619    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, true /*a_fIsJump*/>(pReNative, off, pCallEntry, (int16_t)(a_i16))
    546620
    547621#define IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC64(a_i32, a_cbInstr, a_rcNormal) \
    548622    off = iemNativeEmitRip64RelativeJumpAndFinishingNoFlags(pReNative, off, (a_cbInstr), (a_i32), \
    549623                                                            IEMMODE_64BIT, pCallEntry->idxInstr); \
    550     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     624    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, true /*a_fIsJump*/>(pReNative, off, pCallEntry, (a_i32))
    551625
    552626#define IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC64_WITH_FLAGS(a_i32, a_cbInstr, a_rcNormal) \
     
    554628                                                            IEMMODE_64BIT, pCallEntry->idxInstr); \
    555629    off = iemNativeEmitFinishInstructionFlagsCheck(pReNative, off); \
    556     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     630    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, true /*a_fIsJump*/>(pReNative, off, pCallEntry, (a_i32))
    557631
    558632/** Same as iemRegRip64RelativeJumpS8AndFinishNoFlags,
     
    603677    off = iemNativeEmitEip32RelativeJumpAndFinishingNoFlags(pReNative, off, (a_cbInstr), (int8_t)(a_i8), \
    604678                                                            (a_enmEffOpSize), pCallEntry->idxInstr); \
    605     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     679    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, true /*a_fIsJump*/>(pReNative, off, pCallEntry, (int8_t)(a_i8))
    606680
    607681#define IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC32_WITH_FLAGS(a_i8, a_cbInstr, a_enmEffOpSize, a_rcNormal) \
     
    609683                                                            (a_enmEffOpSize), pCallEntry->idxInstr); \
    610684    off = iemNativeEmitFinishInstructionFlagsCheck(pReNative, off); \
    611     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     685    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, true /*a_fIsJump*/>(pReNative, off, pCallEntry, (int8_t)(a_i8))
    612686
    613687#define IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC32(a_i16, a_cbInstr, a_rcNormal) \
    614688    off = iemNativeEmitEip32RelativeJumpAndFinishingNoFlags(pReNative, off, (a_cbInstr), (int16_t)(a_i16), \
    615689                                                            IEMMODE_16BIT, pCallEntry->idxInstr); \
    616     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     690    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, true /*a_fIsJump*/>(pReNative, off, pCallEntry, (int16_t)(a_i16))
    617691
    618692#define IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC32_WITH_FLAGS(a_i16, a_cbInstr, a_rcNormal) \
     
    620694                                                            IEMMODE_16BIT, pCallEntry->idxInstr); \
    621695    off = iemNativeEmitFinishInstructionFlagsCheck(pReNative, off); \
    622     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     696    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, true /*a_fIsJump*/>(pReNative, off, pCallEntry, (int16_t)(a_i16))
    623697
    624698#define IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC32(a_i32, a_cbInstr, a_rcNormal) \
    625699    off = iemNativeEmitEip32RelativeJumpAndFinishingNoFlags(pReNative, off, (a_cbInstr), (a_i32), \
    626700                                                            IEMMODE_32BIT, pCallEntry->idxInstr); \
    627     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     701    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, true /*a_fIsJump*/>(pReNative, off, pCallEntry, (a_i32))
    628702
    629703#define IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC32_WITH_FLAGS(a_i32, a_cbInstr, a_rcNormal) \
    630             off = iemNativeEmitEip32RelativeJumpAndFinishingNoFlags(pReNative, off, (a_cbInstr), (a_i32), \
    631                                                                     IEMMODE_32BIT, pCallEntry->idxInstr); \
     704    off = iemNativeEmitEip32RelativeJumpAndFinishingNoFlags(pReNative, off, (a_cbInstr), (a_i32), \
     705                                                            IEMMODE_32BIT, pCallEntry->idxInstr); \
    632706    off = iemNativeEmitFinishInstructionFlagsCheck(pReNative, off); \
    633     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     707    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, true /*a_fIsJump*/>(pReNative, off, pCallEntry, (a_i32))
    634708
    635709/** Same as iemRegEip32RelativeJumpS8AndFinishNoFlags,
     
    676750#define IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC16(a_i8, a_cbInstr, a_rcNormal) \
    677751    off = iemNativeEmitIp16RelativeJumpAndFinishingNoFlags(pReNative, off, (a_cbInstr), (int8_t)(a_i8), pCallEntry->idxInstr); \
    678     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     752    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, true /*a_fIsJump*/>(pReNative, off, pCallEntry, (int8_t)(a_i8))
    679753
    680754#define IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC16_WITH_FLAGS(a_i8, a_cbInstr, a_rcNormal) \
    681755    off = iemNativeEmitIp16RelativeJumpAndFinishingNoFlags(pReNative, off, (a_cbInstr), (int8_t)(a_i8), pCallEntry->idxInstr); \
    682756    off = iemNativeEmitFinishInstructionFlagsCheck(pReNative, off); \
    683     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     757    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, true /*a_fIsJump*/>(pReNative, off, pCallEntry, (int8_t)(a_i8))
    684758
    685759#define IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC16(a_i16, a_cbInstr, a_rcNormal) \
    686760    off = iemNativeEmitIp16RelativeJumpAndFinishingNoFlags(pReNative, off, (a_cbInstr), (int16_t)(a_i16), pCallEntry->idxInstr); \
    687     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     761    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, true /*a_fIsJump*/>(pReNative, off, pCallEntry, (int16_t)(a_i16))
    688762
    689763#define IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC16_WITH_FLAGS(a_i16, a_cbInstr, a_rcNormal) \
    690764    off = iemNativeEmitIp16RelativeJumpAndFinishingNoFlags(pReNative, off, (a_cbInstr), (int16_t)(a_i16), pCallEntry->idxInstr); \
    691765    off = iemNativeEmitFinishInstructionFlagsCheck(pReNative, off); \
    692     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     766    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, true /*a_fIsJump*/>(pReNative, off, pCallEntry, (int16_t)(a_i16))
    693767
    694768#define IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC16(a_i32, a_cbInstr, a_rcNormal) \
    695769    off = iemNativeEmitIp16RelativeJumpAndFinishingNoFlags(pReNative, off, (a_cbInstr), (a_i32), pCallEntry->idxInstr); \
    696     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     770    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, true /*a_fIsJump*/>(pReNative, off, pCallEntry, a_i32)
    697771
    698772#define IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC16_WITH_FLAGS(a_i32, a_cbInstr, a_rcNormal) \
    699773    off = iemNativeEmitIp16RelativeJumpAndFinishingNoFlags(pReNative, off, (a_cbInstr), (a_i32), pCallEntry->idxInstr); \
    700774    off = iemNativeEmitFinishInstructionFlagsCheck(pReNative, off); \
    701     off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal>(pReNative, off, pCallEntry)
     775    off = iemNativeEmitFinishInstructionWithStatus<a_rcNormal, true /*a_fIsJump*/>(pReNative, off, pCallEntry, a_i32)
    702776
    703777/** Same as iemRegIp16RelativeJumpS8AndFinishNoFlags. */
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