VirtualBox

Changeset 101163 in vbox


Ignore:
Timestamp:
Sep 18, 2023 8:44:24 PM (12 months ago)
Author:
vboxsync
Message:

VMM/IEM: Experimental recompilation of threaded blocks into native code on linux.amd64. bugref:10370

Location:
trunk/src/VBox/VMM
Files:
1 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/Config.kmk

    r100109 r101163  
    7070ifdef VBOX_WITH_IEM_RECOMPILER # Selectely removing hwvirt doesn't work yet with the recompiler. Python code doesn't check #ifdefs.
    7171 VMM_COMMON_DEFS += VBOX_WITH_IEM_RECOMPILER IEM_WITH_CODE_TLB IEM_WITH_DATA_TLB
     72 ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
     73  VMM_COMMON_DEFS += VBOX_WITH_IEM_NATIVE_RECOMPILER
     74 endif
    7275 VMM_COMMON_DEFS += VBOX_WITH_NESTED_HWVIRT_VMX
    7376 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT # Busted with TLB enabled.
  • trunk/src/VBox/VMM/Makefile.kmk

    r101103 r101163  
    258258        VMMAll/IEMAllThrdFuncs.cpp \
    259259        VMMAll/IEMAllThrdFuncsBltIn.cpp
     260 ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
     261  VBoxVMM_SOURCES += \
     262        VMMAll/IEMAllN8veRecompiler.cpp
     263 endif
    260264 VMMAll/IEMAllThrdFuncs.cpp_CXXFLAGS.win = /bigobj
    261265endif
  • trunk/src/VBox/VMM/VMMAll/IEMAllThrdFuncsBltIn.cpp

    r100829 r101163  
    7373static VBOXSTRICTRC iemThreadeFuncWorkerObsoleteTb(PVMCPUCC pVCpu)
    7474{
    75     iemThreadedTbObsolete(pVCpu, pVCpu->iem.s.pCurTbR3);
     75    /* We set fSafeToFree to false where as we're being called in the context
     76       of a TB callback function, which for native TBs means we cannot release
     77       the executable memory till we've returned our way back to iemTbExec as
     78       that return path codes via the native code generated for the TB. */
     79    iemThreadedTbObsolete(pVCpu, pVCpu->iem.s.pCurTbR3, false /*fSafeToFree*/);
    7680    return VINF_IEM_REEXEC_BREAK;
    7781}
  • trunk/src/VBox/VMM/VMMAll/IEMAllThrdRecompiler.cpp

    r101111 r101163  
    115115*   Internal Functions                                                                                                           *
    116116*********************************************************************************************************************************/
    117 static VBOXSTRICTRC iemThreadedTbExec(PVMCPUCC pVCpu, PIEMTB pTb);
    118117static void         iemTbAllocatorFree(PVMCPUCC pVCpu, PIEMTB pTb);
    119118
     
    650649                if (pTb->x86.fAttr == (uint16_t)pVCpu->cpum.GstCtx.cs.Attr.u)
    651650                {
    652                     pTb->cUsed++;
    653                     pTb->msLastUsed = pVCpu->iem.s.msRecompilerPollNow;
    654651                    STAM_COUNTER_INC(&pTbCache->cLookupHits);
    655652                    AssertMsg(cLeft > 0, ("%d\n", cLeft));
     653
     654                    pTb->msLastUsed = pVCpu->iem.s.msRecompilerPollNow;
     655                    pTb->cUsed++;
     656#ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
     657                    if ((pTb->fFlags & IEMTB_F_TYPE_NATIVE) || pTb->cUsed != 16)
     658                        return pTb;
     659                    return iemNativeRecompile(pVCpu, pTb);
     660#else
    656661                    return pTb;
     662#endif
    657663                }
    658664                Log11(("TB miss: CS: %#x, wanted %#x\n", pTb->x86.fAttr, (uint16_t)pVCpu->cpum.GstCtx.cs.Attr.u));
     
    706712 *
    707713 * @returns VBox status code.
    708  * @param   pVM         The VM handle.
    709  * @param   cInitialTbs The initial number of translation blocks to
    710  *                      preallocator.
    711  * @param   cMaxTbs     The max number of translation blocks allowed.
     714 * @param   pVM             The VM handle.
     715 * @param   cInitialTbs     The initial number of translation blocks to
     716 *                          preallocator.
     717 * @param   cMaxTbs         The max number of translation blocks allowed.
     718 * @param   cbInitialExec   The initial size of the executable memory allocator.
     719 * @param   cbMaxExec       The max size of the executable memory allocator.
     720 * @param   cbChunkExec     The chunk size for executable memory allocator. Zero
     721 *                          or UINT32_MAX for automatically determining this.
    712722 * @thread  EMT
    713723 */
    714 DECLCALLBACK(int) iemTbInit(PVMCC pVM, uint32_t cInitialTbs, uint32_t cMaxTbs)
     724DECLCALLBACK(int) iemTbInit(PVMCC pVM, uint32_t cInitialTbs, uint32_t cMaxTbs,
     725                            uint64_t cbInitialExec, uint64_t cbMaxExec, uint32_t cbChunkExec)
    715726{
    716727    PVMCPUCC pVCpu = VMMGetCpu(pVM);
     
    820831    pVCpu->iem.s.pTbCacheR3 = pTbCache;
    821832
     833    /*
     834     * Initialize the native executable memory allocator.
     835     */
     836#ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
     837    int rc = iemExecMemAllocatorInit(pVCpu, cbMaxExec, cbInitialExec, cbChunkExec);
     838    AssertLogRelRCReturn(rc, rc);
     839#else
     840    RT_NOREF(cbMaxExec, cbInitialExec, cbChunkExec);
     841#endif
     842
    822843    return VINF_SUCCESS;
    823844}
     
    849870            RTMemFree(pTb->Thrd.paCalls);
    850871            break;
     872#ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
    851873        case IEMTB_F_TYPE_NATIVE:
    852874            pTbAllocator->cNativeTbs -= 1;
    853             RTMemFree(pTb->Native.pbCode); /// @todo native: fix me
     875            iemExecMemAllocatorFree(pVCpu, pTb->Native.paInstructions,
     876                                    pTb->Native.cInstructions * sizeof(pTb->Native.paInstructions[0]));
    854877            break;
     878#endif
    855879        default:
    856880            AssertFailed();
     
    880904 * @param   pVCpu   The cross context virtual CPU structure of the calling
    881905 *                  thread.
    882  * @param   pTb     The translation block to free..
     906 * @param   pTb     The translation block to free.
    883907 * @thread  EMT(pVCpu)
    884908 */
     
    899923     */
    900924    iemTbAllocatorFreeInner(pVCpu, pTbAllocator, pTb, idxChunk, (uint32_t)idxInChunk);
     925}
     926
     927
     928/**
     929 * Schedules a native TB for freeing when it's not longer being executed and
     930 * part of the caller's call stack.
     931 *
     932 * The TB will be removed from the translation block cache, though, so it isn't
     933 * possible to executed it again and the IEMTB::pNext member can be used to link
     934 * it together with other TBs awaiting freeing.
     935 *
     936 * @param   pVCpu   The cross context virtual CPU structure of the calling
     937 *                  thread.
     938 * @param   pTb     The translation block to schedule for freeing.
     939 */
     940static void iemTbAlloctorScheduleForFree(PVMCPUCC pVCpu, PIEMTB pTb)
     941{
     942    /*
     943     * Validate state.
     944     */
     945    PIEMTBALLOCATOR const pTbAllocator = pVCpu->iem.s.pTbAllocatorR3;
     946    Assert(pTbAllocator && pTbAllocator->uMagic == IEMTBALLOCATOR_MAGIC);
     947    Assert(pTb->idxAllocChunk < pTbAllocator->cAllocatedChunks);
     948    Assert((uintptr_t)(pTb - pTbAllocator->aChunks[pTb->idxAllocChunk].paTbs) < pTbAllocator->cTbsPerChunk);
     949    Assert(ASMBitTest(&pTbAllocator->bmAllocated,
     950                      IEMTBALLOC_IDX_MAKE(pTbAllocator, pTb->idxAllocChunk,
     951                                          (uintptr_t)(pTb - pTbAllocator->aChunks[pTb->idxAllocChunk].paTbs))));
     952    Assert((pTb->fFlags & IEMTB_F_TYPE_MASK) == IEMTB_F_TYPE_NATIVE);
     953
     954    /*
     955     * Remove it from the cache and prepend it to the allocator's todo list.
     956     */
     957    iemTbCacheRemove(pVCpu->iem.s.pTbCacheR3, pTb);
     958
     959    pTb->pNext = pTbAllocator->pDelayedFreeHead;
     960    pTbAllocator->pDelayedFreeHead = pTb;
     961}
     962
     963
     964/**
     965 * Processes the delayed frees.
     966 *
     967 * This is called by the allocator function as well as the native recompile
     968 * function before making any TB or executable memory allocations respectively.
     969 */
     970void iemTbAllocatorProcessDelayedFrees(PVMCPU pVCpu, PIEMTBALLOCATOR pTbAllocator)
     971{
     972    PIEMTB pTb = pTbAllocator->pDelayedFreeHead;
     973    pTbAllocator->pDelayedFreeHead = NULL;
     974    while (pTb)
     975    {
     976        PIEMTB const pTbNext = pTb->pNext;
     977        Assert(pVCpu->iem.s.pCurTbR3 != pTb);
     978        iemTbAlloctorScheduleForFree(pVCpu, pTb);
     979        pTb = pTbNext;
     980    }
    901981}
    902982
     
    10781158    Assert(pTbAllocator && pTbAllocator->uMagic == IEMTBALLOCATOR_MAGIC);
    10791159
     1160    /* Free any pending TBs before we proceed. */
     1161    if (!pTbAllocator->pDelayedFreeHead)
     1162    { /* probably likely */ }
     1163    else
     1164        iemTbAllocatorProcessDelayedFrees(pVCpu, pTbAllocator);
     1165
    10801166    /* If the allocator is full, take slow code path.*/
    10811167    if (RT_LIKELY(pTbAllocator->cInUseTbs < pTbAllocator->cTotalTbs))
     
    10841170}
    10851171
     1172
     1173
     1174/*********************************************************************************************************************************
     1175*   Threaded Recompiler Core                                                                                                     *
     1176*********************************************************************************************************************************/
    10861177
    10871178/**
     
    12581349 * Called by opcode verifier functions when they detect a problem.
    12591350 */
    1260 void iemThreadedTbObsolete(PVMCPUCC pVCpu, PIEMTB pTb)
    1261 {
    1262     iemTbAllocatorFree(pVCpu, pTb);
     1351void iemThreadedTbObsolete(PVMCPUCC pVCpu, PIEMTB pTb, bool fSafeToFree)
     1352{
     1353    /* Unless it's safe, we can only immediately free threaded TB, as we will
     1354       have more code left to execute in native TBs when fSafeToFree == false.  */
     1355    if (fSafeToFree || (pTb->fFlags & IEMTB_F_TYPE_THREADED))
     1356        iemTbAllocatorFree(pVCpu, pTb);
     1357    else
     1358        iemTbAlloctorScheduleForFree(pVCpu, pTb);
    12631359}
    12641360
     
    21132209
    21142210
     2211
     2212/*********************************************************************************************************************************
     2213*   Recompiled Execution Core                                                                                                    *
     2214*********************************************************************************************************************************/
     2215
    21152216/**
    21162217 * Executes a translation block.
     
    21212222 * @param   pTb     The translation block to execute.
    21222223 */
    2123 static VBOXSTRICTRC iemThreadedTbExec(PVMCPUCC pVCpu, PIEMTB pTb) IEM_NOEXCEPT_MAY_LONGJMP
    2124 {
    2125     /* Check the opcodes in the first page before starting execution. */
     2224static VBOXSTRICTRC iemTbExec(PVMCPUCC pVCpu, PIEMTB pTb) IEM_NOEXCEPT_MAY_LONGJMP
     2225{
     2226    /*
     2227     * Check the opcodes in the first page before starting execution.
     2228     */
    21262229    Assert(!(pVCpu->iem.s.GCPhysInstrBuf & (RTGCPHYS)GUEST_PAGE_OFFSET_MASK));
    21272230    Assert(pTb->aRanges[0].cbOpcodes <= pVCpu->iem.s.cbInstrBufTotal - pVCpu->iem.s.offInstrNextByte);
     
    21312234    {
    21322235        Log7(("TB obsolete: %p GCPhys=%RGp\n", pTb, pTb->GCPhysPc));
    2133         iemThreadedTbObsolete(pVCpu, pTb);
     2236        iemThreadedTbObsolete(pVCpu, pTb, true /*fSafeToFree*/);
    21342237        return VINF_SUCCESS;
    21352238    }
    21362239
    2137     /* Set the current TB so CIMPL function may get at it. */
     2240    /*
     2241     * Set the current TB so CIMPL functions may get at it.
     2242     */
    21382243    pVCpu->iem.s.pCurTbR3 = pTb;
    2139     pVCpu->iem.s.cTbExec++;
    2140 
    2141     /* The execution loop. */
    2142 #ifdef LOG_ENABLED
    2143     uint64_t             uRipPrev   = UINT64_MAX;
    2144 #endif
    2145     PCIEMTHRDEDCALLENTRY pCallEntry = pTb->Thrd.paCalls;
    2146     uint32_t             cCallsLeft = pTb->Thrd.cCalls;
    2147     while (cCallsLeft-- > 0)
    2148     {
    2149 #ifdef LOG_ENABLED
    2150         if (pVCpu->cpum.GstCtx.rip != uRipPrev)
    2151         {
    2152             uRipPrev = pVCpu->cpum.GstCtx.rip;
    2153             iemThreadedLogCurInstr(pVCpu, "EX");
    2154         }
    2155         Log9(("%04x:%08RX64: #%d/%d - %d %s\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
    2156               pTb->Thrd.cCalls - cCallsLeft - 1, pCallEntry->idxInstr, pCallEntry->enmFunction,
    2157               g_apszIemThreadedFunctions[pCallEntry->enmFunction]));
    2158 #endif
    2159         VBOXSTRICTRC const rcStrict = g_apfnIemThreadedFunctions[pCallEntry->enmFunction](pVCpu,
    2160                                                                                           pCallEntry->auParams[0],
    2161                                                                                           pCallEntry->auParams[1],
    2162                                                                                           pCallEntry->auParams[2]);
     2244
     2245    /*
     2246     * Execute the block.
     2247     */
     2248#ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
     2249    if (pTb->fFlags & IEMTB_F_TYPE_NATIVE)
     2250    {
     2251        pVCpu->iem.s.cTbExecNative++;
     2252        typedef IEM_DECL_IMPL_TYPE(int, FNIEMNATIVETB, (PVMCPUCC pVCpu, PIEMTB pTb));
     2253# ifdef LOG_ENABLED
     2254        iemThreadedLogCurInstr(pVCpu, "EXn");
     2255# endif
     2256        VBOXSTRICTRC const rcStrict = ((FNIEMNATIVETB *)pTb->Native.paInstructions)(pVCpu, pTb);
    21632257        if (RT_LIKELY(   rcStrict == VINF_SUCCESS
    21642258                      && pVCpu->iem.s.rcPassUp == VINF_SUCCESS /** @todo this isn't great. */))
    2165             pCallEntry++;
     2259        { /* likely */ }
    21662260        else
    21672261        {
    2168             pVCpu->iem.s.cInstructions += pCallEntry->idxInstr; /* This may be one short, but better than zero. */
    2169             pVCpu->iem.s.pCurTbR3       = NULL;
     2262            /* pVCpu->iem.s.cInstructions is incremented by iemNativeHlpExecStatusCodeFiddling. */
     2263            pVCpu->iem.s.pCurTbR3 = NULL;
    21702264            STAM_REL_COUNTER_INC(&pVCpu->iem.s.StatTbExecBreaks);
    21712265
    2172             /* Some status codes are just to get us out of this loop and
    2173                continue in a different translation block. */
     2266            /* VINF_IEM_REEXEC_BREAK should be treated as VINF_SUCCESS as it's
     2267               only to break out of TB execution early. */
    21742268            if (rcStrict == VINF_IEM_REEXEC_BREAK)
    21752269                return iemExecStatusCodeFiddling(pVCpu, VINF_SUCCESS);
    21762270            return iemExecStatusCodeFiddling(pVCpu, rcStrict);
     2271        }
     2272    }
     2273    else
     2274#endif /* VBOX_WITH_IEM_NATIVE_RECOMPILER */
     2275    {
     2276        /*
     2277         * The threaded execution loop.
     2278         */
     2279        pVCpu->iem.s.cTbExecThreaded++;
     2280#ifdef LOG_ENABLED
     2281        uint64_t             uRipPrev   = UINT64_MAX;
     2282#endif
     2283        PCIEMTHRDEDCALLENTRY pCallEntry = pTb->Thrd.paCalls;
     2284        uint32_t             cCallsLeft = pTb->Thrd.cCalls;
     2285        while (cCallsLeft-- > 0)
     2286        {
     2287#ifdef LOG_ENABLED
     2288            if (pVCpu->cpum.GstCtx.rip != uRipPrev)
     2289            {
     2290                uRipPrev = pVCpu->cpum.GstCtx.rip;
     2291                iemThreadedLogCurInstr(pVCpu, "EXt");
     2292            }
     2293            Log9(("%04x:%08RX64: #%d/%d - %d %s\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
     2294                  pTb->Thrd.cCalls - cCallsLeft - 1, pCallEntry->idxInstr, pCallEntry->enmFunction,
     2295                  g_apszIemThreadedFunctions[pCallEntry->enmFunction]));
     2296#endif
     2297            VBOXSTRICTRC const rcStrict = g_apfnIemThreadedFunctions[pCallEntry->enmFunction](pVCpu,
     2298                                                                                              pCallEntry->auParams[0],
     2299                                                                                              pCallEntry->auParams[1],
     2300                                                                                              pCallEntry->auParams[2]);
     2301            if (RT_LIKELY(   rcStrict == VINF_SUCCESS
     2302                          && pVCpu->iem.s.rcPassUp == VINF_SUCCESS /** @todo this isn't great. */))
     2303                pCallEntry++;
     2304            else
     2305            {
     2306                pVCpu->iem.s.cInstructions += pCallEntry->idxInstr; /* This may be one short, but better than zero. */
     2307                pVCpu->iem.s.pCurTbR3       = NULL;
     2308                STAM_REL_COUNTER_INC(&pVCpu->iem.s.StatTbExecBreaks);
     2309
     2310                /* VINF_IEM_REEXEC_BREAK should be treated as VINF_SUCCESS as it's
     2311                   only to break out of TB execution early. */
     2312                if (rcStrict == VINF_IEM_REEXEC_BREAK)
     2313                    return iemExecStatusCodeFiddling(pVCpu, VINF_SUCCESS);
     2314                return iemExecStatusCodeFiddling(pVCpu, rcStrict);
     2315            }
    21772316        }
    21782317    }
     
    23202459                pTb = iemTbCacheLookup(pVCpu, pTbCache, GCPhysPc, fExtraFlags);
    23212460                if (pTb)
    2322                 {
    2323                     if (pTb->fFlags & IEMTB_F_TYPE_THREADED)
    2324                         rcStrict = iemThreadedTbExec(pVCpu, pTb);
    2325                     else
    2326                         AssertFailedStmt(rcStrict = VERR_INTERNAL_ERROR_4);
    2327                 }
     2461                    rcStrict = iemTbExec(pVCpu, pTb);
    23282462                else
    23292463                    rcStrict = iemThreadedCompile(pVM, pVCpu, GCPhysPc, fExtraFlags);
     
    23462480                        if (RT_LIKELY(   (iIterations & cPollRate) != 0
    23472481                                      || !TMTimerPollBoolWith32BitMilliTS(pVM, pVCpu, &pVCpu->iem.s.msRecompilerPollNow)))
    2348                         {
    2349 
    2350                         }
     2482                            pTb = NULL; /* Clear it before looping so iemTbCacheLookup can safely do native recompilation. */
    23512483                        else
    23522484                            return VINF_SUCCESS;
     
    23652497                iemMemRollback(pVCpu);
    23662498
    2367 #if 0 /** @todo do we need to clean up anything? */
    2368             /* If pTb isn't NULL we're in iemThreadedTbExec. */
     2499#if 0 /** @todo do we need to clean up anything?  If not, we can drop the pTb = NULL some lines up and change the scope. */
     2500            /* If pTb isn't NULL we're in iemTbExec. */
    23692501            if (!pTb)
    23702502            {
  • trunk/src/VBox/VMM/VMMR3/IEMR3.cpp

    r101096 r101163  
    140140                          "InitialTbCount value %u (%#x) is higher than the MaxTbCount value %u (%#x)",
    141141                          cInitialTbs, cInitialTbs, cMaxTbs, cMaxTbs);
    142 #endif
     142
     143    /** @cfgm{/IEM/MaxExecMem, uint64_t, 512 MiB}
     144     * Max executable memory for recompiled code per EMT. */
     145    uint64_t cbMaxExec = 0;
     146    rc = CFGMR3QueryU64Def(pIem, "MaxExecMem", &cbMaxExec, _512M);
     147    AssertLogRelRCReturn(rc, rc);
     148    if (cbMaxExec < _1M || cbMaxExec > 16*_1G64)
     149        return VMSetError(pVM, VERR_OUT_OF_RANGE, RT_SRC_POS,
     150                          "MaxExecMem value %'RU64 (%#RX64) is out of range (min %'RU64, max %'RU64)",
     151                          cbMaxExec, cbMaxExec, (uint64_t)_1M, 16*_1G64);
     152
     153    /** @cfgm{/IEM/ExecChunkSize, uint32_t, 0 (auto)}
     154     * The executable memory allocator chunk size. */
     155    uint32_t cbChunkExec = 0;
     156    rc = CFGMR3QueryU32Def(pIem, "ExecChunkSize", &cbChunkExec, 0);
     157    AssertLogRelRCReturn(rc, rc);
     158    if (cbChunkExec != 0 && cbChunkExec != UINT32_MAX && (cbChunkExec < _1M || cbChunkExec > _256M))
     159        return VMSetError(pVM, VERR_OUT_OF_RANGE, RT_SRC_POS,
     160                          "ExecChunkSize value %'RU32 (%#RX32) is out of range (min %'RU32, max %'RU32)",
     161                          cbChunkExec, cbChunkExec, _1M, _256M);
     162
     163    /** @cfgm{/IEM/InitialExecMemSize, uint64_t, 1}
     164     * The initial executable memory allocator size (per EMT).  The value is
     165     * rounded up to the nearest chunk size, so 1 byte means one chunk. */
     166    uint64_t cbInitialExec = 0;
     167    rc = CFGMR3QueryU64Def(pIem, "InitialExecMemSize", &cbInitialExec, 0);
     168    AssertLogRelRCReturn(rc, rc);
     169    if (cbInitialExec > cbMaxExec)
     170        return VMSetError(pVM, VERR_OUT_OF_RANGE, RT_SRC_POS,
     171                          "InitialExecMemSize value %'RU64 (%#RX64) is out of range (max %'RU64)",
     172                          cbInitialExec, cbInitialExec, cbMaxExec);
     173
     174#endif /* VBOX_WITH_IEM_RECOMPILER*/
    143175
    144176    /*
     
    228260     * the allocations.
    229261     */
    230     rc = VMR3ReqCallWait(pVM, VMCPUID_ALL, (PFNRT)iemTbInit, 3, pVM, cInitialTbs, cMaxTbs);
     262    rc = VMR3ReqCallWait(pVM, VMCPUID_ALL, (PFNRT)iemTbInit, 6,
     263                         pVM, cInitialTbs, cMaxTbs, cbInitialExec, cbMaxExec, cbChunkExec);
    231264    AssertLogRelRCReturn(rc, rc);
    232265#endif
     
    286319
    287320#ifdef VBOX_WITH_IEM_RECOMPILER
    288         STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.cTbExec,             STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
    289                         "Executed translation block",                   "/IEM/CPU%u/re/cTbExec", idCpu);
     321        STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.cTbExecNative,       STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
     322                        "Executed native translation block",            "/IEM/CPU%u/re/cTbExecNative", idCpu);
     323        STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.cTbExecThreaded,     STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
     324                        "Executed threaded translation block",          "/IEM/CPU%u/re/cTbExecThreaded", idCpu);
    290325        STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTbExecBreaks,    STAMTYPE_COUNTER,   STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
    291326                        "Times TB execution was interrupted/broken off", "/IEM/CPU%u/re/cTbExecBreaks", idCpu);
  • trunk/src/VBox/VMM/include/IEMInline.h

    r100998 r101163  
    332332}
    333333
     334#ifdef VBOX_INCLUDED_vmm_dbgf_h /* VM::dbgf.ro.cEnabledHwBreakpoints is only accessible if VBox/vmm/dbgf.h is included. */
    334335
    335336/**
     
    392393}
    393394
     395#endif /* VBOX_INCLUDED_vmm_dbgf_h */
     396
    394397
    395398#ifndef IEM_WITH_OPAQUE_DECODER_STATE
    396399
    397400# if defined(VBOX_INCLUDED_vmm_dbgf_h) || defined(DOXYGEN_RUNNING) /* dbgf.ro.cEnabledHwBreakpoints */
     401
    398402/**
    399403 * Initializes the execution state.
     
    458462#  endif /* VBOX_STRICT */
    459463}
    460 # endif /* VBOX_INCLUDED_vmm_dbgf_h */
    461 
    462 
    463 # if defined(VBOX_WITH_NESTED_HWVIRT_SVM) || defined(VBOX_WITH_NESTED_HWVIRT_VMX)
     464
     465
     466#  if defined(VBOX_WITH_NESTED_HWVIRT_SVM) || defined(VBOX_WITH_NESTED_HWVIRT_VMX)
    464467/**
    465468 * Performs a minimal reinitialization of the execution state.
     
    477480    iemOpcodeFlushHeavy(pVCpu, cbInstr);
    478481}
    479 # endif
    480 
     482#  endif
     483
     484# endif /* VBOX_INCLUDED_vmm_dbgf_h || DOXYGEN_RUNNING */
    481485
    482486/**
     
    35643568
    35653569
     3570# ifdef XAPIC_OFF_END /* Requires VBox/apic.h to be included before IEMInline.h. */
    35663571/**
    35673572 * Sets virtual-APIC write emulation as pending.
     
    35883593        VMCPU_FF_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE);
    35893594}
     3595# endif /* XAPIC_OFF_END */
    35903596
    35913597#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
  • trunk/src/VBox/VMM/include/IEMInternal.h

    r101111 r101163  
    742742AssertCompile(!(IEM_F_MODE_X86_64BIT              & IEM_F_MODE_X86_FLAT_OR_PRE_386_MASK));
    743743
     744/** Native instruction type for use with the native code generator.
     745 * This is a byte (uint8_t) for x86 and amd64 and uint32_t for the other(s). */
     746#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     747typedef uint8_t IEMNATIVEINSTR;
     748#else
     749typedef uint32_t IEMNATIVEINSTR;
     750#endif
     751/** Pointer to a native instruction unit. */
     752typedef IEMNATIVEINSTR *PIEMNATIVEINSTR;
     753
    744754/**
    745755 * A call for the threaded call table.
     
    826836        struct
    827837        {
    828             uint8_t            *pbCode;
    829             /** Amount of code that pbCode points to. */
    830             uint32_t            cbAllocated;
     838            /** The native instructions. */
     839            PIEMNATIVEINSTR     paInstructions;
     840            /** Number of instructions pointed to by paInstructions. */
     841            uint32_t            cInstructions;
    831842        } Native;
    832843        /** Generic view for zeroing when freeing. */
     
    974985    /** Statistics: Time spend pruning. */
    975986    STAMPROFILE     StatPrune;
     987
     988    /** The delayed free list (see iemTbAlloctorScheduleForFree). */
     989    PIEMTB          pDelayedFreeHead;
    976990
    977991    /** Allocation chunks. */
     
    13681382     * This is allocated once with maxed-out sizes and re-used afterwards. */
    13691383    R3PTRTYPE(PIEMTB)       pThrdCompileTbR3;
    1370     /** Fixed TB used for native recompilation.
    1371      * This is allocated once and re-used afterwards, growing individual
    1372      * components as needed. */
    1373     R3PTRTYPE(PIEMTB)       pNativeCompileTbR3;
    13741384    /** Pointer to the ring-3 TB cache for this EMT. */
    13751385    R3PTRTYPE(PIEMTBCACHE)  pTbCacheR3;
     
    13781388     * RIP to opcode bytes stored in the TB (AMD-V / VT-x). */
    13791389    uint64_t                uCurTbStartPc;
    1380     /** Number of TBs executed. */
    1381     uint64_t                cTbExec;
     1390    /** Number of threaded TBs executed. */
     1391    uint64_t                cTbExecThreaded;
     1392    /** Number of native TBs executed. */
     1393    uint64_t                cTbExecNative;
    13821394    /** Whether we need to check the opcode bytes for the current instruction.
    13831395     * This is set by a previous instruction if it modified memory or similar.  */
     
    14141426    /** Pointer to the ring-3 TB allocator for this EMT. */
    14151427    R3PTRTYPE(PIEMTBALLOCATOR) pTbAllocatorR3;
    1416     /* Alignment. */
    1417     uint64_t                auAlignment10[7];
     1428    /** Pointer to the ring-3 executable memory allocator for this EMT. */
     1429    R3PTRTYPE(struct IEMEXECMEMALLOCATOR *) pExecMemAllocatorR3;
     1430
     1431    /** Native recompiler state for ring-3. */
     1432    struct IEMRECOMPILERSTATE
     1433    {
     1434        /** Size of the buffer that pbNativeRecompileBufR3 points to in
     1435         * IEMNATIVEINSTR units. */
     1436        uint32_t                            cInstrBufAlloc;
     1437        uint32_t                            uPadding; /* We don't keep track of this here... */
     1438        /** Fixed temporary code buffer for native recompilation. */
     1439        R3PTRTYPE(PIEMNATIVEINSTR)          pInstrBuf;
     1440
     1441        /** Actual number of labels in paLabels. */
     1442        uint32_t                            cLabels;
     1443        /** Max number of entries allowed in paLabels before reallocating it. */
     1444        uint32_t                            cLabelsAlloc;
     1445        /** Labels defined while recompiling (referenced by fixups). */
     1446        R3PTRTYPE(struct IEMNATIVELABEL *)  paLabels;
     1447
     1448        /** Actual number of fixups paFixups. */
     1449        uint32_t                            cFixups;
     1450        /** Max number of entries allowed in paFixups before reallocating it. */
     1451        uint32_t                            cFixupsAlloc;
     1452        /** Buffer used by the recompiler for recording fixups when generating code. */
     1453        R3PTRTYPE(struct IEMNATIVEFIXUP *)  paFixups;
     1454    } Native;
     1455
     1456//    /* Alignment. */
     1457//    uint64_t                auAlignment10[1];
    14181458    /** Statistics: Times TB execution was broken off before reaching the end. */
    14191459    STAMCOUNTER             StatTbExecBreaks;
     
    14301470    /** Threaded TB statistics: Number of calls per TB. */
    14311471    STAMPROFILE             StatTbThreadedCalls;
     1472    /** Native TB statistics: Native code size per TB. */
     1473    STAMPROFILE             StatTbNativeCode;
     1474    /** Native TB statistics: Profiling native recompilation. */
     1475    STAMPROFILE             StatNativeRecompilation;
    14321476    /** @} */
    14331477
     
    52905334extern const PFNIEMOP g_apfnIemThreadedRecompilerVecMap3[1024];
    52915335
    5292 DECLCALLBACK(int) iemTbInit(PVMCC pVM, uint32_t cInitialTbs, uint32_t cMaxTbs);
    5293 void            iemThreadedTbObsolete(PVMCPUCC pVCpu, PIEMTB pTb);
     5336DECLCALLBACK(int)   iemTbInit(PVMCC pVM, uint32_t cInitialTbs, uint32_t cMaxTbs,
     5337                              uint64_t cbInitialExec, uint64_t cbMaxExec, uint32_t cbChunkExec);
     5338void                iemThreadedTbObsolete(PVMCPUCC pVCpu, PIEMTB pTb, bool fSafeToFree);
     5339void                iemTbAllocatorProcessDelayedFrees(PVMCPU pVCpu, PIEMTBALLOCATOR pTbAllocator);
     5340
    52945341
    52955342/** @todo FNIEMTHREADEDFUNC and friends may need more work... */
     
    53485395bool iemThreadedCompileBeginEmitCallsComplications(PVMCPUCC pVCpu, PIEMTB pTb);
    53495396
     5397/* Native recompiler public bits: */
     5398PIEMTB iemNativeRecompile(PVMCPUCC pVCpu, PIEMTB pTb);
     5399int    iemExecMemAllocatorInit(PVMCPU pVCpu, uint64_t cbMax, uint64_t cbInitial, uint32_t cbChunk);
     5400void   iemExecMemAllocatorFree(PVMCPU pVCpu, void *pv, size_t cb);
     5401
    53505402
    53515403/** @} */
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