VirtualBox

Changeset 58938 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Dec 1, 2015 2:17:45 PM (9 years ago)
Author:
vboxsync
Message:

HM,DBGF: Made DBGF notify HM about changes to VMM event and interrupt breakpoints. Made HM cache the basic info wrt ring-0 loop selection, opting for using a debug loop when debugging takes place to avoid cluttering slowing down the normal execution loop. The plan is to extend the single stepping loop and to put complicated dtrace probes into the same loop. Modified the VMX loop selection already.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r58918 r58938  
    88558855 * @note    Mostly the same as hmR0VmxRunGuestCodeNormal().
    88568856 */
    8857 static VBOXSTRICTRC hmR0VmxRunGuestCodeStep(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
     8857static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
    88588858{
    88598859    VMXTRANSIENT VmxTransient;
     
    89598959
    89608960/**
     8961 * Checks if any expensive dtrace probes are enabled and we should go to the
     8962 * debug loop.
     8963 *
     8964 * @returns true if we should use debug loop, false if not.
     8965 */
     8966static bool hmR0VmxAnyExpensiveProbesEnabled(void)
     8967{
     8968    /* It's probably faster to OR the raw 32-bit counter variables together.
     8969       Since the variables are in an array and the probes are next to one
     8970       another (more or less), we have good locality. So, better read two three
     8971       cache lines ever time and only have one conditional, than 20+ conditionals. */
     8972    return (  VBOXVMM_XCPT_DE_ENABLED_RAW()
     8973            | VBOXVMM_XCPT_DB_ENABLED_RAW()
     8974            | VBOXVMM_XCPT_BP_ENABLED_RAW()
     8975            | VBOXVMM_XCPT_OF_ENABLED_RAW()
     8976            | VBOXVMM_XCPT_BR_ENABLED_RAW()
     8977            | VBOXVMM_XCPT_UD_ENABLED_RAW()
     8978            | VBOXVMM_XCPT_NM_ENABLED_RAW()
     8979            | VBOXVMM_XCPT_DF_ENABLED_RAW()
     8980            | VBOXVMM_XCPT_TS_ENABLED_RAW()
     8981            | VBOXVMM_XCPT_NP_ENABLED_RAW()
     8982            | VBOXVMM_XCPT_SS_ENABLED_RAW()
     8983            | VBOXVMM_XCPT_GP_ENABLED_RAW()
     8984            | VBOXVMM_XCPT_PG_ENABLED_RAW()
     8985            | VBOXVMM_XCPT_MF_ENABLED_RAW()
     8986            | VBOXVMM_XCPT_AC_ENABLED_RAW()
     8987            | VBOXVMM_XCPT_XF_ENABLED_RAW()
     8988            | VBOXVMM_XCPT_VE_ENABLED_RAW()
     8989            | VBOXVMM_XCPT_SX_ENABLED_RAW()
     8990            | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
     8991            | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
     8992           ) != 0;
     8993}
     8994
     8995
     8996/**
    89618997 * Runs the guest code using VT-x.
    89628998 *
     
    89759011
    89769012    VBOXSTRICTRC rcStrict;
    8977     if (!pVCpu->hm.s.fSingleInstruction)
     9013    if (   !pVCpu->hm.s.fUseDebugLoop
     9014        && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled()) )
    89789015        rcStrict = hmR0VmxRunGuestCodeNormal(pVM, pVCpu, pCtx);
    89799016    else
    8980         rcStrict = hmR0VmxRunGuestCodeStep(pVM, pVCpu, pCtx);
     9017        rcStrict = hmR0VmxRunGuestCodeDebug(pVM, pVCpu, pCtx);
    89819018
    89829019    if (rcStrict == VERR_EM_INTERPRETER)
  • trunk/src/VBox/VMM/VMMR3/DBGF.cpp

    r58909 r58938  
    12221222static DECLCALLBACK(VBOXSTRICTRC) dbgfR3EventConfigNotifyAllCpus(PVM pVM, PVMCPU pVCpu, void *pvUser)
    12231223{
    1224     /* Don't do anything, just make sure all CPUs goes thru EM. */
    1225     NOREF(pVM); NOREF(pVCpu); NOREF(pvUser);
     1224    if (pvUser /*fIsHmEnabled*/)
     1225        HMR3NotifyDebugEventChangedPerCpu(pVM, pVCpu);
    12261226    return VINF_SUCCESS;
    12271227}
     
    12561256
    12571257    /*
    1258      * If this is an SMP setup, we must interrupt the other CPUs if there were
    1259      * changes just to make sure their execution engines are aware of them.
     1258     * Inform HM about changes.  In an SMP setup, interrupt execution on the
     1259     * other CPUs so their execution loop can be reselected.
    12601260     */
    12611261    int rc = VINF_SUCCESS;
    1262     if (cChanges > 0 && pVM->cCpus > 1)
    1263         rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3EventConfigNotifyAllCpus, NULL);
     1262    if (cChanges > 0)
     1263    {
     1264        bool const fIsHmEnabled = HMIsEnabled(pVM);
     1265        if (fIsHmEnabled)
     1266            HMR3NotifyDebugEventChanged(pVM);
     1267        if (pVM->cCpus > 1 || fIsHmEnabled)
     1268            rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3EventConfigNotifyAllCpus,
     1269                                    (void *)(uintptr_t)fIsHmEnabled);
     1270    }
    12641271    return rc;
    12651272}
     
    13931400     * Apply the changes.
    13941401     */
    1395     bool fChanged;
     1402    bool fChanged = false;
     1403    bool fThis;
    13961404    for (uint32_t i = 0; i < cConfigs; i++)
    13971405    {
     
    14011409        if (paConfigs[i].enmHardState == DBGFINTERRUPTSTATE_ENABLED)
    14021410        {
    1403             fChanged = ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmHardIntBreakpoints, paConfigs[i].iInterrupt) == false;
    1404             if (fChanged)
     1411            fChanged |= fThis = ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmHardIntBreakpoints, paConfigs[i].iInterrupt) == false;
     1412            if (fThis)
    14051413            {
    14061414                Assert(pVM->dbgf.s.cHardIntBreakpoints < 256);
     
    14101418        else if (paConfigs[i].enmHardState == DBGFINTERRUPTSTATE_DISABLED)
    14111419        {
    1412             fChanged = ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmHardIntBreakpoints, paConfigs[i].iInterrupt) == true;
    1413             if (fChanged)
     1420            fChanged |= fThis = ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmHardIntBreakpoints, paConfigs[i].iInterrupt) == true;
     1421            if (fThis)
    14141422            {
    14151423                Assert(pVM->dbgf.s.cHardIntBreakpoints > 0);
     
    14231431        if (paConfigs[i].enmHardState == DBGFINTERRUPTSTATE_ENABLED)
    14241432        {
    1425             fChanged = ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmSoftIntBreakpoints, paConfigs[i].iInterrupt) == false;
    1426             if (fChanged)
     1433            fChanged |= fThis = ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmSoftIntBreakpoints, paConfigs[i].iInterrupt) == false;
     1434            if (fThis)
    14271435            {
    14281436                Assert(pVM->dbgf.s.cSoftIntBreakpoints < 256);
     
    14321440        else if (paConfigs[i].enmSoftState == DBGFINTERRUPTSTATE_DISABLED)
    14331441        {
    1434             fChanged = ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmSoftIntBreakpoints, paConfigs[i].iInterrupt) == true;
    1435             if (fChanged)
     1442            fChanged |= fThis = ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmSoftIntBreakpoints, paConfigs[i].iInterrupt) == true;
     1443            if (fThis)
    14361444            {
    14371445                Assert(pVM->dbgf.s.cSoftIntBreakpoints > 0);
     
    14421450
    14431451    /*
    1444      * Update the event bitmap entries and see if we need to notify other CPUs.
    1445      */
    1446     fChanged = false;
     1452     * Update the event bitmap entries.
     1453     */
    14471454    if (pVM->dbgf.s.cHardIntBreakpoints > 0)
    14481455        fChanged |= ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_INTERRUPT_HARDWARE) == false;
     
    14551462        fChanged |= ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_INTERRUPT_SOFTWARE) == true;
    14561463
     1464
     1465    /*
     1466     * Inform HM about changes.  In an SMP setup, interrupt execution on the
     1467     * other CPUs so their execution loop can be reselected.
     1468     */
    14571469    int rc = VINF_SUCCESS;
    1458     if (fChanged && pVM->cCpus > 1)
    1459         rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3EventConfigNotifyAllCpus, NULL);
     1470    if (fChanged)
     1471    {
     1472        bool const fIsHmEnabled = HMIsEnabled(pVM);
     1473        if (fIsHmEnabled)
     1474            HMR3NotifyDebugEventChanged(pVM);
     1475        if (pVM->cCpus > 1 || fIsHmEnabled)
     1476            rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3EventConfigNotifyAllCpus,
     1477                                    (void *)(uintptr_t)fIsHmEnabled);
     1478    }
    14601479    return rc;
    14611480}
  • trunk/src/VBox/VMM/VMMR3/HM.cpp

    r58909 r58938  
    27542754
    27552755/**
     2756 * Noticiation callback from DBGF when interrupt breakpoints or generic debug
     2757 * event settings changes.
     2758 *
     2759 * DBGF will call HMR3NotifyDebugEventChangedPerCpu on each CPU afterwards, this
     2760 * function is just updating the VM globals.
     2761 *
     2762 * @param   pVM         The VM cross context VM structure.
     2763 * @thread  EMT(0)
     2764 */
     2765VMMR3_INT_DECL(void) HMR3NotifyDebugEventChanged(PVM pVM)
     2766{
     2767    /* Interrupts. */
     2768    bool fUseDebugLoop = pVM->dbgf.ro.cSoftIntBreakpoints > 0
     2769                      || pVM->dbgf.ro.cHardIntBreakpoints > 0;
     2770
     2771    /* CPU Exceptions. */
     2772    for (DBGFEVENTTYPE enmEvent = DBGFEVENT_XCPT_FIRST;
     2773         !fUseDebugLoop && enmEvent <= DBGFEVENT_XCPT_LAST;
     2774         enmEvent = (DBGFEVENTTYPE)(enmEvent + 1))
     2775        fUseDebugLoop = DBGF_IS_EVENT_ENABLED(pVM, enmEvent);
     2776
     2777    /* Common VM exits. */
     2778    for (DBGFEVENTTYPE enmEvent = DBGFEVENT_EXIT_FIRST;
     2779         !fUseDebugLoop && enmEvent <= DBGFEVENT_EXIT_LAST_COMMON;
     2780         enmEvent = (DBGFEVENTTYPE)(enmEvent + 1))
     2781        fUseDebugLoop = DBGF_IS_EVENT_ENABLED(pVM, enmEvent);
     2782
     2783    /* Vendor specific VM exits. */
     2784    if (HMR3IsVmxEnabled(pVM->pUVM))
     2785        for (DBGFEVENTTYPE enmEvent = DBGFEVENT_EXIT_VMX_FIRST;
     2786             !fUseDebugLoop && enmEvent <= DBGFEVENT_EXIT_VMX_LAST;
     2787             enmEvent = (DBGFEVENTTYPE)(enmEvent + 1))
     2788            fUseDebugLoop = DBGF_IS_EVENT_ENABLED(pVM, enmEvent);
     2789    else
     2790        for (DBGFEVENTTYPE enmEvent = DBGFEVENT_EXIT_SVM_FIRST;
     2791             !fUseDebugLoop && enmEvent <= DBGFEVENT_EXIT_SVM_LAST;
     2792             enmEvent = (DBGFEVENTTYPE)(enmEvent + 1))
     2793            fUseDebugLoop = DBGF_IS_EVENT_ENABLED(pVM, enmEvent);
     2794
     2795    /* Done. */
     2796    pVM->hm.s.fUseDebugLoop = fUseDebugLoop;
     2797}
     2798
     2799
     2800/**
     2801 * Follow up notification callback to HMR3NotifyDebugEventChanged for each CPU.
     2802 *
     2803 * HM uses this to combine the decision made by HMR3NotifyDebugEventChanged with
     2804 * per CPU settings.
     2805 *
     2806 * @param   pVM         The VM cross context VM structure.
     2807 * @param   pVCpu       The cross context virtual CPU structure of the calling EMT.
     2808 */
     2809VMMR3_INT_DECL(void) HMR3NotifyDebugEventChangedPerCpu(PVM pVM, PVMCPU pVCpu)
     2810{
     2811    pVCpu->hm.s.fUseDebugLoop = pVCpu->hm.s.fSingleInstruction | pVM->hm.s.fUseDebugLoop;
     2812}
     2813
     2814
     2815/**
    27562816 * Notification from EM about a rescheduling into hardware assisted execution
    27572817 * mode.
  • trunk/src/VBox/VMM/include/HMInternal.h

    r58913 r58938  
    372372    /** Set when TPR patching is active. */
    373373    bool                        fTPRPatchingActive;
    374     bool                        u8Alignment[3];
     374    /** Set when the debug facility has breakpoints/events enabled that requires
     375     *  us to use the debug execution loop in ring-0. */
     376    bool                        fUseDebugLoop;
     377    bool                        u8Alignment[2];
    375378
    376379    /** Host kernel flags that HM might need to know (SUPKERNELFEATURES_XXX). */
     
    631634    /** Whether we're executing a single instruction. */
    632635    bool                        fSingleInstruction;
     636    /** Whether we should use the debug loop because of single stepping or special
     637     *  debug breakpoints / events are armed. */
     638    bool                        fUseDebugLoop;
    633639    /** Set if we need to clear the trap flag because of single stepping. */
    634640    bool                        fClearTrapFlag;
     
    647653    /** Whether paravirt. hypercalls are enabled. */
    648654    bool                        fHypercallsEnabled;
    649     uint8_t                     u8Alignment0[5];
     655    uint8_t                     u8Alignment0[4];
    650656
    651657    /** World switch exit counter. */
  • trunk/src/VBox/VMM/include/HMInternal.mac

    r57446 r58938  
    6868        .fCheckedTLBFlush       resb    1
    6969        .fSingleInstruction     resb    1
     70        .fUseDebugLoop          resb    1
    7071        .fClearTrapFlag         resb    1
    7172        .fLeaveDone             resb    1
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