VirtualBox

Changeset 58909 in vbox


Ignore:
Timestamp:
Nov 29, 2015 7:23:46 PM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
104409
Message:

DBGF: More groundwork for port I/O, MMIO, interrupt and generic event breakpoints.

Location:
trunk
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/dbgf.h

    r58903 r58909  
    189189     */
    190190    DBGFEVENT_POWERING_OFF,
     191
     192    /** Hardware Interrupt break.
     193     * @todo not yet implemented. */
     194    DBGFEVENT_INTERRUPT_HARDWARE,
     195    /** Software Interrupt break.
     196     * @todo not yet implemented. */
     197    DBGFEVENT_INTERRUPT_SOFTWARE,
    191198
    192199    /** The first selectable event.
     
    435442    } u;
    436443} DBGFEVENT;
     444AssertCompileSizeAlignment(DBGFEVENT, 8);
    437445/** Pointer to VMM Debug Event. */
    438446typedef DBGFEVENT *PDBGFEVENT;
     
    478486VMMR3DECL(int)          DBGFR3InjectNMI(PUVM pUVM, VMCPUID idCpu);
    479487
     488/**
     489 * Event configuration array element, see DBGFR3EventConfigEx.
     490 */
     491typedef struct DBGFEVENTCONFIG
     492{
     493    /** The event to configure */
     494    DBGFEVENTTYPE   enmType;
     495    /** The new state. */
     496    bool            fEnabled;
     497} DBGFEVENTCONFIG;
     498/** Pointer to an event config. */
     499typedef DBGFEVENTCONFIG *PDBGFEVENTCONFIG;
     500/** Pointer to a const event config. */
     501typedef const DBGFEVENTCONFIG *PCDBGFEVENTCONFIG;
     502
     503VMMR3DECL(int)          DBGFR3EventConfigEx(PUVM pUVM, PCDBGFEVENTCONFIG paConfigs, size_t cConfigs);
     504VMMR3DECL(int)          DBGFR3EventConfig(PUVM pUVM, DBGFEVENTTYPE enmEvent, bool fEnabled);
     505VMMR3DECL(bool)         DBGFR3EventIsEnabled(PUVM pUVM, DBGFEVENTTYPE enmEvent);
     506VMMR3DECL(int)          DBGFR3EventQuery(PUVM pUVM, PDBGFEVENTCONFIG paConfigs, size_t cConfigs);
     507
     508/** @name DBGFINTERRUPTSTATE_XXX - interrupt break state.
     509 * @{ */
     510#define DBGFINTERRUPTSTATE_DISABLED     0
     511#define DBGFINTERRUPTSTATE_ENABLED      1
     512#define DBGFINTERRUPTSTATE_DONT_TOUCH   2
     513/** @} */
     514
     515/**
     516 * Interrupt break state configuration entry.
     517 */
     518typedef struct DBGFINTERRUPTCONFIG
     519{
     520    /** The interrupt number. */
     521    uint8_t     iInterrupt;
     522    /** The hardware interrupt state (DBGFINTERRUPTSTATE_XXX). */
     523    uint8_t     enmHardState;
     524    /** The software interrupt state (DBGFINTERRUPTSTATE_XXX). */
     525    uint8_t     enmSoftState;
     526} DBGFINTERRUPTCONFIG;
     527/** Pointer to an interrupt break state config entyr. */
     528typedef DBGFINTERRUPTCONFIG *PDBGFINTERRUPTCONFIG;
     529/** Pointer to a const interrupt break state config entyr. */
     530typedef DBGFINTERRUPTCONFIG const *PCDBGFINTERRUPTCONFIG;
     531
     532VMMR3DECL(int) DBGFR3InterruptConfigEx(PUVM pUVM, PCDBGFINTERRUPTCONFIG paConfigs, size_t cConfigs);
     533VMMR3DECL(int) DBGFR3InterruptHardwareConfig(PUVM pUVM, uint8_t iInterrupt, bool fEnabled);
     534VMMR3DECL(int) DBGFR3InterruptSoftwareConfig(PUVM pUVM, uint8_t iInterrupt, bool fEnabled);
     535VMMR3DECL(int) DBGFR3InterruptHardwareIsEnabled(PUVM pUVM, uint8_t iInterrupt);
     536VMMR3DECL(int) DBGFR3InterruptSoftwareIsEnabled(PUVM pUVM, uint8_t iInterrupt);
     537
    480538#endif /* IN_RING3 */
     539
     540/** @def DBGF_IS_EVENT_ENABLED
     541 * Checks if a selectable debug event is enabled or not (fast).
     542 *
     543 * @returns true/false.
     544 * @param   a_pVM       Pointer to the cross context VM structure.
     545 * @param   a_enmEvent  The selectable event to check.
     546 * @remarks Only for use internally in the VMM. Use DBGFR3EventIsEnabled elsewhere.
     547 */
     548#if defined(VBOX_STRICT) && defined(RT_COMPILER_SUPPORTS_LAMBDA)
     549# define DBGF_IS_EVENT_ENABLED(a_pVM, a_enmEvent) \
     550    ([](PVM a_pLambdaVM, DBGFEVENTTYPE a_enmLambdaEvent) -> bool { \
     551        Assert(a_enmLambdaEvent >= DBGFEVENT_FIRST_SELECTABLE); \
     552        Assert(a_enmLambdaEvent < DBGFEVENT_END); \
     553        return ASMBitTest(&a_pLambdaVM->dbgf.ro.bmSelectedEvents, a_enmLambdaEvent); \
     554    }(a_pVM, a_enmEvent))
     555#elif defined(VBOX_STRICT) && defined(__GNUC__)
     556# define DBGF_IS_EVENT_ENABLED(a_pVM, a_enmEvent) \
     557    __extension__ ({ \
     558        Assert((a_enmEvent) >= DBGFEVENT_FIRST_SELECTABLE); \
     559        Assert((a_enmEvent) < DBGFEVENT_END); \
     560        ASMBitTest(&(a_pVM)->dbgf.ro.bmSelectedEvents, (a_enmEvent)); \
     561    })
     562#else
     563# define DBGF_IS_EVENT_ENABLED(a_pVM, a_enmEvent) \
     564        ASMBitTest(&(a_pVM)->dbgf.ro.bmSelectedEvents, (a_enmEvent))
     565#endif
     566
     567
     568/** @def DBGF_IS_HARDWARE_INT_ENABLED
     569 * Checks if hardware interrupt interception is enabled or not for an interrupt.
     570 *
     571 * @returns true/false.
     572 * @param   a_pVM           Pointer to the cross context VM structure.
     573 * @param   a_iInterrupt    Interrupt to check.
     574 * @remarks Only for use internally in the VMM.  Use
     575 *          DBGFR3InterruptHardwareIsEnabled elsewhere.
     576 */
     577#define DBGF_IS_HARDWARE_INT_ENABLED(a_pVM, a_iInterrupt) \
     578        ASMBitTest(&(a_pVM)->dbgf.ro.bmHardIntBreakpoints, (uint8_t)(a_iInterrupt))
     579
     580/** @def DBGF_IS_SOFTWARE_INT_ENABLED
     581 * Checks if software interrupt interception is enabled or not for an interrupt.
     582 *
     583 * @returns true/false.
     584 * @param   a_pVM           Pointer to the cross context VM structure.
     585 * @param   a_iInterrupt    Interrupt to check.
     586 * @remarks Only for use internally in the VMM.  Use
     587 *          DBGFR3InterruptSoftwareIsEnabled elsewhere.
     588 */
     589#define DBGF_IS_SOFTWARE_INT_ENABLED(a_pVM, a_iInterrupt) \
     590        ASMBitTest(&(a_pVM)->dbgf.ro.bmSoftIntBreakpoints, (uint8_t)(a_iInterrupt))
    481591
    482592
     
    644754 * Breakpoint enumeration callback function.
    645755 *
    646  * @returns VBox status code. Any failure will stop the enumeration.
     756 * @returns VBox status code.
     757 *          The enumeration stops on failure status and VINF_CALLBACK_RETURN.
    647758 * @param   pUVM        The user mode VM handle.
    648759 * @param   pvUser      The user argument.
  • trunk/include/VBox/vmm/iom.h

    r58903 r58909  
    339339VMMR3_INT_DECL(int)  IOMR3MmioDeregister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange);
    340340
    341 VMMR3_INT_DECL(void) IOMR3NotifyBreakpointCountChange(PVM pVM, unsigned cPortIo, unsigned cMmio);
     341VMMR3_INT_DECL(void) IOMR3NotifyBreakpointCountChange(PVM pVM, bool fPortIo, bool fMmio);
    342342VMMR3_INT_DECL(void) IOMR3NotifyDebugEventChange(PVM pVM, DBGFEVENT enmEvent, bool fEnabled);
    343343
  • trunk/include/VBox/vmm/vm.h

    r58283 r58909  
    217217        struct DBGFCPU      s;
    218218#endif
    219         uint8_t             padding[64];        /* multiple of 64 */
     219        uint8_t             padding[256];       /* multiple of 64 */
    220220    } dbgf;
    221221
     
    230230
    231231    /** Align the following members on page boundary. */
    232     uint8_t                 abAlignment2[3584];
     232    uint8_t                 abAlignment2[3392];
    233233
    234234    /** PGM part. */
     
    983983#endif
    984984#ifdef ___VBox_vmm_cpum_h
    985         /** Read only info exposed about the host and guest CPUs.   */
     985        /** Read only info exposed about the host and guest CPUs. */
    986986        struct
    987987        {
     
    11111111        struct DBGF s;
    11121112#endif
     1113#ifdef ___VBox_vmm_dbgf_h
     1114        /** Read only info exposed about interrupt breakpoints and selected events. */
     1115        struct
     1116        {
     1117            /** Bitmap of enabled hardware interrupt breakpoints. */
     1118            uint32_t                    bmHardIntBreakpoints[256 / 32];
     1119            /** Bitmap of enabled software interrupt breakpoints. */
     1120            uint32_t                    bmSoftIntBreakpoints[256 / 32];
     1121            /** Bitmap of selected events.
     1122             * This includes non-selectable events too for simplicity, we maintain the
     1123             * state for some of these, as it may come in handy. */
     1124            uint32_t                    bmSelectedEvents[(DBGFEVENT_END + 31) / 32];
     1125            /** Enabled hardware interrupt breakpoints. */
     1126            uint32_t                    cHardIntBreakpoints;
     1127            /** Enabled software interrupt breakpoints. */
     1128            uint32_t                    cSoftIntBreakpoints;
     1129            /** Number of selected events. */
     1130            uint32_t                    cSelectedEvents;
     1131        } const     ro;
     1132#endif
    11131133        uint8_t     padding[2368];      /* multiple of 64 */
    11141134    } dbgf;
  • trunk/include/VBox/vmm/vm.mac

    r56291 r58909  
    142142    .pdm                    resb 256
    143143    .iom                    resb 512
    144     .dbgf                   resb 64
     144    .dbgf                   resb 256
    145145    .gim                    resb 64
    146146
  • trunk/src/VBox/Debugger/DBGConsole.cpp

    r58170 r58909  
    657657
    658658        case DBGFEVENT_BREAKPOINT:
     659        case DBGFEVENT_BREAKPOINT_IO:
     660        case DBGFEVENT_BREAKPOINT_MMIO:
    659661        case DBGFEVENT_BREAKPOINT_HYPER:
    660662        {
    661663            bool fRegCtxGuest = pDbgc->fRegCtxGuest;
    662             pDbgc->fRegCtxGuest = pEvent->enmType == DBGFEVENT_BREAKPOINT;
     664            pDbgc->fRegCtxGuest = pEvent->enmType != DBGFEVENT_BREAKPOINT_HYPER;
    663665
    664666            rc = dbgcBpExec(pDbgc, pEvent->u.Bp.iBp);
  • trunk/src/VBox/VMM/VMMAll/DBGFAll.cpp

    r58903 r58909  
    2626#include <VBox/err.h>
    2727#include <iprt/assert.h>
     28
     29
     30/*
     31 * Check the read-only VM members.
     32 */
     33AssertCompileMembersSameSizeAndOffset(VM, dbgf.s.bmSoftIntBreakpoints,  VM, dbgf.ro.bmSoftIntBreakpoints);
     34AssertCompileMembersSameSizeAndOffset(VM, dbgf.s.bmHardIntBreakpoints,  VM, dbgf.ro.bmHardIntBreakpoints);
     35AssertCompileMembersSameSizeAndOffset(VM, dbgf.s.bmSelectedEvents,      VM, dbgf.ro.bmSelectedEvents);
     36AssertCompileMembersSameSizeAndOffset(VM, dbgf.s.cHardIntBreakpoints,   VM, dbgf.ro.cHardIntBreakpoints);
     37AssertCompileMembersSameSizeAndOffset(VM, dbgf.s.cSoftIntBreakpoints,   VM, dbgf.ro.cSoftIntBreakpoints);
     38AssertCompileMembersSameSizeAndOffset(VM, dbgf.s.cSelectedEvents,       VM, dbgf.ro.cSelectedEvents);
    2839
    2940
     
    120131 * @returns true if armed, false if not.
    121132 * @param   pVM        The cross context VM structure.
     133 * @remarks Don't call this from CPUMRecalcHyperDRx!
    122134 */
    123135VMM_INT_DECL(bool) DBGFBpIsHwArmed(PVM pVM)
    124136{
    125     Assert(RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints) == 4);
    126     return (pVM->dbgf.s.aHwBreakpoints[0].fEnabled && pVM->dbgf.s.aHwBreakpoints[0].enmType == DBGFBPTYPE_REG)
    127         || (pVM->dbgf.s.aHwBreakpoints[1].fEnabled && pVM->dbgf.s.aHwBreakpoints[1].enmType == DBGFBPTYPE_REG)
    128         || (pVM->dbgf.s.aHwBreakpoints[2].fEnabled && pVM->dbgf.s.aHwBreakpoints[2].enmType == DBGFBPTYPE_REG)
    129         || (pVM->dbgf.s.aHwBreakpoints[3].fEnabled && pVM->dbgf.s.aHwBreakpoints[3].enmType == DBGFBPTYPE_REG);
     137    return pVM->dbgf.s.cEnabledHwBreakpoints > 0;
    130138}
    131139
     
    136144 * @returns true if armed, false if not.
    137145 * @param   pVM        The cross context VM structure.
     146 * @remarks Don't call this from CPUMRecalcHyperDRx!
    138147 */
    139148VMM_INT_DECL(bool) DBGFBpIsHwIoArmed(PVM pVM)
    140149{
    141     Assert(RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints) == 4);
    142     /** @todo cache this! */
    143     return (   pVM->dbgf.s.aHwBreakpoints[0].u.Reg.fType == X86_DR7_RW_IO
    144             && pVM->dbgf.s.aHwBreakpoints[0].fEnabled
    145             && pVM->dbgf.s.aHwBreakpoints[0].enmType     == DBGFBPTYPE_REG
    146            )
    147         || (   pVM->dbgf.s.aHwBreakpoints[1].u.Reg.fType == X86_DR7_RW_IO
    148             && pVM->dbgf.s.aHwBreakpoints[1].fEnabled
    149             && pVM->dbgf.s.aHwBreakpoints[1].enmType     == DBGFBPTYPE_REG
    150            )
    151         || (   pVM->dbgf.s.aHwBreakpoints[2].u.Reg.fType == X86_DR7_RW_IO
    152             && pVM->dbgf.s.aHwBreakpoints[2].fEnabled
    153             && pVM->dbgf.s.aHwBreakpoints[2].enmType     == DBGFBPTYPE_REG
    154            )
    155         || (   pVM->dbgf.s.aHwBreakpoints[3].u.Reg.fType == X86_DR7_RW_IO
    156             && pVM->dbgf.s.aHwBreakpoints[3].fEnabled
    157             && pVM->dbgf.s.aHwBreakpoints[3].enmType     == DBGFBPTYPE_REG
    158            );
     150    return pVM->dbgf.s.cEnabledHwIoBreakpoints > 0;
    159151}
    160152
     
    185177     * the guest.
    186178     */
    187     for (unsigned iBp = 0; iBp < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints); iBp++)
     179    if (pVM->dbgf.s.cEnabledHwIoBreakpoints > 0)
    188180    {
    189         if (   pVM->dbgf.s.aHwBreakpoints[iBp].u.Reg.fType == X86_DR7_RW_IO
    190             && pVM->dbgf.s.aHwBreakpoints[iBp].fEnabled
    191             && pVM->dbgf.s.aHwBreakpoints[iBp].enmType     == DBGFBPTYPE_REG )
     181        for (unsigned iBp = 0; iBp < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints); iBp++)
    192182        {
    193             uint8_t  cbReg      = pVM->dbgf.s.aHwBreakpoints[iBp].u.Reg.cb; Assert(RT_IS_POWER_OF_TWO(cbReg));
    194             uint64_t uDrXFirst  = pVM->dbgf.s.aHwBreakpoints[iBp].u.Reg.GCPtr & ~(uint64_t)(cbReg - 1);
    195             uint64_t uDrXLast   = uDrXFirst + cbReg - 1;
    196             if (uDrXFirst <= uIoPortLast && uDrXLast >= uIoPortFirst)
     183            if (   pVM->dbgf.s.aHwBreakpoints[iBp].u.Reg.fType == X86_DR7_RW_IO
     184                && pVM->dbgf.s.aHwBreakpoints[iBp].fEnabled
     185                && pVM->dbgf.s.aHwBreakpoints[iBp].enmType     == DBGFBPTYPE_REG )
    197186            {
    198                 /* (See also DBGFRZTrap01Handler.) */
    199                 pVCpu->dbgf.s.iActiveBp = pVM->dbgf.s.aHwBreakpoints[iBp].iBp;
    200                 pVCpu->dbgf.s.fSingleSteppingRaw = false;
    201 
    202                 LogFlow(("DBGFBpCheckIo: hit hw breakpoint %d at %04x:%RGv (iop %#x)\n",
    203                          pVM->dbgf.s.aHwBreakpoints[iBp].iBp, pCtx->cs.Sel, pCtx->rip, uIoPort));
    204                 return VINF_EM_DBG_BREAKPOINT;
     187                uint8_t  cbReg      = pVM->dbgf.s.aHwBreakpoints[iBp].u.Reg.cb; Assert(RT_IS_POWER_OF_TWO(cbReg));
     188                uint64_t uDrXFirst  = pVM->dbgf.s.aHwBreakpoints[iBp].u.Reg.GCPtr & ~(uint64_t)(cbReg - 1);
     189                uint64_t uDrXLast   = uDrXFirst + cbReg - 1;
     190                if (uDrXFirst <= uIoPortLast && uDrXLast >= uIoPortFirst)
     191                {
     192                    /* (See also DBGFRZTrap01Handler.) */
     193                    pVCpu->dbgf.s.iActiveBp = pVM->dbgf.s.aHwBreakpoints[iBp].iBp;
     194                    pVCpu->dbgf.s.fSingleSteppingRaw = false;
     195
     196                    LogFlow(("DBGFBpCheckIo: hit hw breakpoint %d at %04x:%RGv (iop %#x)\n",
     197                             pVM->dbgf.s.aHwBreakpoints[iBp].iBp, pCtx->cs.Sel, pCtx->rip, uIoPort));
     198                    return VINF_EM_DBG_BREAKPOINT;
     199                }
    205200            }
    206201        }
  • trunk/src/VBox/VMM/VMMR3/DBGF.cpp

    r58903 r58909  
    12181218
    12191219/**
     1220 * @callback_method_impl{FNVMMEMTRENDEZVOUS}
     1221 */
     1222static DECLCALLBACK(VBOXSTRICTRC) dbgfR3EventConfigNotifyAllCpus(PVM pVM, PVMCPU pVCpu, void *pvUser)
     1223{
     1224    /* Don't do anything, just make sure all CPUs goes thru EM. */
     1225    NOREF(pVM); NOREF(pVCpu); NOREF(pvUser);
     1226    return VINF_SUCCESS;
     1227}
     1228
     1229
     1230/**
     1231 * Worker for DBGFR3EventConfigEx.
     1232 *
     1233 * @returns VBox status code. Will not return VBOX_INTERRUPTED.
     1234 * @param   pUVM        The user mode VM handle.
     1235 * @param   paConfigs   The event to configure and their new state.
     1236 * @param   cConfigs    Number of entries in @a paConfigs.
     1237 */
     1238static DECLCALLBACK(int) dbgfR3EventConfigEx(PUVM pUVM, DBGFEVENTCONFIG volatile const *paConfigs, size_t cConfigs)
     1239{
     1240    PVM pVM = pUVM->pVM;
     1241    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     1242
     1243    /*
     1244     * Apply the changes.
     1245     */
     1246    unsigned cChanges = 0;
     1247    for (uint32_t i = 0; i < cConfigs; i++)
     1248    {
     1249        DBGFEVENTTYPE enmType = paConfigs[i].enmType;
     1250        AssertReturn(enmType >= DBGFEVENT_FIRST_SELECTABLE && enmType < DBGFEVENT_END, VERR_INVALID_PARAMETER);
     1251        if (paConfigs[i].fEnabled)
     1252            cChanges += ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmSelectedEvents, enmType) == false;
     1253        else
     1254            cChanges += ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmSelectedEvents, enmType) == true;
     1255    }
     1256
     1257    /*
     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.
     1260     */
     1261    int rc = VINF_SUCCESS;
     1262    if (cChanges > 0 && pVM->cCpus > 1)
     1263        rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3EventConfigNotifyAllCpus, NULL);
     1264    return rc;
     1265}
     1266
     1267
     1268/**
     1269 * Configures (enables/disables) multiple selectable debug events.
     1270 *
     1271 * @returns VBox status code.
     1272 * @param   pUVM        The user mode VM handle.
     1273 * @param   paConfigs   The event to configure and their new state.
     1274 * @param   cConfigs    Number of entries in @a paConfigs.
     1275 */
     1276VMMR3DECL(int) DBGFR3EventConfigEx(PUVM pUVM, PCDBGFEVENTCONFIG paConfigs, size_t cConfigs)
     1277{
     1278    /*
     1279     * Validate input.
     1280     */
     1281    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
     1282    size_t i = cConfigs;
     1283    while (i-- > 0)
     1284    {
     1285        AssertReturn(paConfigs[i].enmType >= DBGFEVENT_FIRST_SELECTABLE, VERR_INVALID_PARAMETER);
     1286        AssertReturn(paConfigs[i].enmType <  DBGFEVENT_END, VERR_INVALID_PARAMETER);
     1287    }
     1288
     1289    /*
     1290     * Apply the changes in EMT(0).
     1291     */
     1292    return VMR3ReqPriorityCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3EventConfigEx, 3, pUVM, paConfigs, cConfigs);
     1293}
     1294
     1295
     1296/**
     1297 * Enables or disables a selectable debug event.
     1298 *
     1299 * @returns VBox status code.
     1300 * @param   pUVM        The user mode VM handle.
     1301 * @param   enmEvent    The selectable debug event.
     1302 * @param   fEnabled    The new state.
     1303 */
     1304VMMR3DECL(int) DBGFR3EventConfig(PUVM pUVM, DBGFEVENTTYPE enmEvent, bool fEnabled)
     1305{
     1306    /*
     1307     * Convert to an array call.
     1308     */
     1309    DBGFEVENTCONFIG EvtCfg = { enmEvent, fEnabled };
     1310    return DBGFR3EventConfigEx(pUVM, &EvtCfg, 1);
     1311}
     1312
     1313
     1314/**
     1315 * Checks if the given selectable event is enabled.
     1316 *
     1317 * @returns true if enabled, false if not or invalid input.
     1318 * @param   pUVM        The user mode VM handle.
     1319 * @param   enmEvent    The selectable debug event.
     1320 * @sa      DBGFR3EventQuery
     1321 */
     1322VMMR3DECL(bool) DBGFR3EventIsEnabled(PUVM pUVM, DBGFEVENTTYPE enmEvent)
     1323{
     1324    /*
     1325     * Validate input.
     1326     */
     1327    AssertReturn(   enmEvent >= DBGFEVENT_HALT_DONE
     1328                 && enmEvent <  DBGFEVENT_END, false);
     1329    Assert(   enmEvent >= DBGFEVENT_FIRST_SELECTABLE
     1330           || enmEvent == DBGFEVENT_BREAKPOINT
     1331           || enmEvent == DBGFEVENT_BREAKPOINT_IO
     1332           || enmEvent == DBGFEVENT_BREAKPOINT_MMIO);
     1333
     1334    UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
     1335    PVM pVM = pUVM->pVM;
     1336    VM_ASSERT_VALID_EXT_RETURN(pVM, false);
     1337
     1338    /*
     1339     * Check the event status.
     1340     */
     1341    return ASMBitTest(&pVM->dbgf.s.bmSelectedEvents, enmEvent);
     1342}
     1343
     1344
     1345/**
     1346 * Queries the status of a set of events.
     1347 *
     1348 * @returns VBox status code.
     1349 * @param   pUVM        The user mode VM handle.
     1350 * @param   paConfigs   The events to query and where to return the state.
     1351 * @param   cConfigs    The number of elements in @a paConfigs.
     1352 * @sa      DBGFR3EventIsEnabled, DBGF_IS_EVENT_ENABLED
     1353 */
     1354VMMR3DECL(int) DBGFR3EventQuery(PUVM pUVM, PDBGFEVENTCONFIG paConfigs, size_t cConfigs)
     1355{
     1356    /*
     1357     * Validate input.
     1358     */
     1359    UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
     1360    PVM pVM = pUVM->pVM;
     1361    VM_ASSERT_VALID_EXT_RETURN(pVM, false);
     1362
     1363    for (size_t i = 0; i < cConfigs; i++)
     1364    {
     1365        DBGFEVENTTYPE enmType = paConfigs[i].enmType;
     1366        AssertReturn(   enmType >= DBGFEVENT_HALT_DONE
     1367                     && enmType <  DBGFEVENT_END, VERR_INVALID_PARAMETER);
     1368        Assert(   enmType >= DBGFEVENT_FIRST_SELECTABLE
     1369               || enmType == DBGFEVENT_BREAKPOINT
     1370               || enmType == DBGFEVENT_BREAKPOINT_IO
     1371               || enmType == DBGFEVENT_BREAKPOINT_MMIO);
     1372        paConfigs[i].fEnabled = ASMBitTest(&pVM->dbgf.s.bmSelectedEvents, paConfigs[i].enmType);
     1373    }
     1374
     1375    return VINF_SUCCESS;
     1376}
     1377
     1378
     1379/**
     1380 * Worker for DBGFR3InterruptConfigEx.
     1381 *
     1382 * @returns VBox status code. Will not return VBOX_INTERRUPTED.
     1383 * @param   pUVM        The user mode VM handle.
     1384 * @param   paConfigs   The event to configure and their new state.
     1385 * @param   cConfigs    Number of entries in @a paConfigs.
     1386 */
     1387static DECLCALLBACK(int) dbgfR3InterruptConfigEx(PUVM pUVM, PCDBGFINTERRUPTCONFIG paConfigs, size_t cConfigs)
     1388{
     1389    PVM pVM = pUVM->pVM;
     1390    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     1391
     1392    /*
     1393     * Apply the changes.
     1394     */
     1395    bool fChanged;
     1396    for (uint32_t i = 0; i < cConfigs; i++)
     1397    {
     1398        /*
     1399         * Hardware interrupts.
     1400         */
     1401        if (paConfigs[i].enmHardState == DBGFINTERRUPTSTATE_ENABLED)
     1402        {
     1403            fChanged = ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmHardIntBreakpoints, paConfigs[i].iInterrupt) == false;
     1404            if (fChanged)
     1405            {
     1406                Assert(pVM->dbgf.s.cHardIntBreakpoints < 256);
     1407                pVM->dbgf.s.cHardIntBreakpoints++;
     1408            }
     1409        }
     1410        else if (paConfigs[i].enmHardState == DBGFINTERRUPTSTATE_DISABLED)
     1411        {
     1412            fChanged = ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmHardIntBreakpoints, paConfigs[i].iInterrupt) == true;
     1413            if (fChanged)
     1414            {
     1415                Assert(pVM->dbgf.s.cHardIntBreakpoints > 0);
     1416                pVM->dbgf.s.cHardIntBreakpoints--;
     1417            }
     1418        }
     1419
     1420        /*
     1421         * Software interrupts.
     1422         */
     1423        if (paConfigs[i].enmHardState == DBGFINTERRUPTSTATE_ENABLED)
     1424        {
     1425            fChanged = ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmSoftIntBreakpoints, paConfigs[i].iInterrupt) == false;
     1426            if (fChanged)
     1427            {
     1428                Assert(pVM->dbgf.s.cSoftIntBreakpoints < 256);
     1429                pVM->dbgf.s.cSoftIntBreakpoints++;
     1430            }
     1431        }
     1432        else if (paConfigs[i].enmSoftState == DBGFINTERRUPTSTATE_DISABLED)
     1433        {
     1434            fChanged = ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmSoftIntBreakpoints, paConfigs[i].iInterrupt) == true;
     1435            if (fChanged)
     1436            {
     1437                Assert(pVM->dbgf.s.cSoftIntBreakpoints > 0);
     1438                pVM->dbgf.s.cSoftIntBreakpoints--;
     1439            }
     1440        }
     1441    }
     1442
     1443    /*
     1444     * Update the event bitmap entries and see if we need to notify other CPUs.
     1445     */
     1446    fChanged = false;
     1447    if (pVM->dbgf.s.cHardIntBreakpoints > 0)
     1448        fChanged |= ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_INTERRUPT_HARDWARE) == false;
     1449    else
     1450        fChanged |= ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_INTERRUPT_HARDWARE) == true;
     1451
     1452    if (pVM->dbgf.s.cSoftIntBreakpoints > 0)
     1453        fChanged |= ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_INTERRUPT_SOFTWARE) == false;
     1454    else
     1455        fChanged |= ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_INTERRUPT_SOFTWARE) == true;
     1456
     1457    int rc = VINF_SUCCESS;
     1458    if (fChanged && pVM->cCpus > 1)
     1459        rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3EventConfigNotifyAllCpus, NULL);
     1460    return rc;
     1461}
     1462
     1463
     1464/**
     1465 * Changes
     1466 *
     1467 * @returns VBox status code.
     1468 * @param   pUVM        The user mode VM handle.
     1469 * @param   paConfigs   The events to query and where to return the state.
     1470 * @param   cConfigs    The number of elements in @a paConfigs.
     1471 * @sa      DBGFR3InterruptConfigHardware, DBGFR3InterruptConfigSoftware
     1472 */
     1473VMMR3DECL(int) DBGFR3InterruptConfigEx(PUVM pUVM, PCDBGFINTERRUPTCONFIG paConfigs, size_t cConfigs)
     1474{
     1475    /*
     1476     * Validate input.
     1477     */
     1478    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
     1479    size_t i = cConfigs;
     1480    while (i-- > 0)
     1481    {
     1482        AssertReturn(paConfigs[i].enmHardState <= DBGFINTERRUPTSTATE_DONT_TOUCH, VERR_INVALID_PARAMETER);
     1483        AssertReturn(paConfigs[i].enmSoftState <= DBGFINTERRUPTSTATE_DONT_TOUCH, VERR_INVALID_PARAMETER);
     1484    }
     1485
     1486    /*
     1487     * Apply the changes in EMT(0).
     1488     */
     1489    return VMR3ReqPriorityCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3InterruptConfigEx, 3, pUVM, paConfigs, cConfigs);
     1490}
     1491
     1492
     1493/**
     1494 * Configures interception of a hardware interrupt.
     1495 *
     1496 * @returns VBox status code.
     1497 * @param   pUVM        The user mode VM handle.
     1498 * @param   iInterrupt  The interrupt number.
     1499 * @param   fEnabled    Whether interception is enabled or not.
     1500 * @sa      DBGFR3InterruptSoftwareConfig, DBGFR3InterruptConfigEx
     1501 */
     1502VMMR3DECL(int) DBGFR3InterruptHardwareConfig(PUVM pUVM, uint8_t iInterrupt, bool fEnabled)
     1503{
     1504    /*
     1505     * Convert to DBGFR3InterruptConfigEx call.
     1506     */
     1507    DBGFINTERRUPTCONFIG IntCfg = { iInterrupt, (uint8_t)fEnabled, DBGFINTERRUPTSTATE_DONT_TOUCH };
     1508    return DBGFR3InterruptConfigEx(pUVM, &IntCfg, 1);
     1509}
     1510
     1511
     1512/**
     1513 * Configures interception of a software interrupt.
     1514 *
     1515 * @returns VBox status code.
     1516 * @param   pUVM        The user mode VM handle.
     1517 * @param   iInterrupt  The interrupt number.
     1518 * @param   fEnabled    Whether interception is enabled or not.
     1519 * @sa      DBGFR3InterruptHardwareConfig, DBGFR3InterruptConfigEx
     1520 */
     1521VMMR3DECL(int) DBGFR3InterruptSoftwareConfig(PUVM pUVM, uint8_t iInterrupt, bool fEnabled)
     1522{
     1523    /*
     1524     * Convert to DBGFR3InterruptConfigEx call.
     1525     */
     1526    DBGFINTERRUPTCONFIG IntCfg = { iInterrupt, DBGFINTERRUPTSTATE_DONT_TOUCH, (uint8_t)fEnabled };
     1527    return DBGFR3InterruptConfigEx(pUVM, &IntCfg, 1);
     1528}
     1529
     1530
     1531/**
     1532 * Checks whether interception is enabled for a hardware interrupt.
     1533 *
     1534 * @returns true if enabled, false if not or invalid input.
     1535 * @param   pUVM        The user mode VM handle.
     1536 * @param   iInterrupt  The interrupt number.
     1537 * @sa      DBGFR3InterruptSoftwareIsEnabled, DBGF_IS_HARDWARE_INT_ENABLED,
     1538 *          DBGF_IS_SOFTWARE_INT_ENABLED
     1539 */
     1540VMMR3DECL(int) DBGFR3InterruptHardwareIsEnabled(PUVM pUVM, uint8_t iInterrupt)
     1541{
     1542    /*
     1543     * Validate input.
     1544     */
     1545    UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
     1546    PVM pVM = pUVM->pVM;
     1547    VM_ASSERT_VALID_EXT_RETURN(pVM, false);
     1548
     1549    /*
     1550     * Check it.
     1551     */
     1552    return ASMBitTest(&pVM->dbgf.s.bmHardIntBreakpoints, iInterrupt);
     1553}
     1554
     1555
     1556/**
     1557 * Checks whether interception is enabled for a software interrupt.
     1558 *
     1559 * @returns true if enabled, false if not or invalid input.
     1560 * @param   pUVM        The user mode VM handle.
     1561 * @param   iInterrupt  The interrupt number.
     1562 * @sa      DBGFR3InterruptHardwareIsEnabled, DBGF_IS_SOFTWARE_INT_ENABLED,
     1563 *          DBGF_IS_HARDWARE_INT_ENABLED,
     1564 */
     1565VMMR3DECL(int) DBGFR3InterruptSoftwareIsEnabled(PUVM pUVM, uint8_t iInterrupt)
     1566{
     1567    /*
     1568     * Validate input.
     1569     */
     1570    UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
     1571    PVM pVM = pUVM->pVM;
     1572    VM_ASSERT_VALID_EXT_RETURN(pVM, false);
     1573
     1574    /*
     1575     * Check it.
     1576     */
     1577    return ASMBitTest(&pVM->dbgf.s.bmSoftIntBreakpoints, iInterrupt);
     1578}
     1579
     1580
     1581
     1582/**
    12201583 * Call this to single step programmatically.
    12211584 *
  • trunk/src/VBox/VMM/VMMR3/DBGFBp.cpp

    r58903 r58909  
    103103{
    104104    /*
    105      * Determine which array to search.
    106      */
     105     * Determine which array to search and where in the array to start
     106     * searching (latter for grouping similar BPs, reducing runtime overhead).
     107     */
     108    unsigned    iStart;
    107109    unsigned    cBps;
    108     uint32_t   *pcBpsCur;
    109110    PDBGFBP     paBps;
    110111    switch (enmType)
     
    113114            cBps = RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints);
    114115            paBps = &pVM->dbgf.s.aHwBreakpoints[0];
    115             pcBpsCur = &pVM->dbgf.s.cHwBreakpoints;
     116            iStart = 0;
    116117            break;
    117118
    118119        case DBGFBPTYPE_INT3:
    119120        case DBGFBPTYPE_REM:
     121        case DBGFBPTYPE_PORT_IO:
     122        case DBGFBPTYPE_MMIO:
    120123            cBps = RT_ELEMENTS(pVM->dbgf.s.aBreakpoints);
    121124            paBps = &pVM->dbgf.s.aBreakpoints[0];
    122             pcBpsCur = &pVM->dbgf.s.cBreakpoints;
     125            if (enmType == DBGFBPTYPE_PORT_IO)
     126                iStart = cBps / 4 * 2;
     127            else if (enmType == DBGFBPTYPE_MMIO)
     128                iStart = cBps / 4 * 1;
     129            else if (enmType == DBGFBPTYPE_REM)
     130                iStart = cBps / 4 * 3;
     131            else
     132                iStart = 0;
    123133            break;
    124134
     
    129139
    130140    /*
    131      * Search.
    132      */
    133     for (unsigned iBp = 0; iBp < cBps; iBp++)
     141     * Search for a free breakpoint entry.
     142     */
     143    unsigned iBp;
     144    for (iBp = iStart; iBp < cBps; iBp++)
    134145        if (paBps[iBp].enmType == DBGFBPTYPE_FREE)
     146            break;
     147    if (iBp >= cBps && iStart != 0)
     148        for (iBp = 0; iBp < cBps; iBp++)
     149            if (paBps[iBp].enmType == DBGFBPTYPE_FREE)
     150                break;
     151    if (iBp < cBps)
     152    {
     153        /*
     154         * Return what we found.
     155         */
     156        paBps[iBp].fEnabled = false;
     157        paBps[iBp].cHits    = 0;
     158        paBps[iBp].enmType  = enmType;
     159        return &paBps[iBp];
     160    }
     161
     162    LogFlow(("dbgfR3BpAlloc: returns NULL - we're out of breakpoint slots! cBps=%u\n", cBps));
     163    return NULL;
     164}
     165
     166
     167/**
     168 * Updates IOM on whether we've got any armed I/O port or MMIO breakpoints.
     169 *
     170 * @returns VINF_SUCCESS
     171 * @param   pVM         The cross context VM structure.
     172 * @param   enmType     The breakpoint type.
     173 * @param   pOpt        The breakpoint optimization structure to update.
     174 */
     175static int dbgfR3BpUpdateSearchOptimizations(PVM pVM, DBGFBPTYPE enmType, PDBGFBPSEARCHOPT pOpt)
     176{
     177    DBGFBPSEARCHOPT Opt  = { UINT32_MAX, 0 };
     178
     179    for (uint32_t iBp = 0; iBp < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints); iBp++)
     180        if (   pVM->dbgf.s.aBreakpoints[iBp].enmType == enmType
     181            && pVM->dbgf.s.aBreakpoints[iBp].fEnabled)
    135182        {
    136             ++*pcBpsCur;
    137             paBps[iBp].cHits   = 0;
    138             paBps[iBp].enmType = enmType;
    139             return &paBps[iBp];
     183            if (Opt.iStartSearch > iBp)
     184                Opt.iStartSearch = iBp;
     185            Opt.cToSearch = iBp - Opt.iStartSearch + 1;
    140186        }
    141187
    142     LogFlow(("dbgfR3BpAlloc: returns NULL - we're out of breakpoint slots! %u/%u\n", *pcBpsCur, cBps));
    143     return NULL;
     188    *pOpt = Opt;
     189    return VINF_SUCCESS;
    144190}
    145191
     
    176222        case DBGFBPTYPE_INT3:
    177223        case DBGFBPTYPE_REM:
     224        case DBGFBPTYPE_PORT_IO:
     225        case DBGFBPTYPE_MMIO:
    178226            break;
    179227
     
    248296
    249297        case DBGFBPTYPE_REG:
    250             Assert(pVM->dbgf.s.cHwBreakpoints > 0);
    251             pVM->dbgf.s.cHwBreakpoints--;
     298            Assert(pBp - &pVM->dbgf.s.aHwBreakpoints[0] < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints));
    252299            break;
    253300
    254301        case DBGFBPTYPE_INT3:
    255302        case DBGFBPTYPE_REM:
    256             Assert(pVM->dbgf.s.cBreakpoints > 0);
    257             pVM->dbgf.s.cBreakpoints--;
     303        case DBGFBPTYPE_PORT_IO:
     304        case DBGFBPTYPE_MMIO:
     305            Assert(pBp - &pVM->dbgf.s.aBreakpoints[0] < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints));
    258306            break;
    259307
     
    264312    }
    265313    pBp->enmType = DBGFBPTYPE_FREE;
     314    NOREF(pVM);
    266315}
    267316
     
    325374    ASMCompilerBarrier();
    326375    pBp->fEnabled       = true;
     376    dbgfR3BpUpdateSearchOptimizations(pVM, DBGFBPTYPE_INT3, &pVM->dbgf.s.Int3);
    327377
    328378    /*
     
    360410     * This must be done on EMT.
    361411     */
    362     /** @todo SMP? */
    363     int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpSetInt3, 5,
     412    int rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3BpSetInt3, 5,
    364413                              pUVM, pAddress, &iHitTrigger, &iHitDisable, piBp);
    365414    LogFlow(("DBGFR3BpSet: returns %Rrc\n", rc));
     
    556605     * This must be done on EMT.
    557606     */
    558     int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpSetReg, 7,
     607    int rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3BpSetReg, 7,
    559608                              pUVM, pAddress, &iHitTrigger, &iHitDisable, fType, cb, piBp);
    560609    LogFlow(("DBGFR3BpSetReg: returns %Rrc\n", rc));
     
    567616 * @callback_method_impl{FNVMMEMTRENDEZVOUS}
    568617 */
    569 DECLCALLBACK(VBOXSTRICTRC) dbgfR3BpRegRecalcOnCpu(PVM pVM, PVMCPU pVCpu, void *pvUser)
     618static DECLCALLBACK(VBOXSTRICTRC) dbgfR3BpRegRecalcOnCpu(PVM pVM, PVMCPU pVCpu, void *pvUser)
    570619{
    571620    NOREF(pVM); NOREF(pvUser);
     621
     622    /*
     623     * CPU 0 updates the enabled hardware breakpoint counts.
     624     */
     625    if (pVCpu->idCpu == 0)
     626    {
     627        pVM->dbgf.s.cEnabledHwBreakpoints   = 0;
     628        pVM->dbgf.s.cEnabledHwIoBreakpoints = 0;
     629
     630        for (uint32_t iBp = 0; iBp < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints); iBp++)
     631            if (   pVM->dbgf.s.aHwBreakpoints[iBp].fEnabled
     632                && pVM->dbgf.s.aHwBreakpoints[iBp].enmType == DBGFBPTYPE_REG)
     633            {
     634                pVM->dbgf.s.cEnabledHwBreakpoints   += 1;
     635                pVM->dbgf.s.cEnabledHwIoBreakpoints += pVM->dbgf.s.aHwBreakpoints[iBp].u.Reg.fType == X86_DR7_RW_IO;
     636            }
     637    }
     638
    572639    return CPUMRecalcHyperDRx(pVCpu, UINT8_MAX, false);
    573640}
     
    576643/**
    577644 * Arms a debug register breakpoint.
     645 *
    578646 * This is used to implement both DBGFR3BpSetReg() and DBGFR3BpEnable().
    579647 *
     
    581649 * @param   pVM         The cross context VM structure.
    582650 * @param   pBp         The breakpoint.
     651 * @thread  EMT(0)
    583652 */
    584653static int dbgfR3BpRegArm(PVM pVM, PDBGFBP pBp)
     
    591660/**
    592661 * Disarms a debug register breakpoint.
     662 *
    593663 * This is used to implement both DBGFR3BpClear() and DBGFR3BpDisable().
    594664 *
     
    596666 * @param   pVM         The cross context VM structure.
    597667 * @param   pBp         The breakpoint.
     668 * @thread  EMT(0)
    598669 */
    599670static int dbgfR3BpRegDisarm(PVM pVM, PDBGFBP pBp)
     
    615686 *                          Use ~(uint64_t) if it's never gonna be disabled.
    616687 * @param   piBp            Where to store the breakpoint id. (optional)
    617  * @thread  EMT
     688 * @thread  EMT(0)
    618689 * @internal
    619690 */
     
    707778     * This must be done on EMT.
    708779     */
    709     int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpSetREM, 5,
     780    int rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3BpSetREM, 5,
    710781                              pUVM, pAddress, &iHitTrigger, &iHitDisable, piBp);
    711782    LogFlow(("DBGFR3BpSetREM: returns %Rrc\n", rc));
     
    714785
    715786
    716 
    717787/**
    718788 * Updates IOM on whether we've got any armed I/O port or MMIO breakpoints.
     
    720790 * @returns VINF_SUCCESS
    721791 * @param   pVM         The cross context VM structure.
     792 * @thread  EMT(0)
    722793 */
    723794static int dbgfR3BpUpdateIom(PVM pVM)
    724795{
    725     unsigned cPortIo = 0;
    726     unsigned cMmio = 0;
    727     for (uint32_t iBp = 0; iBp < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints); iBp++)
    728         if (pVM->dbgf.s.aBreakpoints[iBp].fEnabled)
    729         {
    730             if (pVM->dbgf.s.aBreakpoints[iBp].enmType == DBGFBPTYPE_PORT_IO)
    731                 cPortIo++;
    732             else if (pVM->dbgf.s.aBreakpoints[iBp].enmType == DBGFBPTYPE_MMIO)
    733                 cMmio++;
    734         }
    735 
    736     pVM->dbgf.s.fHasPortIoBps = cPortIo != 0;
    737     pVM->dbgf.s.fHasMmioBps   = cMmio   != 0;
    738 
    739     IOMR3NotifyBreakpointCountChange(pVM, cPortIo, cMmio);
     796    dbgfR3BpUpdateSearchOptimizations(pVM, DBGFBPTYPE_PORT_IO, &pVM->dbgf.s.PortIo);
     797    if (pVM->dbgf.s.PortIo.cToSearch)
     798        ASMAtomicBitSet(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_BREAKPOINT_IO);
     799    else
     800        ASMAtomicBitClear(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_BREAKPOINT_IO);
     801
     802    dbgfR3BpUpdateSearchOptimizations(pVM, DBGFBPTYPE_MMIO, &pVM->dbgf.s.Mmio);
     803    if (pVM->dbgf.s.Mmio.cToSearch)
     804        ASMAtomicBitSet(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_BREAKPOINT_MMIO);
     805    else
     806        ASMAtomicBitClear(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_BREAKPOINT_MMIO);
     807
     808    IOMR3NotifyBreakpointCountChange(pVM, pVM->dbgf.s.PortIo.cToSearch != 0, pVM->dbgf.s.Mmio.cToSearch != 0);
    740809    return VINF_SUCCESS;
    741810}
     
    755824 *                          Use ~(uint64_t) if it's never gonna be disabled.
    756825 * @param   piBp            Where to store the breakpoint ID.
     826 * @thread  EMT(0)
    757827 */
    758828static DECLCALLBACK(int) dbgfR3BpSetPortIo(PUVM pUVM, RTIOPORT uPort, RTIOPORT cPorts, uint32_t fAccess,
     
    821891 *                          Use ~(uint64_t) if it's never gonna be disabled.
    822892 * @param   piBp            Where to store the breakpoint ID. Optional.
     893 * @thread  Any thread.
    823894 */
    824895VMMR3DECL(int)  DBGFR3BpSetPortIo(PUVM pUVM, RTIOPORT uPort, RTIOPORT cPorts, uint32_t fAccess,
     
    837908     */
    838909    uint32_t iBp = -1;
    839     int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpSetPortIo, 7,
     910    int rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3BpSetPortIo, 7,
    840911                              pUVM, uPort, cPorts, fAccess, &iHitTrigger, &iHitDisable, piBp);
    841912    if (piBp)
    842913        *piBp = iBp;
    843     LogFlow(("DBGFR3BpSetPortIo: returns %Rrc *piBp=%d\n", rc, iBp));
     914    LogFlow(("DBGFR3BpSetPortIo: returns %Rrc iBp=%d\n", rc, iBp));
    844915    return rc;
    845916}
     
    859930 *                          Use ~(uint64_t) if it's never gonna be disabled.
    860931 * @param   piBp            Where to store the breakpoint ID.
     932 * @thread  EMT(0)
    861933 */
    862934static DECLCALLBACK(int) dbgfR3BpSetMmio(PUVM pUVM, PCRTGCPHYS pGCPhys, uint32_t cb, uint32_t fAccess,
     
    927999 *                          Use ~(uint64_t) if it's never gonna be disabled.
    9281000 * @param   piBp            Where to store the breakpoint ID. Optional.
     1001 * @thread  Any thread.
    9291002 */
    9301003VMMR3DECL(int)  DBGFR3BpSetMmio(PUVM pUVM, RTGCPHYS GCPhys, uint32_t cb, uint32_t fAccess,
     
    9431016     */
    9441017    uint32_t iBp = -1;
    945     int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpSetMmio, 7,
     1018    int rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3BpSetMmio, 7,
    9461019                              pUVM, &GCPhys, cb, fAccess, &iHitTrigger, &iHitDisable, piBp);
    9471020    if (piBp)
    9481021        *piBp = iBp;
    949     LogFlow(("DBGFR3BpSetMmio: returns %Rrc *piBp=%d\n", rc, iBp));
     1022    LogFlow(("DBGFR3BpSetMmio: returns %Rrc iBp=%d\n", rc, iBp));
    9501023    return rc;
    9511024}
     
    9581031 * @param   pUVM        The user mode VM handle.
    9591032 * @param   iBp         The id of the breakpoint which should be removed (cleared).
    960  * @thread  EMT
     1033 * @thread  EMT(0)
    9611034 * @internal
    9621035 */
     
    9871060            case DBGFBPTYPE_INT3:
    9881061                rc = dbgfR3BpInt3Disarm(pUVM, pBp);
     1062                dbgfR3BpUpdateSearchOptimizations(pVM, DBGFBPTYPE_INT3, &pVM->dbgf.s.Int3);
    9891063                break;
    9901064
     
    10291103     * This must be done on EMT.
    10301104     */
    1031     int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpClear, 2, pUVM, iBp);
     1105    int rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3BpClear, 2, pUVM, iBp);
    10321106    LogFlow(("DBGFR3BpClear: returns %Rrc\n", rc));
    10331107    return rc;
     
    10411115 * @param   pUVM        The user mode VM handle.
    10421116 * @param   iBp         The id of the breakpoint which should be enabled.
    1043  * @thread  EMT
     1117 * @thread  EMT(0)
    10441118 * @internal
    10451119 */
     
    10731147
    10741148        case DBGFBPTYPE_INT3:
     1149            dbgfR3BpUpdateSearchOptimizations(pVM, DBGFBPTYPE_INT3, &pVM->dbgf.s.Int3);
    10751150            rc = dbgfR3BpInt3Arm(pUVM, pBp);
    10761151            break;
     
    11121187     * This must be done on EMT.
    11131188     */
    1114     int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpEnable, 2, pUVM, iBp);
     1189    int rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3BpEnable, 2, pUVM, iBp);
    11151190    LogFlow(("DBGFR3BpEnable: returns %Rrc\n", rc));
    11161191    return rc;
     
    11241199 * @param   pUVM        The user mode VM handle.
    11251200 * @param   iBp         The id of the breakpoint which should be disabled.
    1126  * @thread  EMT
     1201 * @thread  EMT(0)
    11271202 * @internal
    11281203 */
     
    11571232        case DBGFBPTYPE_INT3:
    11581233            rc = dbgfR3BpInt3Disarm(pUVM, pBp);
     1234            dbgfR3BpUpdateSearchOptimizations(pVM, DBGFBPTYPE_INT3, &pVM->dbgf.s.Int3);
    11591235            break;
    11601236
     
    11931269     * This must be done on EMT.
    11941270     */
    1195     int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpDisable, 2, pUVM, iBp);
     1271    int rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3BpDisable, 2, pUVM, iBp);
    11961272    LogFlow(("DBGFR3BpDisable: returns %Rrc\n", rc));
    11971273    return rc;
     
    12261302        {
    12271303            int rc = pfnCallback(pUVM, pvUser, &pVM->dbgf.s.aHwBreakpoints[i]);
    1228             if (RT_FAILURE(rc))
     1304            if (RT_FAILURE(rc) || rc == VINF_CALLBACK_RETURN)
    12291305                return rc;
    12301306        }
     
    12371313        {
    12381314            int rc = pfnCallback(pUVM, pvUser, &pVM->dbgf.s.aBreakpoints[i]);
    1239             if (RT_FAILURE(rc))
     1315            if (RT_FAILURE(rc) || rc == VINF_CALLBACK_RETURN)
    12401316                return rc;
    12411317        }
     
    12591335     * This must be done on EMT.
    12601336     */
    1261     int rc = VMR3ReqPriorityCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpEnum, 3, pUVM, pfnCallback, pvUser);
     1337    int rc = VMR3ReqPriorityCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3BpEnum, 3, pUVM, pfnCallback, pvUser);
    12621338    LogFlow(("DBGFR3BpClear: returns %Rrc\n", rc));
    12631339    return rc;
  • trunk/src/VBox/VMM/VMMR3/HM.cpp

    r58396 r58909  
    252252    EXIT_REASON(SVM_EXIT_LDTR_READ          ,104, "Read LDTR."),
    253253    EXIT_REASON(SVM_EXIT_TR_READ            ,105, "Read TR."),
    254     EXIT_REASON(SVM_EXIT_TR_READ            ,106, "Write IDTR."),
    255     EXIT_REASON(SVM_EXIT_TR_READ            ,107, "Write GDTR."),
    256     EXIT_REASON(SVM_EXIT_TR_READ            ,108, "Write LDTR."),
    257     EXIT_REASON(SVM_EXIT_TR_READ            ,109, "Write TR."),
     254    EXIT_REASON(SVM_EXIT_IDTR_WRITE         ,106, "Write IDTR."),
     255    EXIT_REASON(SVM_EXIT_GDTR_WRITE         ,107, "Write GDTR."),
     256    EXIT_REASON(SVM_EXIT_LDTR_WRITE         ,108, "Write LDTR."),
     257    EXIT_REASON(SVM_EXIT_TR_WRITE           ,109, "Write TR."),
    258258    EXIT_REASON(SVM_EXIT_RDTSC              ,110, "RDTSC instruction."),
    259259    EXIT_REASON(SVM_EXIT_RDPMC              ,111, "RDPMC instruction."),
     
    287287    EXIT_REASON(SVM_EXIT_MWAIT              ,139, "MWAIT instruction."),
    288288    EXIT_REASON(SVM_EXIT_MWAIT_ARMED        ,140, "MWAIT instruction when armed."),
     289    EXIT_REASON(SVM_EXIT_XSETBV             ,141, "XSETBV instruction."),
    289290    EXIT_REASON(SVM_EXIT_NPF                ,1024, "Nested paging fault."),
     291    EXIT_REASON(SVM_EXIT_AVIC_INCOMPLETE_IPI,1025, "AVIC incomplete IPI delivery."),
     292    EXIT_REASON(SVM_EXIT_AVIC_NOACCEL       ,1026, "AVIC unaccelerated register."),
    290293    EXIT_REASON_NIL()
    291294};
  • trunk/src/VBox/VMM/VMMR3/IOM.cpp

    r58903 r58909  
    16531653 *
    16541654 * @param   pVM         The cross context VM structure.
    1655  * @param   cPortIo     Number of armed I/O port breakpoints.
    1656  * @param   cMmio       Number of armed MMIO breakpoints.
    1657  */
    1658 VMMR3_INT_DECL(void) IOMR3NotifyBreakpointCountChange(PVM pVM, unsigned cPortIo, unsigned cMmio)
     1655 * @param   fPortIo     True if there are armed I/O port breakpoints.
     1656 * @param   fMmio       True if there are armed MMIO breakpoints.
     1657 */
     1658VMMR3_INT_DECL(void) IOMR3NotifyBreakpointCountChange(PVM pVM, bool fPortIo, bool fMmio)
    16591659{
    16601660    /** @todo I/O breakpoints. */
  • trunk/src/VBox/VMM/VMMRZ/DBGFRZ.cpp

    r58903 r58909  
    5757     * A breakpoint?
    5858     */
    59     if (uDr6 & (X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3))
     59    AssertCompile(X86_DR6_B0 == 1 && X86_DR6_B1 == 2 && X86_DR6_B2 == 4 && X86_DR6_B3 == 8);
     60    if (   (uDr6 & (X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3))
     61        && pVM->dbgf.s.cEnabledHwBreakpoints > 0)
    6062    {
    61         Assert(X86_DR6_B0 == 1 && X86_DR6_B1 == 2 && X86_DR6_B2 == 4 && X86_DR6_B3 == 8);
    6263        for (unsigned iBp = 0; iBp < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints); iBp++)
    6364        {
     
    125126     * Don't bother if we don't have any breakpoints.
    126127     */
    127     if (pVM->dbgf.s.cBreakpoints > 0)
     128    unsigned cToSearch = pVM->dbgf.s.Int3.cToSearch;
     129    if (cToSearch > 0)
    128130    {
    129131        RTGCPTR pPc;
     
    137139        AssertRCReturn(rc, rc);
    138140
    139         for (unsigned iBp = 0; iBp < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints); iBp++)
     141        unsigned iBp = pVM->dbgf.s.Int3.iStartSearch;
     142        while (cToSearch-- > 0)
    140143        {
    141             if (    pVM->dbgf.s.aBreakpoints[iBp].u.GCPtr == (RTGCUINTPTR)pPc
    142                 &&  pVM->dbgf.s.aBreakpoints[iBp].enmType == DBGFBPTYPE_INT3)
     144            if (   pVM->dbgf.s.aBreakpoints[iBp].u.GCPtr == (RTGCUINTPTR)pPc
     145                && pVM->dbgf.s.aBreakpoints[iBp].enmType == DBGFBPTYPE_INT3)
    143146            {
    144147                pVM->dbgf.s.aBreakpoints[iBp].cHits++;
     
    152155                     : VINF_EM_DBG_BREAKPOINT;
    153156            }
     157            iBp++;
    154158        }
    155159    }
  • trunk/src/VBox/VMM/include/DBGFInternal.h

    r58903 r58909  
    170170
    171171
    172 
    173 /**
    174  * Converts a DBGF pointer into a VM pointer.
    175  * @returns Pointer to the VM structure the CPUM is part of.
    176  * @param   pDBGF   Pointer to DBGF instance data.
    177  */
    178 #define DBGF2VM(pDBGF)  ( (PVM)((char*)pDBGF - pDBGF->offVM) )
     172/**
     173 * Breakpoint search optimization.
     174 */
     175typedef struct DBGFBPSEARCHOPT
     176{
     177    /** Where to start searching for hits.
     178     * (First enabled is #DBGF::aBreakpoints[iStartSearch]). */
     179    uint32_t volatile       iStartSearch;
     180    /** The number of aBreakpoints entries to search.
     181     * (Last enabled is #DBGF::aBreakpoints[iStartSearch + cToSearch - 1])  */
     182    uint32_t volatile       cToSearch;
     183} DBGFBPSEARCHOPT;
     184/** Pointer to a breakpoint search optimziation structure. */
     185typedef DBGFBPSEARCHOPT *PDBGFBPSEARCHOPT;
     186
    179187
    180188
     
    184192typedef struct DBGF
    185193{
    186     /** Offset to the VM structure. */
    187     int32_t                     offVM;
    188 
    189     /** Set if we've got armed port I/O breakpoints. */
    190     bool                        fHasPortIoBps : 1;
    191     /** Set if we've got armed memory mapped I/O breakpoints. */
    192     bool                        fHasMmioBps : 1;
     194    /** Bitmap of enabled hardware interrupt breakpoints. */
     195    uint32_t                    bmHardIntBreakpoints[256 / 32];
     196    /** Bitmap of enabled software interrupt breakpoints. */
     197    uint32_t                    bmSoftIntBreakpoints[256 / 32];
     198    /** Bitmap of selected events.
     199     * This includes non-selectable events too for simplicity, we maintain the
     200     * state for some of these, as it may come in handy. */
     201    uint32_t                    bmSelectedEvents[(DBGFEVENT_END + 31) / 32];
     202
     203    /** Enabled hardware interrupt breakpoints. */
     204    uint32_t                    cHardIntBreakpoints;
     205    /** Enabled software interrupt breakpoints. */
     206    uint32_t                    cSoftIntBreakpoints;
     207
     208    /** Number of selected events. */
     209    uint32_t                    cSelectedEvents;
    193210
    194211    /** Debugger Attached flag.
     
    208225     */
    209226    RTPINGPONG                  PingPong;
     227    RTHCUINTPTR                 uPtrPadding; /**< Alignment padding. */
    210228
    211229    /** The Event to the debugger.
     
    227245    DBGFCMDDATA                 VMMCmdData;
    228246
    229     /** The number of hardware breakpoints. */
    230     uint32_t                    cHwBreakpoints;
    231     /** The number of active breakpoints. */
    232     uint32_t                    cBreakpoints;
     247    uint32_t                    u32Padding; /**< Alignment padding. */
     248
     249    /** The number of enabled hardware breakpoints. */
     250    uint8_t                     cEnabledHwBreakpoints;
     251    /** The number of enabled hardware I/O breakpoints. */
     252    uint8_t                     cEnabledHwIoBreakpoints;
     253    uint8_t                     abPadding[2]; /**< Unused padding space up for grabs. */
     254
    233255    /** Array of hardware breakpoints. (0..3)
    234256     * This is shared among all the CPUs because life is much simpler that way. */
     
    238260    DBGFBP                      aBreakpoints[32];
    239261
     262    /** MMIO breakpoint search optimizations. */
     263    DBGFBPSEARCHOPT             Mmio;
     264    /** I/O port breakpoint search optimizations. */
     265    DBGFBPSEARCHOPT             PortIo;
     266    /** INT3 breakpoint search optimizations. */
     267    DBGFBPSEARCHOPT             Int3;
    240268} DBGF;
     269AssertCompileMemberAlignment(DBGF, DbgEvent, 8);
     270AssertCompileMemberAlignment(DBGF, aHwBreakpoints, 8);
     271AssertCompileMemberAlignment(DBGF, bmHardIntBreakpoints, 8);
    241272/** Pointer to DBGF Data. */
    242273typedef DBGF *PDBGF;
     274
     275
     276/**
     277 * Event state (for DBGFCPU::aEvents).
     278 */
     279typedef enum DBGFEVENTSTATE
     280{
     281    /** Invalid event stack entry. */
     282    DBGFEVENTSTATE_INVALID = 0,
     283    /** The current event stack entry. */
     284    DBGFEVENTSTATE_CURRENT,
     285    /** Event that should be ignored but hasn't yet actually been ignored. */
     286    DBGFEVENTSTATE_IGNORE,
     287    /** Event that has been ignored but may be restored to IGNORE should another
     288     * debug event fire before the instruction is completed. */
     289    DBGFEVENTSTATE_RESTORABLE,
     290    /** End of valid events.   */
     291    DBGFEVENTSTATE_END,
     292    /** Make sure we've got a 32-bit type. */
     293    DBGFEVENTSTATE_32BIT_HACK = 0x7fffffff
     294} DBGFEVENTSTATE;
    243295
    244296
     
    259311     * encounters a breakpoint and returns VINF_EM_DBG_BREAKPOINT. This is
    260312     * currently not used for REM breakpoints because of the lazy coupling
    261      * between VBox and REM. */
     313     * between VBox and REM.
     314     *
     315     * @todo drop this in favor of aEvents!  */
    262316    uint32_t                iActiveBp;
    263317    /** Set if we're singlestepping in raw mode.
     
    265319    bool                    fSingleSteppingRaw;
    266320
    267     /** Padding the structure to 16 bytes. */
    268     bool                    afReserved[7];
     321    /** Alignment padding. */
     322    bool                    afPadding[3];
     323
     324    /** The number of events on the stack (aEvents).
     325     * The pending event is the last one (aEvents[cEvents - 1]), but only when
     326     * enmState is DBGFEVENTSTATE_CURRENT. */
     327    uint32_t                cEvents;
     328    /** Events - current, ignoring and ignored.
     329     *
     330     * We maintain a stack of events in order to try avoid ending up in an infinit
     331     * loop when resuming after an event fired.  There are cases where we may end
     332     * generating additional events before the instruction can be executed
     333     * successfully.  Like for instance an XCHG on MMIO with separate read and write
     334     * breakpoints, or a MOVSB instruction working on breakpointed MMIO as both
     335     * source and destination.
     336     *
     337     * So, when resuming after dropping into the debugger for an event, we convert
     338     * the DBGFEVENTSTATE_CURRENT event into a DBGFEVENTSTATE_IGNORE event, leaving
     339     * cEvents unchanged.  If the event is reported again, we will ignore it and
     340     * tell the reporter to continue executing.  The event change to the
     341     * DBGFEVENTSTATE_RESTORABLE state.
     342     *
     343     * Currently, the event reporter has to figure out that it is a nested event and
     344     * tell DBGF to restore DBGFEVENTSTATE_RESTORABLE events (and keep
     345     * DBGFEVENTSTATE_IGNORE, should they happen out of order for some weird
     346     * reason).
     347     */
     348    struct
     349    {
     350        /** The event details. */
     351        DBGFEVENT           Event;
     352        /** The RIP at which this happend (for validating ignoring). */
     353        uint64_t            rip;
     354        /** The event state. */
     355        DBGFEVENTSTATE      enmState;
     356        /** Alignment padding. */
     357        uint32_t            u32Alignment;
     358    } aEvents[3];
    269359} DBGFCPU;
     360AssertCompileMemberAlignment(DBGFCPU, aEvents, 8);
     361AssertCompileMemberSizeAlignment(DBGFCPU, aEvents[0], 8);
    270362/** Pointer to DBGFCPU data. */
    271363typedef DBGFCPU *PDBGFCPU;
  • trunk/src/VBox/VMM/testcase/tstVMStruct.h

    r58781 r58909  
    209209
    210210    GEN_CHECK_SIZE(DBGF);
    211     GEN_CHECK_OFF(DBGF, offVM);
     211    GEN_CHECK_OFF(DBGF, bmHardIntBreakpoints);
     212    GEN_CHECK_OFF(DBGF, bmSoftIntBreakpoints);
     213    GEN_CHECK_OFF(DBGF, bmSelectedEvents);
     214    GEN_CHECK_OFF(DBGF, cHardIntBreakpoints);
     215    GEN_CHECK_OFF(DBGF, cSoftIntBreakpoints);
     216    GEN_CHECK_OFF(DBGF, cSelectedEvents);
    212217    GEN_CHECK_OFF(DBGF, fAttached);
    213218    GEN_CHECK_OFF(DBGF, fStoppedInHyper);
     
    218223    //GEN_CHECK_OFF(DBGF, pInfoFirst);
    219224    //GEN_CHECK_OFF(DBGF, InfoCritSect);
    220     GEN_CHECK_OFF(DBGF, cHwBreakpoints);
    221     GEN_CHECK_OFF(DBGF, cBreakpoints);
     225    GEN_CHECK_OFF(DBGF, cEnabledHwBreakpoints);
     226    GEN_CHECK_OFF(DBGF, cEnabledHwIoBreakpoints);
    222227    GEN_CHECK_OFF(DBGF, aHwBreakpoints);
    223228    GEN_CHECK_OFF(DBGF, aBreakpoints);
     229    GEN_CHECK_OFF(DBGF, Mmio);
     230    GEN_CHECK_OFF(DBGF, PortIo);
     231    GEN_CHECK_OFF(DBGF, Int3);
    224232    //GEN_CHECK_OFF(DBGF, hAsDbLock);
    225233    //GEN_CHECK_OFF(DBGF, hRegDbLock);
     
    231239    GEN_CHECK_OFF(DBGFCPU, iActiveBp);
    232240    GEN_CHECK_OFF(DBGFCPU, fSingleSteppingRaw);
     241    GEN_CHECK_OFF(DBGFCPU, cEvents);
     242    GEN_CHECK_OFF(DBGFCPU, aEvents);
     243    GEN_CHECK_OFF(DBGFCPU, aEvents[1]);
     244    GEN_CHECK_OFF(DBGFCPU, aEvents[1].Event);
     245    GEN_CHECK_OFF(DBGFCPU, aEvents[1].Event.enmCtx);
     246    GEN_CHECK_OFF(DBGFCPU, aEvents[1].Event.enmType);
     247    GEN_CHECK_OFF(DBGFCPU, aEvents[1].Event.u.Bp.iBp);
     248    GEN_CHECK_OFF(DBGFCPU, aEvents[1].rip);
     249    GEN_CHECK_OFF(DBGFCPU, aEvents[1].enmState);
    233250    //GEN_CHECK_OFF(DBGFCPU, pGuestRegSet);
    234251    //GEN_CHECK_OFF(DBGFCPU, pHyperRegSet);
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