VirtualBox

Changeset 72580 in vbox for trunk


Ignore:
Timestamp:
Jun 16, 2018 3:57:07 PM (7 years ago)
Author:
vboxsync
Message:

EM,NEM: Added /EM/ExitOptimizationEnabled config option to disable exit optimizations if necessary. Handle return-to-ring-3 cases in the most basic way too. bugref:9044

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/err.h

    r72546 r72580  
    257257/** Reason for leaving RZ: Pending ring-3 OUT instruction. */
    258258#define VINF_EM_PENDING_R3_IOPORT_WRITE      1160
     259/** Trick for resuming EMHistoryExec after a VMCPU_FF_IOM is handled. */
     260#define VINF_EM_RESUME_R3_HISTORY_EXEC       1161
    259261/** @} */
    260262
  • trunk/src/VBox/VMM/VMMAll/EMAll.cpp

    r72579 r72580  
    404404
    405405/**
     406 * Worker for EMHistoryExec that checks for ring-3 returns and flags
     407 * continuation of the EMHistoryExec run there.
     408 */
     409DECL_FORCE_INLINE(void) emHistoryExecSetContinueExitRecIdx(PVMCPU pVCpu, VBOXSTRICTRC rcStrict, PCEMEXITREC pExitRec)
     410{
     411    pVCpu->em.s.idxContinueExitRec = UINT16_MAX;
     412#ifdef IN_RING3
     413    RT_NOREF_PV(rcStrict); RT_NOREF_PV(pExitRec);
     414#else
     415    switch (VBOXSTRICTRC_VAL(rcStrict))
     416    {
     417        case VINF_SUCCESS:
     418        default:
     419            break;
     420
     421        /* Only status codes that EMHandleRCTmpl.h will resume EMHistoryExec with. */
     422        case VINF_IOM_R3_IOPORT_READ:           /* -> emR3ExecuteIOInstruction */
     423        case VINF_IOM_R3_IOPORT_WRITE:          /* -> emR3ExecuteIOInstruction */
     424        case VINF_IOM_R3_IOPORT_COMMIT_WRITE:   /* -> VMCPU_FF_IOM -> VINF_EM_RESUME_R3_HISTORY_EXEC -> emR3ExecuteIOInstruction */
     425        case VINF_IOM_R3_MMIO_READ:             /* -> emR3ExecuteInstruction */
     426        case VINF_IOM_R3_MMIO_WRITE:            /* -> emR3ExecuteInstruction */
     427        case VINF_IOM_R3_MMIO_READ_WRITE:       /* -> emR3ExecuteInstruction */
     428        case VINF_IOM_R3_MMIO_COMMIT_WRITE:     /* -> VMCPU_FF_IOM -> VINF_EM_RESUME_R3_HISTORY_EXEC -> emR3ExecuteIOInstruction */
     429        case VINF_CPUM_R3_MSR_READ:             /* -> emR3ExecuteInstruction */
     430        case VINF_CPUM_R3_MSR_WRITE:            /* -> emR3ExecuteInstruction */
     431        case VINF_GIM_R3_HYPERCALL:             /* -> emR3ExecuteInstruction */
     432            pVCpu->em.s.idxContinueExitRec = (uint16_t)(pExitRec - &pVCpu->em.s.aExitRecords[0]);
     433            break;
     434    }
     435#endif /* !IN_RING3 */
     436}
     437
     438
     439/**
    406440 * Execute using history.
    407441 *
     
    439473            LogFlow(("EMHistoryExec/EXEC_WITH_MAX: %Rrc cExits=%u cMaxExitDistance=%u cInstructions=%u\n",
    440474                     VBOXSTRICTRC_VAL(rcStrict), ExecStats.cExits, ExecStats.cMaxExitDistance, ExecStats.cInstructions));
     475            emHistoryExecSetContinueExitRecIdx(pVCpu, rcStrict, pExitRec);
    441476            return rcStrict;
    442477        }
     
    456491            LogFlow(("EMHistoryExec/EXEC_PROBE: %Rrc cExits=%u cMaxExitDistance=%u cInstructions=%u\n",
    457492                     VBOXSTRICTRC_VAL(rcStrict), ExecStats.cExits, ExecStats.cMaxExitDistance, ExecStats.cInstructions));
     493            emHistoryExecSetContinueExitRecIdx(pVCpu, rcStrict, pExitRecUnconst);
    458494            if (ExecStats.cExits >= 2)
    459495            {
     
    463499                LogFlow(("EMHistoryExec/EXEC_PROBE: -> EXEC_WITH_MAX %u\n", ExecStats.cMaxExitDistance));
    464500            }
     501#ifndef IN_RING3
     502            else if (pVCpu->em.s.idxContinueExitRec != UINT16_MAX)
     503                LogFlow(("EMHistoryExec/EXEC_PROBE: -> ring-3\n"));
     504#endif
    465505            else
    466506            {
    467507                pExitRecUnconst->enmAction = EMEXITACTION_NORMAL_PROBED;
     508                pVCpu->em.s.idxContinueExitRec = UINT16_MAX;
    468509                LogFlow(("EMHistoryExec/EXEC_PROBE: -> PROBED\n"));
    469                 /** @todo check for return to ring-3 and such and optimize/reprobe. */
    470510            }
    471511            return rcStrict;
     
    484524
    485525
     526/**
     527 * Worker for emHistoryAddOrUpdateRecord.
     528 */
    486529DECL_FORCE_INLINE(PCEMEXITREC) emHistoryRecordInit(PEMEXITREC pExitRec, uint64_t uFlatPC, uint32_t uFlagsAndType, uint64_t uExitNo)
    487530{
     
    497540
    498541
     542/**
     543 * Worker for emHistoryAddOrUpdateRecord.
     544 */
    499545DECL_FORCE_INLINE(PCEMEXITREC) emHistoryRecordInitNew(PVMCPU pVCpu, PEMEXITENTRY pHistEntry, uintptr_t idxSlot,
    500546                                                      PEMEXITREC pExitRec, uint64_t uFlatPC,
     
    505551    LogFlow(("emHistoryRecordInitNew: [%#x] = %#07x %016RX64; (%u of %u used)\n", idxSlot, uFlagsAndType, uFlatPC,
    506552             pVCpu->em.s.cExitRecordUsed, RT_ELEMENTS(pVCpu->em.s.aExitRecords) ));
     553    return emHistoryRecordInit(pExitRec, uFlatPC, uFlagsAndType, uExitNo);
     554}
     555
     556
     557/**
     558 * Worker for emHistoryAddOrUpdateRecord.
     559 */
     560DECL_FORCE_INLINE(PCEMEXITREC) emHistoryRecordInitReplacement(PEMEXITENTRY pHistEntry, uintptr_t idxSlot,
     561                                                              PEMEXITREC pExitRec, uint64_t uFlatPC,
     562                                                              uint32_t uFlagsAndType, uint64_t uExitNo)
     563{
     564    pHistEntry->idxSlot = (uint32_t)idxSlot;
     565    LogFlow(("emHistoryRecordInitReplacement: [%#x] = %#07x %016RX64 replacing %#07x %016RX64 with %u hits, %u exits old\n",
     566             idxSlot, uFlagsAndType, uFlatPC, pExitRec->uFlagsAndType, pExitRec->uFlatPC, pExitRec->cHits,
     567             uExitNo - pExitRec->uLastExitNo));
    507568    return emHistoryRecordInit(pExitRec, uFlatPC, uFlagsAndType, uExitNo);
    508569}
     
    615676                STAM_REL_COUNTER_INC(&pVCpu->em.s.aStatHistoryRecReplaced[iOldestStep]);
    616677                pExitRec = &pVCpu->em.s.aExitRecords[idxOldest];
    617                 return emHistoryRecordInitNew(pVCpu, pHistEntry, idxOldest, pExitRec, uFlatPC, uFlagsAndType, uExitNo);
     678                return emHistoryRecordInitReplacement(pHistEntry, idxOldest, pExitRec, uFlatPC, uFlagsAndType, uExitNo);
    618679            }
    619680        }
     
    689750     */
    690751    if (   (uFlagsAndType & (EMEXIT_F_KIND_MASK | EMEXIT_F_CS_EIP | EMEXIT_F_UNFLATTENED_PC)) == EMEXIT_F_KIND_EM
     752        && pVCpu->em.s.fExitOptimizationEnabled
    691753        && uFlatPC != UINT64_MAX)
    692754        return emHistoryAddOrUpdateRecord(pVCpu, uFlagsAndType, uFlatPC, pHistEntry, uExitNo);
     
    769831     */
    770832    if (   (uFlagsAndType & (EMEXIT_F_KIND_MASK | EMEXIT_F_CS_EIP | EMEXIT_F_UNFLATTENED_PC)) == EMEXIT_F_KIND_EM
     833        && pVCpu->em.s.fExitOptimizationEnabled
    771834        && pHistEntry->uFlatPC != UINT64_MAX)
    772835        return emHistoryAddOrUpdateRecord(pVCpu, uFlagsAndType, pHistEntry->uFlatPC, pHistEntry, uExitNo);
     
    804867     * If common exit type, we will insert/update the exit into the exit record hash table.
    805868     */
    806     if ((uFlagsAndType & (EMEXIT_F_KIND_MASK | EMEXIT_F_CS_EIP | EMEXIT_F_UNFLATTENED_PC)) == EMEXIT_F_KIND_EM)
     869    if (   (uFlagsAndType & (EMEXIT_F_KIND_MASK | EMEXIT_F_CS_EIP | EMEXIT_F_UNFLATTENED_PC)) == EMEXIT_F_KIND_EM
     870        && pVCpu->em.s.fExitOptimizationEnabled)
    807871        return emHistoryAddOrUpdateRecord(pVCpu, uFlagsAndType, uFlatPC, pHistEntry, uExitNo);
    808872    return NULL;
  • trunk/src/VBox/VMM/VMMR3/EM.cpp

    r72579 r72580  
    149149    }
    150150
    151     LogRel(("EMR3Init: fRecompileUser=%RTbool fRecompileSupervisor=%RTbool fRawRing1Enabled=%RTbool fIemExecutesAll=%RTbool fGuruOnTripleFault=%RTbool\n",
    152             pVM->fRecompileUser, pVM->fRecompileSupervisor, pVM->fRawRing1Enabled, pVM->em.s.fIemExecutesAll, pVM->em.s.fGuruOnTripleFault));
     151    /**
     152     * @cfgm{/EM/ExitOptimizationEnabled, bool, true}
     153     * Whether to try correlate exit history, detect hot spots and try optimize
     154     * these using IEM if there are other exits close by.
     155     */
     156    bool fExitOptimizationEnabled = true;
     157    rc = CFGMR3QueryBoolDef(pCfgEM, "ExitOptimizationEnabled", &fExitOptimizationEnabled, true);
     158    AssertLogRelRCReturn(rc, rc);
     159    for (VMCPUID i = 0; i < pVM->cCpus; i++)
     160        pVM->aCpus[i].em.s.fExitOptimizationEnabled = fExitOptimizationEnabled;
     161
     162    LogRel(("EMR3Init: fRecompileUser=%RTbool fRecompileSupervisor=%RTbool fRawRing1Enabled=%RTbool fIemExecutesAll=%RTbool fGuruOnTripleFault=%RTbool fExitOptimizationEnabled=%RTbool\n",
     163            pVM->fRecompileUser, pVM->fRecompileSupervisor, pVM->fRawRing1Enabled, pVM->em.s.fIemExecutesAll, pVM->em.s.fGuruOnTripleFault, fExitOptimizationEnabled));
    153164
    154165#ifdef VBOX_WITH_REM
     
    175186        PVMCPU pVCpu = &pVM->aCpus[i];
    176187
    177         pVCpu->em.s.enmState     = (i == 0) ? EMSTATE_NONE : EMSTATE_WAIT_SIPI;
    178         pVCpu->em.s.enmPrevState = EMSTATE_NONE;
    179         pVCpu->em.s.fForceRAW    = false;
    180 
    181         pVCpu->em.s.pCtx         = CPUMQueryGuestCtxPtr(pVCpu);
     188        pVCpu->em.s.enmState            = i == 0 ? EMSTATE_NONE : EMSTATE_WAIT_SIPI;
     189        pVCpu->em.s.enmPrevState        = EMSTATE_NONE;
     190        pVCpu->em.s.fForceRAW           = false;
     191        pVCpu->em.s.u64TimeSliceStart   = 0; /* paranoia */
     192        pVCpu->em.s.idxContinueExitRec  = UINT16_MAX;
     193
     194        pVCpu->em.s.pCtx                = CPUMQueryGuestCtxPtr(pVCpu);
    182195#ifdef VBOX_WITH_RAW_MODE
    183196        if (VM_IS_RAW_MODE_ENABLED(pVM))
     
    187200        }
    188201#endif
    189 
    190         /* Force reset of the time slice. */
    191         pVCpu->em.s.u64TimeSliceStart = 0;
    192202
    193203# define EM_REG_COUNTER(a, b, c) \
     
    17741784    /* IOM has pending work (comitting an I/O or MMIO write). */
    17751785    if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_IOM))
     1786    {
    17761787        rc = IOMR3ProcessForceFlag(pVM, pVCpu, rc);
     1788        if (pVCpu->em.s.idxContinueExitRec >= RT_ELEMENTS(pVCpu->em.s.aExitRecords))
     1789        { /* half likely, or at least it's a line shorter. */ }
     1790        else if (rc == VINF_SUCCESS)
     1791            rc = VINF_EM_RESUME_R3_HISTORY_EXEC;
     1792        else
     1793            pVCpu->em.s.idxContinueExitRec = UINT16_MAX;
     1794    }
    17771795
    17781796#ifdef VBOX_WITH_RAW_MODE
  • trunk/src/VBox/VMM/VMMR3/EMR3Nem.cpp

    r72488 r72580  
    179179    PCPUMCTX pCtx = pVCpu->em.s.pCtx;
    180180#endif
    181     int      rc;
    182181    NOREF(rcRC);
    183182
     
    199198     */
    200199    STAM_PROFILE_START(&pVCpu->em.s.StatIEMEmu, a);
    201     CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_MUST_MASK);
    202     rc = VBOXSTRICTRC_TODO(IEMExecOne(pVCpu));
     200
     201    VBOXSTRICTRC rcStrict;
     202    uint32_t     idxContinueExitRec = pVCpu->em.s.idxContinueExitRec;
     203    RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
     204    if (idxContinueExitRec >= RT_ELEMENTS(pVCpu->em.s.aExitRecords))
     205    {
     206        CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_MUST_MASK);
     207        rcStrict = IEMExecOne(pVCpu);
     208    }
     209    else
     210    {
     211        RT_UNTRUSTED_VALIDATED_FENCE();
     212        rcStrict = EMHistoryExec(pVCpu, &pVCpu->em.s.aExitRecords[idxContinueExitRec], 0);
     213        LogFlow(("emR3NemExecuteInstruction: %Rrc (EMHistoryExec)\n", VBOXSTRICTRC_VAL(rcStrict)));
     214    }
     215
    203216    STAM_PROFILE_STOP(&pVCpu->em.s.StatIEMEmu, a);
    204217
    205     if (   rc == VERR_IEM_ASPECT_NOT_IMPLEMENTED
    206         || rc == VERR_IEM_INSTR_NOT_IMPLEMENTED)
     218    if (   rcStrict == VERR_IEM_ASPECT_NOT_IMPLEMENTED
     219        || rcStrict == VERR_IEM_INSTR_NOT_IMPLEMENTED)
    207220    {
    208221#ifdef VBOX_WITH_REM
     
    215228        pVM->em.s.idLastRemCpu = pVCpu->idCpu;
    216229
    217         rc = REMR3EmulateInstruction(pVM, pVCpu);
     230        rcStrict = REMR3EmulateInstruction(pVM, pVCpu);
    218231        EMRemUnlock(pVM);
    219232        STAM_PROFILE_STOP(&pVCpu->em.s.StatREMEmu, b);
     
    222235#endif /* !VBOX_WITH_REM */
    223236    }
    224     return rc;
     237    return VBOXSTRICTRC_TODO(rcStrict);
    225238}
    226239
     
    259272    STAM_PROFILE_START(&pVCpu->em.s.StatIOEmu, a);
    260273
    261 #if 0
    262     PCPUMCTX pCtx = pVCpu->em.s.pCtx;
    263 
    264     /*
    265      * Try to restart the io instruction that was refused in ring-0.
    266      */
    267     VBOXSTRICTRC rcStrict = HMR3RestartPendingIOInstr(pVM, pVCpu, pCtx);
    268     if (IOM_SUCCESS(rcStrict))
    269     {
     274    /*
     275     * Hand it over to the interpreter.
     276     */
     277    CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_MUST_MASK);
     278    VBOXSTRICTRC rcStrict;
     279    uint32_t     idxContinueExitRec = pVCpu->em.s.idxContinueExitRec;
     280    RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
     281    if (idxContinueExitRec >= RT_ELEMENTS(pVCpu->em.s.aExitRecords))
     282    {
     283        rcStrict = IEMExecOne(pVCpu);
     284        LogFlow(("emR3NemExecuteIOInstruction: %Rrc (IEMExecOne)\n", VBOXSTRICTRC_VAL(rcStrict)));
     285        STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatIoIem);
     286    }
     287    else
     288    {
     289        RT_UNTRUSTED_VALIDATED_FENCE();
     290        rcStrict = EMHistoryExec(pVCpu, &pVCpu->em.s.aExitRecords[idxContinueExitRec], 0);
     291        LogFlow(("emR3NemExecuteIOInstruction: %Rrc (EMHistoryExec)\n", VBOXSTRICTRC_VAL(rcStrict)));
    270292        STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatIoRestarted);
    271         STAM_PROFILE_STOP(&pVCpu->em.s.StatIOEmu, a);
    272         return VBOXSTRICTRC_TODO(rcStrict);     /* rip already updated. */
    273     }
    274     AssertMsgReturn(rcStrict == VERR_NOT_FOUND, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)),
    275                     RT_SUCCESS_NP(rcStrict) ? VERR_IPE_UNEXPECTED_INFO_STATUS : VBOXSTRICTRC_TODO(rcStrict));
    276 #endif
    277 
    278     /*
    279      * Hand it over to the interpreter.
    280      */
    281     CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_MUST_MASK);
    282     VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
    283     LogFlow(("emR3NemExecuteIOInstruction: %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
    284     STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatIoIem);
     293    }
    285294
    286295    STAM_PROFILE_STOP(&pVCpu->em.s.StatIOEmu, a);
  • trunk/src/VBox/VMM/include/EMHandleRCTmpl.h

    r72492 r72580  
    217217        case VINF_IOM_R3_IOPORT_READ:
    218218        case VINF_IOM_R3_IOPORT_WRITE:
     219        case VINF_EM_RESUME_R3_HISTORY_EXEC: /* Resume EMHistoryExec after VMCPU_FF_IOM. */
    219220            rc = emR3ExecuteIOInstruction(pVM, pVCpu);
    220221            break;
  • trunk/src/VBox/VMM/include/EMInternal.h

    r72579 r72580  
    400400#endif
    401401
    402     /** Pointer to the guest CPUM state. (R3 Ptr) */
     402    /** Pointer to the guest CPUM state. (R3 Ptr)
     403     * @obsolete Use pVCpu->cpum.GstCtx!  */
    403404    R3PTRTYPE(PCPUMCTX)     pCtx;
    404405
     
    499500#endif
    500501
     502    /** Exit history table (6KB). */
     503    EMEXITENTRY             aExitHistory[256];
    501504    /** Where to store the next exit history entry.
    502505     * Since aExitHistory is 256 items longs, we'll just increment this and
     
    504507     * wrapped around or not.  */
    505508    uint64_t                iNextExit;
    506     /** Exit history table (6KB). */
    507     EMEXITENTRY             aExitHistory[256];
    508 
     509    /** Whether exit optimizations are enabled or not. */
     510    bool                    fExitOptimizationEnabled;
     511    /** Explicit padding. */
     512    bool                    afPadding2[1];
     513    /** Index into aExitRecords set by EMHistoryExec when returning to ring-3.
     514     * This is UINT16_MAX if not armed.  */
     515    uint16_t volatile       idxContinueExitRec;
     516    /** Number of exit records in use. */
     517    uint32_t                cExitRecordUsed;
    509518    /** Hit statistics for each lookup step. */
    510519    STAMCOUNTER             aStatHistoryRecHits[16];
     
    515524    /** New record statistics for each lookup step. */
    516525    STAMCOUNTER             aStatHistoryRecNew[16];
    517     /** Number of exit records in use. */
    518     uint32_t                cExitRecordUsed;
    519     /** Explicit padding. */
    520     uint32_t                uPadding2;
     526
    521527    /** Exit records (32KB). (Aligned on 32 byte boundrary.) */
    522528    EMEXITREC               aExitRecords[1024];
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