VirtualBox

Changeset 32489 in vbox


Ignore:
Timestamp:
Sep 14, 2010 3:50:31 PM (14 years ago)
Author:
vboxsync
Message:

VMM: More work on the periodic preemption timer (no actual timers yet).

Location:
trunk
Files:
11 edited

Legend:

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

    r30237 r32489  
    148148GVMMR0DECL(int)     GVMMR0SchedWakeUpAndPokeCpus(PVM pVM, PCVMCPUSET pSleepSet, PCVMCPUSET pPokeSet);
    149149GVMMR0DECL(int)     GVMMR0SchedPoll(PVM pVM, VMCPUID idCpu, bool fYield);
     150GVMMR0DECL(void)    GVMMR0SchedUpdatePeriodicPreemptionTimer(PVM pVM, RTCPUID idHostCpu, uint32_t uHz);
    150151GVMMR0DECL(int)     GVMMR0QueryStatistics(PGVMMSTATS pStats, PSUPDRVSESSION pSession, PVM pVM);
    151152GVMMR0DECL(int)     GVMMR0ResetStatistics(PCGVMMSTATS pStats, PSUPDRVSESSION pSession, PVM pVM);
  • trunk/include/VBox/hwaccm.h

    r30241 r32489  
    139139VMMR3DECL(int)          HWACCMR3PatchTprInstr(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
    140140VMMR3DECL(bool)         HWACCMR3IsRescheduleRequired(PVM pVM, PCPUMCTX pCtx);
     141VMMR3DECL(bool)         HWACCMR3IsVmxPreemptionTimerUsed(PVM pVM);
    141142
    142143/** @} */
  • trunk/include/VBox/tm.h

    r32484 r32489  
    9292#endif
    9393VMMDECL(uint32_t)       TMGetWarpDrive(PVM pVM);
     94VMM_INT_DECL(uint32_t)  TMCalcHostTimerFrequency(PVM pVM, PVMCPU pVCpu);
    9495#ifdef IN_RING3
    9596VMMR3DECL(int)          TMR3GetCpuLoadTimes(PVM pVM, VMCPUID idCpu, uint64_t *pcNsTotal, uint64_t *pcNsExecuting,
  • trunk/src/VBox/VMM/HWACCM.cpp

    r32378 r32489  
    24362436
    24372437/**
     2438 * Checks if the VMX-preemption timer is being used.
     2439 *
     2440 * @returns true if it is, false if it isn't.
     2441 * @param   pVM         The VM handle.
     2442 */
     2443VMMR3DECL(bool) HWACCMR3IsVmxPreemptionTimerUsed(PVM pVM)
     2444{
     2445    return HWACCMIsEnabled(pVM)
     2446        && pVM->hwaccm.s.vmx.fEnabled
     2447        && pVM->hwaccm.s.vmx.fUsePreemptTimer;
     2448}
     2449
     2450/**
    24382451 * Restart an I/O instruction that was refused in ring-0
    24392452 *
  • trunk/src/VBox/VMM/VMM.cpp

    r32140 r32489  
    141141    pVM->vmm.s.hEvtMulRendezvousDone            = NIL_RTSEMEVENTMULTI;
    142142    pVM->vmm.s.hEvtRendezvousDoneCaller         = NIL_RTSEMEVENT;
    143     int rc = CFGMR3QueryU32(CFGMR3GetRoot(pVM), "YieldEMTInterval", &pVM->vmm.s.cYieldEveryMillies);
    144     if (rc == VERR_CFGM_VALUE_NOT_FOUND)
    145         pVM->vmm.s.cYieldEveryMillies = 23; /* Value arrived at after experimenting with the grub boot prompt. */
    146         //pVM->vmm.s.cYieldEveryMillies = 8; //debugging
    147     else
    148         AssertMsgRCReturn(rc, ("Configuration error. Failed to query \"YieldEMTInterval\", rc=%Rrc\n", rc), rc);
     143
     144    /** @cfgm{YieldEMTInterval, uint32_t, 1, UINT32_MAX, 23, ms}
     145     * The EMT yield interval.  The EMT yielding is a hack we employ to play a
     146     * bit nicer with the rest of the system (like for instance the GUI).
     147     */
     148    int rc = CFGMR3QueryU32Def(CFGMR3GetRoot(pVM), "YieldEMTInterval", &pVM->vmm.s.cYieldEveryMillies,
     149                               23 /* Value arrived at after experimenting with the grub boot prompt. */);
     150    AssertMsgRCReturn(rc, ("Configuration error. Failed to query \"YieldEMTInterval\", rc=%Rrc\n", rc), rc);
     151
     152
     153    /** @cfgm{VMM/UsePeriodicPreemptionTimers, boolean, true}
     154     * Controls whether we employ per-cpu preemption timers to limit the time
     155     * spent executing guest code.  This option is not available on all
     156     * platforms and we will silently ignore this setting then.  If we are
     157     * running in VT-x mode, we will use the VMX-preemption timer instead of
     158     * this one when possible.
     159     */
     160    PCFGMNODE pCfgVMM = CFGMR3GetChild(CFGMR3GetRoot(pVM), "VMM");
     161    rc = CFGMR3QueryBoolDef(pCfgVMM, "UsePeriodicPreemptionTimers", &pVM->vmm.s.fUsePeriodicPreemptionTimers, true);
     162    AssertMsgRCReturn(rc, ("Configuration error. Failed to query \"VMM/UsePeriodicPreemptionTimers\", rc=%Rrc\n", rc), rc);
    149163
    150164    /*
     
    493507#endif
    494508
     509    /*
     510     * Disable the periodic preemption timers if we can use the VMX-preemption
     511     * timer instead.
     512     */
     513    if (   pVM->vmm.s.fUsePeriodicPreemptionTimers
     514        && HWACCMR3IsVmxPreemptionTimerUsed(pVM))
     515        pVM->vmm.s.fUsePeriodicPreemptionTimers = false;
     516    LogRel(("VMM: fUsePeriodicPreemptionTimers=%RTbool\n", pVM->vmm.s.fUsePeriodicPreemptionTimers));
     517
    495518    return VINF_SUCCESS;
    496519}
  • trunk/src/VBox/VMM/VMMAll/TMAll.cpp

    r32484 r32489  
    22752275 * @param   pVM         The VM handle.
    22762276 */
    2277 VMMDECL(uint32_t) TMGetFrequencyHint(PVM pVM)
     2277static uint32_t tmGetFrequencyHint(PVM pVM)
    22782278{
    22792279    /*
     
    23262326            }
    23272327            ASMAtomicWriteU32(&pVM->tm.s.uMaxHzHint, uMaxHzHint);
    2328             Log(("TMGetFrequencyHint: New value %u Hz\n", uMaxHzHint));
     2328            Log(("tmGetFrequencyHint: New value %u Hz\n", uMaxHzHint));
    23292329            tmTimerUnlock(pVM);
    23302330        }
     
    23322332    return uMaxHzHint;
    23332333}
     2334
     2335
     2336/**
     2337 * Calculates a host timer frequency that would be suitable for the current
     2338 * timer load.
     2339 *
     2340 * This will take the highest timer frequency, adjust for catch-up and warp
     2341 * driver, and finally add a little fudge factor.  The caller (VMM) will use
     2342 * the result to adjust the per-cpu preemption timer.
     2343 *
     2344 * @returns The highest frequency.  0 if no important timers around.
     2345 * @param   pVM         The VM handle.
     2346 * @param   pVCpu       The current CPU.
     2347 */
     2348VMM_INT_DECL(uint32_t) TMCalcHostTimerFrequency(PVM pVM, PVMCPU pVCpu)
     2349{
     2350    uint32_t uHz = tmGetFrequencyHint(pVM);
     2351
     2352    /* Catch up. */
     2353    if (ASMAtomicUoReadBool(&pVM->tm.s.fVirtualSyncCatchUp))
     2354    {
     2355        uint32_t u32Pct = ASMAtomicReadU32(&pVM->tm.s.u32VirtualSyncCatchUpPercentage);
     2356        if (ASMAtomicReadBool(&pVM->tm.s.fVirtualSyncCatchUp))
     2357        {
     2358            uHz *= u32Pct + 100;
     2359            uHz /= 100;
     2360        }
     2361    }
     2362
     2363    /* Warp drive */
     2364    if (ASMAtomicUoReadBool(&pVM->tm.s.fVirtualWarpDrive))
     2365    {
     2366        uint32_t u32Pct = ASMAtomicReadU32(&pVM->tm.s.u32VirtualWarpDrivePercentage);
     2367        if (ASMAtomicReadBool(&pVM->tm.s.fVirtualWarpDrive))
     2368        {
     2369            uHz *= u32Pct;
     2370            uHz /= 100;
     2371        }
     2372    }
     2373
     2374    /* Fudge factor. */
     2375    /** @todo make this configurable. */
     2376    uHz *= 110 + pVCpu->idCpu == pVM->tm.s.idTimerCpu;
     2377    uHz /= 100;
     2378
     2379    return uHz;
     2380}
  • trunk/src/VBox/VMM/VMMInternal.h

    r29902 r32489  
    262262    /** Whether log flushing has been disabled or not. */
    263263    bool                        fRCLoggerFlushingDisabled;
    264     bool                        afAlignment[6]; /**< Alignment padding. */
     264    bool                        afAlignment[5]; /**< Alignment padding. */
    265265    /** @} */
    266266
    267267    /** Whether the stack guard pages have been stationed or not. */
    268268    bool                        fStackGuardsStationed;
     269    /** Whether we should use the periodic preemption timers. */
     270    bool                        fUsePeriodicPreemptionTimers;
    269271
    270272    /** The EMT yield timer. */
  • trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp

    r31407 r32489  
    18881888
    18891889/**
     1890 * Updates the periodic preemption timer for the calling CPU.
     1891 *
     1892 * The caller must have disabled preemption!
     1893 *
     1894 * @param   pVM         The VM handle.
     1895 * @param   idHostCpu   The current host CPU id.
     1896 * @param   uHz         The desired frequency.
     1897 */
     1898GVMMR0DECL(void) GVMMR0SchedUpdatePeriodicPreemptionTimer(PVM pVM, RTCPUID idHostCpu, uint32_t uHz)
     1899{
     1900
     1901}
     1902
     1903
     1904/**
    18901905 * Retrieves the GVMM statistics visible to the caller.
    18911906 *
  • trunk/src/VBox/VMM/VMMR0/HWACCMR0.cpp

    r32361 r32489  
    14351435VMMR0DECL(int) HWACCMR0EnterSwitcher(PVM pVM, bool *pfVTxDisabled)
    14361436{
    1437     Assert(!(ASMGetFlags() & X86_EFL_IF));
     1437    Assert(!(ASMGetFlags() & X86_EFL_IF) || !RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    14381438
    14391439    *pfVTxDisabled = false;
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r32431 r32489  
    530530        case VMMR0_DO_RAW_RUN:
    531531        {
    532             /* Safety precaution as hwaccm disables the switcher. */
    533             if (RT_LIKELY(!pVM->vmm.s.fSwitcherDisabled))
     532            /* Some safety precautions first. */
     533#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
     534            if (RT_LIKELY(   !pVM->vmm.s.fSwitcherDisabled /* hwaccm */
     535                          && pVM->cCpus == 1               /* !smp */
     536                          && PGMGetHyperCR3(pVCpu)))
     537#else
     538            if (RT_LIKELY(   !pVM->vmm.s.fSwitcherDisabled
     539                          && pVM->cCpus == 1))
     540#endif
    534541            {
    535                 RTCCUINTREG uFlags = ASMIntDisableFlags();
    536                 int         rc;
    537                 bool        fVTxDisabled;
    538 
    539                 if (RT_UNLIKELY(pVM->cCpus > 1))
     542                /* Disable preemption and update the periodic preemption timer. */
     543                RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
     544                RTThreadPreemptDisable(&PreemptState);
     545                ASMAtomicWriteU32(&pVCpu->idHostCpu, RTMpCpuId());
     546                if (pVM->vmm.s.fUsePeriodicPreemptionTimers)
     547                    GVMMR0SchedUpdatePeriodicPreemptionTimer(pVM, pVCpu->idHostCpu, TMCalcHostTimerFrequency(pVM, pVCpu));
     548
     549                /* We might need to disable VT-x if the active switcher turns off paging. */
     550                bool fVTxDisabled;
     551                int rc = HWACCMR0EnterSwitcher(pVM, &fVTxDisabled);
     552                if (RT_SUCCESS(rc))
    540553                {
    541                     pVCpu->vmm.s.iLastGZRc = VERR_RAW_MODE_INVALID_SMP;
     554                    RTCCUINTREG uFlags = ASMIntDisableFlags();
     555                    VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
     556
     557                    TMNotifyStartOfExecution(pVCpu);
     558                    rc = pVM->vmm.s.pfnHostToGuestR0(pVM);
     559                    pVCpu->vmm.s.iLastGZRc = rc;
     560                    TMNotifyEndOfExecution(pVCpu);
     561
     562                    VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED);
     563
     564                    /* Re-enable VT-x if previously turned off. */
     565                    HWACCMR0LeaveSwitcher(pVM, fVTxDisabled);
     566
     567                    if (    rc == VINF_EM_RAW_INTERRUPT
     568                        ||  rc == VINF_EM_RAW_INTERRUPT_HYPER)
     569                        TRPMR0DispatchHostInterrupt(pVM);
     570
    542571                    ASMSetFlags(uFlags);
    543                     return;
     572
     573#ifdef VBOX_WITH_STATISTICS
     574                    STAM_COUNTER_INC(&pVM->vmm.s.StatRunRC);
     575                    vmmR0RecordRC(pVM, pVCpu, rc);
     576#endif
    544577                }
    545 
    546 #ifndef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
    547                 if (RT_UNLIKELY(!PGMGetHyperCR3(pVCpu)))
    548                 {
    549                     pVCpu->vmm.s.iLastGZRc = VERR_PGM_NO_CR3_SHADOW_ROOT;
    550                     ASMSetFlags(uFlags);
    551                     return;
    552                 }
    553 #endif
    554 
    555                 /* We might need to disable VT-x if the active switcher turns off paging. */
    556                 rc = HWACCMR0EnterSwitcher(pVM, &fVTxDisabled);
    557                 if (RT_FAILURE(rc))
    558                 {
     578                else
    559579                    pVCpu->vmm.s.iLastGZRc = rc;
    560                     ASMSetFlags(uFlags);
    561                     return;
    562                 }
    563 
    564                 ASMAtomicWriteU32(&pVCpu->idHostCpu, RTMpCpuId());
    565                 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
    566 
    567                 TMNotifyStartOfExecution(pVCpu);
    568                 rc = pVM->vmm.s.pfnHostToGuestR0(pVM);
    569                 pVCpu->vmm.s.iLastGZRc = rc;
    570                 TMNotifyEndOfExecution(pVCpu);
    571 
    572                 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED);
    573580                ASMAtomicWriteU32(&pVCpu->idHostCpu, NIL_RTCPUID);
    574 
    575                 /* Re-enable VT-x if previously turned off. */
    576                 HWACCMR0LeaveSwitcher(pVM, fVTxDisabled);
    577 
    578                 if (    rc == VINF_EM_RAW_INTERRUPT
    579                     ||  rc == VINF_EM_RAW_INTERRUPT_HYPER)
    580                     TRPMR0DispatchHostInterrupt(pVM);
    581 
    582                 ASMSetFlags(uFlags);
    583 
    584 #ifdef VBOX_WITH_STATISTICS
    585                 STAM_COUNTER_INC(&pVM->vmm.s.StatRunRC);
    586                 vmmR0RecordRC(pVM, pVCpu, rc);
    587 #endif
     581                RTThreadPreemptRestore(&PreemptState);
    588582            }
    589583            else
     
    591585                Assert(!pVM->vmm.s.fSwitcherDisabled);
    592586                pVCpu->vmm.s.iLastGZRc = VERR_NOT_SUPPORTED;
     587                if (pVM->cCpus != 1)
     588                    pVCpu->vmm.s.iLastGZRc = VERR_RAW_MODE_INVALID_SMP;
     589#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
     590                if (!PGMGetHyperCR3(pVCpu))
     591                    pVCpu->vmm.s.iLastGZRc = VERR_PGM_NO_CR3_SHADOW_ROOT;
     592#endif
    593593            }
    594594            break;
     
    604604        case VMMR0_DO_HWACC_RUN:
    605605        {
    606             int rc;
    607 
    608             STAM_COUNTER_INC(&pVM->vmm.s.StatRunRC);
    609 
    610606#ifdef VBOX_WITH_VMMR0_DISABLE_PREEMPTION
    611607            RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
     
    615611#endif
    616612            ASMAtomicWriteU32(&pVCpu->idHostCpu, RTMpCpuId());
     613            if (pVM->vmm.s.fUsePeriodicPreemptionTimers)
     614                GVMMR0SchedUpdatePeriodicPreemptionTimer(pVM, pVCpu->idHostCpu, TMCalcHostTimerFrequency(pVM, pVCpu));
    617615
    618616#ifdef LOG_ENABLED
     
    629627            }
    630628#endif
     629            int rc;
    631630            if (!HWACCMR0SuspendPending())
    632631            {
     
    638637                    AssertRC(rc2);
    639638                }
     639                STAM_COUNTER_INC(&pVM->vmm.s.StatRunRC);
    640640            }
    641641            else
  • trunk/src/VBox/VMM/testcase/tstVMStructRC.cpp

    r32484 r32489  
    992992    GEN_CHECK_OFF(VMM, fRCLoggerFlushingDisabled);
    993993    GEN_CHECK_OFF(VMM, fStackGuardsStationed);
     994    GEN_CHECK_OFF(VMM, fUsePeriodicPreemptionTimers);
    994995    GEN_CHECK_OFF(VMM, pYieldTimer);
    995996    GEN_CHECK_OFF(VMM, cYieldResumeMillies);
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