VirtualBox

Changeset 104084 in vbox for trunk/src


Ignore:
Timestamp:
Mar 27, 2024 12:55:34 PM (12 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
162485
Message:

VMM/IEM: Implement support for automatically flushing all call volatile registers which shadow a guest register and have unwritten data stored when calling an external helper, add a flag to iemNativeEmitCallCommon() to prevent calling iemNativeRegFlushPendingWrites() (except for call volatile registers which get written back always). make us of that flag when emitting code for IEM_MC_CALL_VOID_AIMPL_XXX/IEM_MC_CALL_AIMPL_XXX as assembly helplers can't throw exceptions and don't access CPUMCTX but operate entirely on the given arguments. This should avoid a few unnecessary writebacks, bugref:10629

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

Legend:

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

    r104075 r104084  
    24152415    /*
    24162416     * Do all the call setup and cleanup.
     2417     *
     2418     * It is only required to flush pending guest register writes in call volatile registers as
     2419     * assembly helpers can't throw and don't access anything living in CPUMCTX, they only
     2420     * access parameters. The flushing of call volatile registers is always done in iemNativeEmitCallCommon()
     2421     * no matter the fFlushPendingWrites parameter.
    24172422     */
    2418     off = iemNativeEmitCallCommon(pReNative, off, cArgs, 0 /*cHiddenArgs*/);
     2423    off = iemNativeEmitCallCommon(pReNative, off, cArgs, 0 /*cHiddenArgs*/, false /*fFlushPendingWrites*/);
    24192424
    24202425    /*
  • trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp

    r104073 r104084  
    43764376    RT_NOREF(pszCaller);
    43774377
     4378#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     4379    Assert(!(pReNative->Core.aHstRegs[idxRegNew].fGstRegShadows & pReNative->Core.bmGstRegShadowDirty));
     4380#endif
    43784381    iemNativeRegClearGstRegShadowing(pReNative, idxRegNew, off);
    43794382
     
    51835186    RT_NOREF(pszCaller);
    51845187
     5188    Assert(!(  (pReNative->Core.bmGstSimdRegShadowDirtyLo128 | pReNative->Core.bmGstSimdRegShadowDirtyHi128)
     5189             & pReNative->Core.aHstSimdRegs[idxRegNew].fGstRegShadows));
    51855190    iemNativeSimdRegClearGstSimdRegShadowing(pReNative, idxRegNew, off);
    51865191
     
    54185423
    54195424            AssertMsg(pReNative->Core.aHstSimdRegs[idxSimdReg].fGstRegShadows != 0, ("idxSimdReg=%#x\n", idxSimdReg));
     5425
     5426#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     5427            /*
     5428             * Flush any pending writes now (might have been skipped earlier in iemEmitCallCommon() but it doesn't apply
     5429             * to call volatile registers).
     5430             */
     5431            if (  (pReNative->Core.bmGstSimdRegShadowDirtyLo128 | pReNative->Core.bmGstSimdRegShadowDirtyHi128)
     5432                & pReNative->Core.aHstSimdRegs[idxSimdReg].fGstRegShadows)
     5433                off = iemNativeSimdRegFlushDirtyGuestByHostSimdRegShadow(pReNative, off, idxSimdReg);
     5434#endif
    54205435            Assert(!(  (pReNative->Core.bmGstSimdRegShadowDirtyLo128 | pReNative->Core.bmGstSimdRegShadowDirtyHi128)
    54215436                     & pReNative->Core.aHstSimdRegs[idxSimdReg].fGstRegShadows));
     
    55515566
    55525567            AssertMsg(pReNative->Core.aHstRegs[idxReg].fGstRegShadows != 0, ("idxReg=%#x\n", idxReg));
     5568
    55535569#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     5570            /*
     5571             * Flush any pending writes now (might have been skipped earlier in iemEmitCallCommon() but it doesn't apply
     5572             * to call volatile registers).
     5573             */
     5574            if (pReNative->Core.bmGstRegShadowDirty & pReNative->Core.aHstRegs[idxReg].fGstRegShadows)
     5575                off = iemNativeRegFlushDirtyGuestByHostRegShadow(pReNative, off, idxReg);
    55545576            Assert(!(pReNative->Core.bmGstRegShadowDirty & pReNative->Core.aHstRegs[idxReg].fGstRegShadows));
    55555577#endif
     5578
    55565579            pReNative->Core.bmGstRegShadows &= ~pReNative->Core.aHstRegs[idxReg].fGstRegShadows;
    55575580            pReNative->Core.aHstRegs[idxReg].fGstRegShadows = 0;
     
    58865909    return off;
    58875910}
     5911
     5912
     5913#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     5914/**
     5915 * Flush all shadowed guest SIMD registers marked as dirty for the given host SIMD register.
     5916 *
     5917 * @returns New code buffer offset.
     5918 * @param   pReNative       The native recompile state.
     5919 * @param   off             Current code buffer position.
     5920 * @param   idxHstSimdReg   The host SIMD register.
     5921 *
     5922 * @note This doesn't do any unshadowing of guest registers from the host register.
     5923 */
     5924DECL_HIDDEN_THROW(uint32_t) iemNativeSimdRegFlushDirtyGuestByHostSimdRegShadow(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t const idxHstSimdReg)
     5925{
     5926    /* We need to flush any pending guest register writes this host register shadows. */
     5927    uint64_t bmGstSimdRegShadowDirty =   (pReNative->Core.bmGstSimdRegShadowDirtyLo128 | pReNative->Core.bmGstSimdRegShadowDirtyHi128)
     5928                                       & pReNative->Core.aHstSimdRegs[idxHstSimdReg].fGstRegShadows;
     5929    if (bmGstSimdRegShadowDirty)
     5930    {
     5931# ifdef IEMNATIVE_WITH_TB_DEBUG_INFO
     5932        iemNativeDbgInfoAddNativeOffset(pReNative, off);
     5933        iemNativeDbgInfoAddGuestRegWriteback(pReNative, true /*fSimdReg*/, bmGstSimdRegShadowDirty);
     5934# endif
     5935
     5936        uint32_t idxGstSimdReg = 0;
     5937        do
     5938        {
     5939            if (bmGstSimdRegShadowDirty & 0x1)
     5940                off = iemNativeSimdRegFlushPendingWrite(pReNative, off, IEMNATIVEGSTSIMDREG_SIMD(idxGstSimdReg));
     5941
     5942            idxGstSimdReg++;
     5943            bmGstSimdRegShadowDirty >>= 1;
     5944        } while (bmGstSimdRegShadowDirty);
     5945    }
     5946
     5947    return off;
     5948}
     5949#endif
    58885950
    58895951
     
    66746736 * the guest state (like raising exceptions) and such.
    66756737 *
    6676  * This optimization has not yet been implemented.  The first target would be
    6677  * RIP updates, since these are the most common ones.
    6678  *
    66796738 * @note This function does not flush any shadowing information for guest registers. This needs to be done by
    66806739 *       the caller if it wishes to do so.
     
    91039162 *                          them, whereas all the regular arguments must
    91049163 *                          (tstIEMCheckMc ensures this).
     9164 * @param   fFlushPendingWrites Flag whether to flush pending writes (default true),
     9165 *                              this will still flush pending writes in call volatile registers if false.
    91059166 */
    91069167DECL_HIDDEN_THROW(uint32_t)
    9107 iemNativeEmitCallCommon(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t cArgs, uint8_t cHiddenArgs)
     9168iemNativeEmitCallCommon(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t cArgs, uint8_t cHiddenArgs, bool fFlushPendingWrites /*= true*/)
    91089169{
    91099170#ifdef VBOX_STRICT
     
    91249185
    91259186    /* We don't know what the called function makes use of, so flush any pending register writes. */
    9126     off = iemNativeRegFlushPendingWrites(pReNative, off);
     9187#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     9188    if (fFlushPendingWrites)
     9189#endif
     9190        off = iemNativeRegFlushPendingWrites(pReNative, off);
    91279191
    91289192    /*
     
    91909254
    91919255    uint8_t const cRegArgs = RT_MIN(cArgs, RT_ELEMENTS(g_aidxIemNativeCallRegs));
     9256
     9257#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     9258    /*
     9259     * At the very first step go over the host registers that will be used for arguments
     9260     * don't shadow anything which needs writing back first.
     9261     */
     9262    for (uint32_t i = 0; i < cRegArgs; i++)
     9263    {
     9264        uint8_t const idxArgReg = g_aidxIemNativeCallRegs[i];
     9265
     9266        /* Writeback any dirty guest shadows before using this register. */
     9267        if (pReNative->Core.bmGstRegShadowDirty & pReNative->Core.aHstRegs[idxArgReg].fGstRegShadows)
     9268            off = iemNativeRegFlushDirtyGuestByHostRegShadow(pReNative, off, idxArgReg);
     9269        Assert(!(pReNative->Core.bmGstRegShadowDirty & pReNative->Core.aHstRegs[idxArgReg].fGstRegShadows));
     9270    }
     9271#endif
    91929272
    91939273    /*
  • trunk/src/VBox/VMM/include/IEMN8veRecompiler.h

    r104073 r104084  
    15711571#ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
    15721572DECLHIDDEN(void)            iemNativeSimdRegFreeVar(PIEMRECOMPILERSTATE pReNative, uint8_t idxHstSimdReg, bool fFlushShadows) RT_NOEXCEPT;
     1573# ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     1574DECL_HIDDEN_THROW(uint32_t) iemNativeSimdRegFlushDirtyGuestByHostSimdRegShadow(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxHstReg);
     1575# endif
    15731576#endif
    15741577DECLHIDDEN(void)            iemNativeRegFreeAndFlushMask(PIEMRECOMPILERSTATE pReNative, uint32_t fHstRegMask) RT_NOEXCEPT;
     
    16551658#endif
    16561659DECL_HIDDEN_THROW(uint32_t) iemNativeEmitCheckCallRetAndPassUp(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxInstr);
    1657 DECL_HIDDEN_THROW(uint32_t) iemNativeEmitCallCommon(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t cArgs, uint8_t cHiddenArgs);
     1660DECL_HIDDEN_THROW(uint32_t) iemNativeEmitCallCommon(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t cArgs, uint8_t cHiddenArgs, bool fFlushPendingWrites = true);
    16581661DECL_HIDDEN_THROW(uint32_t) iemNativeEmitCImplCall(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxInstr,
    16591662                                                   uint64_t fGstShwFlush, uintptr_t pfnCImpl, uint8_t cbInstr, uint8_t cAddParams,
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