VirtualBox

Changeset 58903 in vbox


Ignore:
Timestamp:
Nov 27, 2015 3:07:07 PM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
104399
Message:

DBGF: I/O and MMIO breakpoint API changes.

Location:
trunk
Files:
9 edited

Legend:

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

    r58891 r58903  
    493493    /** Recompiler. */
    494494    DBGFBPTYPE_REM,
     495    /** Port I/O breakpoint. */
     496    DBGFBPTYPE_PORT_IO,
     497    /** Memory mapped I/O breakpoint. */
     498    DBGFBPTYPE_MMIO,
    495499    /** ensure 32-bit size. */
    496500    DBGFBPTYPE_32BIT_HACK = 0x7fffffff
    497501} DBGFBPTYPE;
    498502
     503
     504/** @name DBGFBPIOACCESS_XXX - I/O (port + mmio) access types.
     505 * @{ */
     506/** Byte sized read accesses. */
     507#define DBGFBPIOACCESS_READ_BYTE            UINT32_C(0x00000001)
     508/** Word sized accesses. */
     509#define DBGFBPIOACCESS_READ_WORD            UINT32_C(0x00000002)
     510/** Double word sized accesses. */
     511#define DBGFBPIOACCESS_READ_DWORD           UINT32_C(0x00000004)
     512/** Quad word sized accesses - not available for I/O ports. */
     513#define DBGFBPIOACCESS_READ_QWORD           UINT32_C(0x00000008)
     514/** Other sized accesses - not available for I/O ports. */
     515#define DBGFBPIOACCESS_READ_OTHER           UINT32_C(0x00000010)
     516/** Read mask. */
     517#define DBGFBPIOACCESS_READ_MASK            UINT32_C(0x0000001f)
     518
     519/** Byte sized write accesses. */
     520#define DBGFBPIOACCESS_WRITE_BYTE           UINT32_C(0x00000100)
     521/** Word sized write accesses. */
     522#define DBGFBPIOACCESS_WRITE_WORD           UINT32_C(0x00000200)
     523/** Double word sized write accesses. */
     524#define DBGFBPIOACCESS_WRITE_DWORD          UINT32_C(0x00000400)
     525/** Quad word sized write accesses - not available for I/O ports. */
     526#define DBGFBPIOACCESS_WRITE_QWORD          UINT32_C(0x00000800)
     527/** Other sized write accesses - not available for I/O ports. */
     528#define DBGFBPIOACCESS_WRITE_OTHER          UINT32_C(0x00001000)
     529/** Write mask. */
     530#define DBGFBPIOACCESS_WRITE_MASK           UINT32_C(0x00001f00)
     531
     532/** All kind of access (read, write, all sizes). */
     533#define DBGFBPIOACCESS_ALL                  UINT32_C(0x00001f1f)
     534
     535/** The acceptable mask for I/O ports.   */
     536#define DBGFBPIOACCESS_VALID_MASK_PORT_IO   UINT32_C(0x00000303)
     537/** The acceptable mask for MMIO.   */
     538#define DBGFBPIOACCESS_VALID_MASK_MMIO      UINT32_C(0x00001f1f)
     539/** @} */
    499540
    500541/**
     
    510551     * Use ~(uint64_t)0 if it should never stop. */
    511552    uint64_t        iHitDisable;
    512     /** The Flat GC address of the breakpoint.
    513      * (PC register value if REM type?) */
    514     RTGCUINTPTR     GCPtr;
    515553    /** The breakpoint id. */
    516     uint32_t        iBp;
     554    uint16_t        iBp;
    517555    /** The breakpoint status - enabled or disabled. */
    518556    bool            fEnabled;
    519 
    520557    /** The breakpoint type. */
    521558    DBGFBPTYPE      enmType;
    522 
    523 #if GC_ARCH_BITS == 64
    524     uint32_t        u32Padding;
    525 #endif
    526559
    527560    /** Union of type specific data. */
    528561    union
    529562    {
     563        /** The flat GC address breakpoint address for REG, INT3 and REM breakpoints. */
     564        RTGCUINTPTR         GCPtr;
     565
    530566        /** Debug register data. */
    531567        struct DBGFBPREG
    532568        {
     569            /** The flat GC address of the breakpoint. */
     570            RTGCUINTPTR     GCPtr;
    533571            /** The debug register number. */
    534             uint8_t     iReg;
     572            uint8_t         iReg;
    535573            /** The access type (one of the X86_DR7_RW_* value). */
    536             uint8_t     fType;
     574            uint8_t         fType;
    537575            /** The access size. */
    538             uint8_t     cb;
     576            uint8_t         cb;
    539577        } Reg;
    540578        /** Recompiler breakpoint data. */
    541579        struct DBGFBPINT3
    542580        {
     581            /** The flat GC address of the breakpoint. */
     582            RTGCUINTPTR     GCPtr;
    543583            /** The byte value we replaced by the INT 3 instruction. */
    544             uint8_t     bOrg;
     584            uint8_t         bOrg;
    545585        } Int3;
    546586
     
    548588        struct DBGFBPREM
    549589        {
    550             /** nothing yet */
    551             uint8_t fDummy;
     590            /** The flat GC address of the breakpoint.
     591             * (PC register value?) */
     592            RTGCUINTPTR     GCPtr;
    552593        } Rem;
     594
     595        /** I/O port breakpoint data.   */
     596        struct DBGFBPPORTIO
     597        {
     598            /** The first port. */
     599            RTIOPORT        uPort;
     600            /** The number of ports. */
     601            RTIOPORT        cPorts;
     602            /** Valid DBGFBPIOACCESS_XXX selection, max DWORD size. */
     603            uint32_t        fAccess;
     604        } PortIo;
     605
     606        /** Memory mapped I/O breakpoint data. */
     607        struct DBGFBPMMIO
     608        {
     609            /** The first MMIO address. */
     610            RTGCPHYS        PhysAddr;
     611            /** The size of the MMIO range in bytes. */
     612            uint32_t        cb;
     613            /** Valid DBGFBPIOACCESS_XXX selection, max DWORD size. */
     614            uint32_t        fAccess;
     615        } Mmio;
     616
    553617        /** Paddind to ensure that the size is identical on win32 and linux. */
    554         uint64_t    u64Padding;
     618        uint64_t    u64Padding[2];
    555619    } u;
    556620} DBGFBP;
     621AssertCompileMembersAtSameOffset(DBGFBP, u.GCPtr, DBGFBP, u.Reg.GCPtr);
     622AssertCompileMembersAtSameOffset(DBGFBP, u.GCPtr, DBGFBP, u.Int3.GCPtr);
     623AssertCompileMembersAtSameOffset(DBGFBP, u.GCPtr, DBGFBP, u.Rem.GCPtr);
    557624
    558625/** Pointer to a breakpoint. */
     
    566633                               uint8_t fType, uint8_t cb, uint32_t *piBp);
    567634VMMR3DECL(int)  DBGFR3BpSetREM(PUVM pUVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable, uint32_t *piBp);
     635VMMR3DECL(int)  DBGFR3BpSetPortIo(PUVM pUVM, RTIOPORT uPort, RTIOPORT cPorts, uint32_t fAccess,
     636                                  uint64_t iHitTrigger, uint64_t iHitDisable, uint32_t *piBp);
     637VMMR3DECL(int)  DBGFR3BpSetMmio(PUVM pUVM, RTGCPHYS GCPhys, uint32_t cb, uint32_t fAccess,
     638                                uint64_t iHitTrigger, uint64_t iHitDisable, uint32_t *piBp);
    568639VMMR3DECL(int)  DBGFR3BpClear(PUVM pUVM, uint32_t iBp);
    569640VMMR3DECL(int)  DBGFR3BpEnable(PUVM pUVM, uint32_t iBp);
  • trunk/include/VBox/vmm/iom.h

    r58110 r58903  
    2929#include <VBox/types.h>
    3030#include <VBox/dis.h>
     31#include <VBox/vmm/dbgf.h>
    3132
    3233RT_C_DECLS_BEGIN
     
    338339VMMR3_INT_DECL(int)  IOMR3MmioDeregister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange);
    339340
     341VMMR3_INT_DECL(void) IOMR3NotifyBreakpointCountChange(PVM pVM, unsigned cPortIo, unsigned cMmio);
     342VMMR3_INT_DECL(void) IOMR3NotifyDebugEventChange(PVM pVM, DBGFEVENT enmEvent, bool fEnabled);
     343
    340344/** @} */
    341345#endif /* IN_RING3 */
  • trunk/src/VBox/Debugger/DBGCEmulateCodeView.cpp

    r58890 r58903  
    675675     * BP type and size.
    676676     */
    677     char chType;
    678     char cb = 1;
     677    DBGCCmdHlpPrintf(&pDbgc->CmdHlp, "%#4x %c ", pBp->iBp, pBp->fEnabled ? 'e' : 'd');
     678    bool fHasAddress = false;
    679679    switch (pBp->enmType)
    680680    {
    681681        case DBGFBPTYPE_INT3:
    682             chType = 'p';
     682            DBGCCmdHlpPrintf(&pDbgc->CmdHlp, " p %RGv", pBp->u.Int3.GCPtr);
     683            fHasAddress = true;
    683684            break;
    684685        case DBGFBPTYPE_REG:
     686        {
     687            char chType;
    685688            switch (pBp->u.Reg.fType)
    686689            {
     
    692695
    693696            }
    694             cb = pBp->u.Reg.cb;
    695             break;
     697            DBGCCmdHlpPrintf(&pDbgc->CmdHlp, "%d %c %RGv", pBp->u.Reg.cb, chType, pBp->u.Reg.GCPtr);
     698            fHasAddress = true;
     699            break;
     700        }
     701
    696702        case DBGFBPTYPE_REM:
    697             chType = 'r';
    698             break;
     703            DBGCCmdHlpPrintf(&pDbgc->CmdHlp, " r %RGv", pBp->u.Rem.GCPtr);
     704            fHasAddress = true;
     705            break;
     706
     707/** @todo realign the list when I/O and MMIO breakpoint command have been added and it's possible to test this code. */
     708        case DBGFBPTYPE_PORT_IO:
     709        case DBGFBPTYPE_MMIO:
     710        {
     711            uint32_t fAccess = pBp->enmType == DBGFBPTYPE_PORT_IO ? pBp->u.PortIo.fAccess : pBp->u.Mmio.fAccess;
     712            DBGCCmdHlpPrintf(&pDbgc->CmdHlp, pBp->enmType == DBGFBPTYPE_PORT_IO ?  " i" : " m");
     713            DBGCCmdHlpPrintf(&pDbgc->CmdHlp, " %c%c%c%c%c%c",
     714                             fAccess & DBGFBPIOACCESS_READ_MASK   ? 'r' : '-',
     715                             fAccess & DBGFBPIOACCESS_READ_BYTE   ? '1' : '-',
     716                             fAccess & DBGFBPIOACCESS_READ_WORD   ? '2' : '-',
     717                             fAccess & DBGFBPIOACCESS_READ_DWORD  ? '4' : '-',
     718                             fAccess & DBGFBPIOACCESS_READ_QWORD  ? '8' : '-',
     719                             fAccess & DBGFBPIOACCESS_READ_OTHER  ? '+' : '-');
     720            DBGCCmdHlpPrintf(&pDbgc->CmdHlp, " %c%c%c%c%c%c",
     721                             fAccess & DBGFBPIOACCESS_WRITE_MASK  ? 'w' : '-',
     722                             fAccess & DBGFBPIOACCESS_WRITE_BYTE  ? '1' : '-',
     723                             fAccess & DBGFBPIOACCESS_WRITE_WORD  ? '2' : '-',
     724                             fAccess & DBGFBPIOACCESS_WRITE_DWORD ? '4' : '-',
     725                             fAccess & DBGFBPIOACCESS_WRITE_QWORD ? '8' : '-',
     726                             fAccess & DBGFBPIOACCESS_WRITE_OTHER ? '+' : '-');
     727            if (pBp->enmType == DBGFBPTYPE_PORT_IO)
     728                DBGCCmdHlpPrintf(&pDbgc->CmdHlp, " %04x-%04x",
     729                                 pBp->u.PortIo.uPort, pBp->u.PortIo.uPort + pBp->u.PortIo.cPorts - 1);
     730            else
     731                DBGCCmdHlpPrintf(&pDbgc->CmdHlp, "%RGp LB %03x", pBp->u.Mmio.PhysAddr, pBp->u.Mmio.cb);
     732            break;
     733        }
     734
    699735        default:
    700             chType = '?';
    701             break;
    702     }
    703 
    704     DBGCCmdHlpPrintf(&pDbgc->CmdHlp, "%#4x %c %d %c %RGv %04RX64 (%04RX64 to ",
    705                      pBp->iBp, pBp->fEnabled ? 'e' : 'd', (int)cb, chType,
    706                      pBp->GCPtr, pBp->cHits, pBp->iHitTrigger);
     736            DBGCCmdHlpPrintf(&pDbgc->CmdHlp, " unknown type %d!!", pBp->enmType);
     737            AssertFailed();
     738            break;
     739
     740    }
    707741    if (pBp->iHitDisable == ~(uint64_t)0)
    708         DBGCCmdHlpPrintf(&pDbgc->CmdHlp, "~0)  ");
     742        DBGCCmdHlpPrintf(&pDbgc->CmdHlp, " %04RX64 (%04RX64 to ~0)  ", pBp->cHits, pBp->iHitTrigger);
    709743    else
    710         DBGCCmdHlpPrintf(&pDbgc->CmdHlp, "%04RX64)", pBp->iHitDisable);
    711 
    712     /*
    713      * Try resolve the address.
    714      */
    715     RTDBGSYMBOL Sym;
    716     RTINTPTR    off;
    717     DBGFADDRESS Addr;
    718     int rc = DBGFR3AsSymbolByAddr(pUVM, pDbgc->hDbgAs, DBGFR3AddrFromFlat(pDbgc->pUVM, &Addr, pBp->GCPtr),
    719                                   RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL, &off, &Sym, NULL);
    720     if (RT_SUCCESS(rc))
    721     {
    722         if (!off)
    723             DBGCCmdHlpPrintf(&pDbgc->CmdHlp, "%s", Sym.szName);
    724         else if (off > 0)
    725             DBGCCmdHlpPrintf(&pDbgc->CmdHlp, "%s+%RGv", Sym.szName, off);
    726         else
    727             DBGCCmdHlpPrintf(&pDbgc->CmdHlp, "%s-%RGv", Sym.szName, -off);
     744        DBGCCmdHlpPrintf(&pDbgc->CmdHlp, " %04RX64 (%04RX64 to %04RX64)", pBp->cHits, pBp->iHitTrigger, pBp->iHitDisable);
     745
     746    /*
     747     * Try resolve the address if it has one.
     748     */
     749    if (fHasAddress)
     750    {
     751        RTDBGSYMBOL Sym;
     752        RTINTPTR    off;
     753        DBGFADDRESS Addr;
     754        int rc = DBGFR3AsSymbolByAddr(pUVM, pDbgc->hDbgAs, DBGFR3AddrFromFlat(pDbgc->pUVM, &Addr, pBp->u.GCPtr),
     755                                      RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL, &off, &Sym, NULL);
     756        if (RT_SUCCESS(rc))
     757        {
     758            if (!off)
     759                DBGCCmdHlpPrintf(&pDbgc->CmdHlp, "%s", Sym.szName);
     760            else if (off > 0)
     761                DBGCCmdHlpPrintf(&pDbgc->CmdHlp, "%s+%RGv", Sym.szName, off);
     762            else
     763                DBGCCmdHlpPrintf(&pDbgc->CmdHlp, "%s-%RGv", Sym.szName, -off);
     764        }
    728765    }
    729766
  • trunk/src/VBox/VMM/VMMAll/DBGFAll.cpp

    r58123 r58903  
    6969    PCDBGFBP    pBp = &pVM->dbgf.s.aHwBreakpoints[0];
    7070    Assert(pBp->u.Reg.iReg == 0);
    71     return pBp->GCPtr;
     71    return pBp->u.Reg.GCPtr;
    7272}
    7373
     
    8383    PCDBGFBP    pBp = &pVM->dbgf.s.aHwBreakpoints[1];
    8484    Assert(pBp->u.Reg.iReg == 1);
    85     return pBp->GCPtr;
     85    return pBp->u.Reg.GCPtr;
    8686}
    8787
     
    9797    PCDBGFBP    pBp = &pVM->dbgf.s.aHwBreakpoints[2];
    9898    Assert(pBp->u.Reg.iReg == 2);
    99     return pBp->GCPtr;
     99    return pBp->u.Reg.GCPtr;
    100100}
    101101
     
    111111    PCDBGFBP    pBp = &pVM->dbgf.s.aHwBreakpoints[3];
    112112    Assert(pBp->u.Reg.iReg == 3);
    113     return pBp->GCPtr;
     113    return pBp->u.Reg.GCPtr;
    114114}
    115115
     
    192192        {
    193193            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].GCPtr & ~(uint64_t)(cbReg - 1);
     194            uint64_t uDrXFirst  = pVM->dbgf.s.aHwBreakpoints[iBp].u.Reg.GCPtr & ~(uint64_t)(cbReg - 1);
    195195            uint64_t uDrXLast   = uDrXFirst + cbReg - 1;
    196196            if (uDrXFirst <= uIoPortLast && uDrXLast >= uIoPortFirst)
  • trunk/src/VBox/VMM/VMMR3/DBGF.cpp

    r58170 r58903  
    668668        for (size_t i = 0; i < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints); i++)
    669669            if (    pVM->dbgf.s.aBreakpoints[i].enmType == DBGFBPTYPE_REM
    670                 &&  pVM->dbgf.s.aBreakpoints[i].GCPtr == eip)
     670                &&  pVM->dbgf.s.aBreakpoints[i].u.Rem.GCPtr == eip)
    671671            {
    672672                pVM->dbgf.s.DbgEvent.u.Bp.iBp = pVM->dbgf.s.aBreakpoints[i].iBp;
  • trunk/src/VBox/VMM/VMMR3/DBGFBp.cpp

    r58126 r58903  
    2929#endif
    3030#include <VBox/vmm/mm.h>
     31#include <VBox/vmm/iom.h>
     32#include <VBox/vmm/hm.h>
    3133#include "DBGFInternal.h"
    3234#include <VBox/vmm/vm.h>
     
    223225     */
    224226    for (unsigned iBp = 0; iBp < cBps; iBp++)
    225     {
    226         if (    paBps[iBp].enmType == enmType
    227             &&  paBps[iBp].GCPtr == GCPtr)
     227        if (   paBps[iBp].enmType == enmType
     228            && paBps[iBp].u.GCPtr == GCPtr)
    228229            return &paBps[iBp];
    229     }
    230230
    231231    return NULL;
     
    320320    if (!pBp)
    321321        return VERR_DBGF_NO_MORE_BP_SLOTS;
    322     pBp->GCPtr       = pAddress->FlatPtr;
    323     pBp->iHitTrigger = *piHitTrigger;
    324     pBp->iHitDisable = *piHitDisable;
    325     pBp->fEnabled    = true;
     322    pBp->u.Int3.GCPtr   = pAddress->FlatPtr;
     323    pBp->iHitTrigger    = *piHitTrigger;
     324    pBp->iHitDisable    = *piHitDisable;
     325    ASMCompilerBarrier();
     326    pBp->fEnabled       = true;
    326327
    327328    /*
     
    386387     */
    387388    DBGFADDRESS Addr;
    388     DBGFR3AddrFromFlat(pUVM, &Addr, pBp->GCPtr);
     389    DBGFR3AddrFromFlat(pUVM, &Addr, pBp->u.Int3.GCPtr);
    389390    int rc = DBGFR3MemRead(pUVM, idCpu, &Addr, &pBp->u.Int3.bOrg, 1);
    390391    if (RT_SUCCESS(rc))
     
    415416     */
    416417    DBGFADDRESS     Addr;
    417     DBGFR3AddrFromFlat(pUVM, &Addr, pBp->GCPtr);
     418    DBGFR3AddrFromFlat(pUVM, &Addr, pBp->u.Int3.GCPtr);
    418419    uint8_t         bCurrent;
    419420    int rc = DBGFR3MemRead(pUVM, idCpu, &Addr, &bCurrent, 1);
     
    508509    if (!pBp)
    509510        return VERR_DBGF_NO_MORE_BP_SLOTS;
    510     pBp->GCPtr       = pAddress->FlatPtr;
    511511    pBp->iHitTrigger = *piHitTrigger;
    512512    pBp->iHitDisable = *piHitDisable;
    513     pBp->fEnabled    = true;
    514513    Assert(pBp->iBp == pBp->u.Reg.iReg);
     514    pBp->u.Reg.GCPtr = pAddress->FlatPtr;
    515515    pBp->u.Reg.fType = fType;
    516516    pBp->u.Reg.cb    = cb;
     517    ASMCompilerBarrier();
     518    pBp->fEnabled    = true;
    517519
    518520    /*
     
    642644        if (!pBp->fEnabled)
    643645#ifdef VBOX_WITH_REM
    644             rc = REMR3BreakpointSet(pVM, pBp->GCPtr);
     646            rc = REMR3BreakpointSet(pVM, pBp->u.Rem.GCPtr);
    645647#else
    646             rc = IEMBreakpointSet(pVM, pBp->GCPtr);
     648            rc = IEMBreakpointSet(pVM, pBp->u.Rem.GCPtr);
    647649#endif
    648650        if (RT_SUCCESS(rc))
     
    661663    if (!pBp)
    662664        return VERR_DBGF_NO_MORE_BP_SLOTS;
    663     pBp->GCPtr      = pAddress->FlatPtr;
     665    pBp->u.Rem.GCPtr = pAddress->FlatPtr;
    664666    pBp->iHitTrigger = *piHitTrigger;
    665667    pBp->iHitDisable = *piHitDisable;
     668    ASMCompilerBarrier();
    666669    pBp->fEnabled    = true;
    667670
     
    711714
    712715
     716
     717/**
     718 * Updates IOM on whether we've got any armed I/O port or MMIO breakpoints.
     719 *
     720 * @returns VINF_SUCCESS
     721 * @param   pVM         The cross context VM structure.
     722 */
     723static int dbgfR3BpUpdateIom(PVM pVM)
     724{
     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);
     740    return VINF_SUCCESS;
     741}
     742
     743
     744/**
     745 * EMT worker for DBGFR3BpSetPortIo.
     746 *
     747 * @returns VBox status code.
     748 * @param   pUVM            The user mode VM handle.
     749 * @param   uPort           The first I/O port.
     750 * @param   cPorts          The number of I/O ports.
     751 * @param   fAccess         The access we want to break on.
     752 * @param   piHitTrigger    The hit count at which the breakpoint start triggering.
     753 *                          Use 0 (or 1) if it's gonna trigger at once.
     754 * @param   piHitDisable    The hit count which disables the breakpoint.
     755 *                          Use ~(uint64_t) if it's never gonna be disabled.
     756 * @param   piBp            Where to store the breakpoint ID.
     757 */
     758static DECLCALLBACK(int) dbgfR3BpSetPortIo(PUVM pUVM, RTIOPORT uPort, RTIOPORT cPorts, uint32_t fAccess,
     759                                           uint64_t const *piHitTrigger, uint64_t const *piHitDisable, uint32_t *piBp)
     760{
     761    /*
     762     * Validate input.
     763     */
     764    PVM pVM = pUVM->pVM;
     765    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     766    *piBp = ~0;
     767
     768    /*
     769     * Check if the breakpoint already exists.
     770     */
     771    for (uint32_t i = 0; i < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints); i++)
     772        if (   pVM->dbgf.s.aBreakpoints[i].enmType == DBGFBPTYPE_PORT_IO
     773            && pVM->dbgf.s.aBreakpoints[i].u.PortIo.uPort == uPort
     774            && pVM->dbgf.s.aBreakpoints[i].u.PortIo.cPorts == cPorts
     775            && pVM->dbgf.s.aBreakpoints[i].u.PortIo.fAccess == fAccess)
     776        {
     777            if (!pVM->dbgf.s.aBreakpoints[i].fEnabled)
     778            {
     779                pVM->dbgf.s.aBreakpoints[i].fEnabled = true;
     780                dbgfR3BpUpdateIom(pVM);
     781            }
     782            *piBp = pVM->dbgf.s.aBreakpoints[i].iBp;
     783            return VINF_DBGF_BP_ALREADY_EXIST;
     784        }
     785
     786    /*
     787     * Allocate and initialize the breakpoint.
     788     */
     789    PDBGFBP pBp = dbgfR3BpAlloc(pVM, DBGFBPTYPE_PORT_IO);
     790    if (!pBp)
     791        return VERR_DBGF_NO_MORE_BP_SLOTS;
     792    pBp->iHitTrigger        = *piHitTrigger;
     793    pBp->iHitDisable        = *piHitDisable;
     794    pBp->u.PortIo.uPort     = uPort;
     795    pBp->u.PortIo.cPorts    = cPorts;
     796    pBp->u.PortIo.fAccess   = fAccess;
     797    ASMCompilerBarrier();
     798    pBp->fEnabled           = true;
     799
     800    /*
     801     * Tell IOM.
     802     */
     803    dbgfR3BpUpdateIom(pVM);
     804    *piBp = pBp->iBp;
     805    return VINF_SUCCESS;
     806}
     807
     808
     809/**
     810 * Sets an I/O port breakpoint.
     811 *
     812 * @returns VBox status code.
     813 * @param   pUvm            The user mode VM handle.
     814 * @param   uPort           The first I/O port.
     815 * @param   cPorts          The number of I/O ports, see DBGFBPIOACCESS_XXX.
     816 * @param   fAccess         The access we want to break on.
     817 * @param   iHitTrigger     The hit count at which the breakpoint start
     818 *                          triggering. Use 0 (or 1) if it's gonna trigger at
     819 *                          once.
     820 * @param   iHitDisable     The hit count which disables the breakpoint.
     821 *                          Use ~(uint64_t) if it's never gonna be disabled.
     822 * @param   piBp            Where to store the breakpoint ID. Optional.
     823 */
     824VMMR3DECL(int)  DBGFR3BpSetPortIo(PUVM pUVM, RTIOPORT uPort, RTIOPORT cPorts, uint32_t fAccess,
     825                                  uint64_t iHitTrigger, uint64_t iHitDisable, uint32_t *piBp)
     826{
     827    AssertReturn(!(fAccess & ~DBGFBPIOACCESS_VALID_MASK_PORT_IO), VERR_INVALID_FLAGS);
     828    AssertReturn(fAccess, VERR_INVALID_FLAGS);
     829    if (iHitTrigger > iHitDisable)
     830        return VERR_INVALID_PARAMETER;
     831    AssertPtrNullReturn(piBp, VERR_INVALID_POINTER);
     832    AssertReturn(cPorts > 0, VERR_OUT_OF_RANGE);
     833    AssertReturn((RTIOPORT)(uPort + cPorts) < uPort, VERR_OUT_OF_RANGE);
     834
     835    /*
     836     * This must be done on EMT.
     837     */
     838    uint32_t iBp = -1;
     839    int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpSetPortIo, 7,
     840                              pUVM, uPort, cPorts, fAccess, &iHitTrigger, &iHitDisable, piBp);
     841    if (piBp)
     842        *piBp = iBp;
     843    LogFlow(("DBGFR3BpSetPortIo: returns %Rrc *piBp=%d\n", rc, iBp));
     844    return rc;
     845}
     846
     847
     848/**
     849 * EMT worker for DBGFR3BpSetMmio.
     850 *
     851 * @returns VBox status code.
     852 * @param   pUVM            The user mode VM handle.
     853 * @param   pGCPhys         The start of the MMIO range to break on.
     854 * @param   cb              The the size of the MMIO range.
     855 * @param   fAccess         The access we want to break on.
     856 * @param   piHitTrigger    The hit count at which the breakpoint start triggering.
     857 *                          Use 0 (or 1) if it's gonna trigger at once.
     858 * @param   piHitDisable    The hit count which disables the breakpoint.
     859 *                          Use ~(uint64_t) if it's never gonna be disabled.
     860 * @param   piBp            Where to store the breakpoint ID.
     861 */
     862static DECLCALLBACK(int) dbgfR3BpSetMmio(PUVM pUVM, PCRTGCPHYS pGCPhys, uint32_t cb, uint32_t fAccess,
     863                                         uint64_t const *piHitTrigger, uint64_t const *piHitDisable, uint32_t *piBp)
     864{
     865    RTGCPHYS const GCPhys = *pGCPhys;
     866
     867    /*
     868     * Validate input.
     869     */
     870    PVM pVM = pUVM->pVM;
     871    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     872    *piBp = ~0;
     873
     874    /*
     875     * Check if the breakpoint already exists.
     876     */
     877    for (uint32_t i = 0; i < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints); i++)
     878        if (   pVM->dbgf.s.aBreakpoints[i].enmType == DBGFBPTYPE_MMIO
     879            && pVM->dbgf.s.aBreakpoints[i].u.Mmio.PhysAddr == GCPhys
     880            && pVM->dbgf.s.aBreakpoints[i].u.Mmio.cb == cb
     881            && pVM->dbgf.s.aBreakpoints[i].u.Mmio.fAccess == fAccess)
     882        {
     883            if (!pVM->dbgf.s.aBreakpoints[i].fEnabled)
     884            {
     885                pVM->dbgf.s.aBreakpoints[i].fEnabled = true;
     886                dbgfR3BpUpdateIom(pVM);
     887            }
     888            *piBp = pVM->dbgf.s.aBreakpoints[i].iBp;
     889            return VINF_DBGF_BP_ALREADY_EXIST;
     890        }
     891
     892    /*
     893     * Allocate and initialize the breakpoint.
     894     */
     895    PDBGFBP pBp = dbgfR3BpAlloc(pVM, DBGFBPTYPE_PORT_IO);
     896    if (!pBp)
     897        return VERR_DBGF_NO_MORE_BP_SLOTS;
     898    pBp->iHitTrigger        = *piHitTrigger;
     899    pBp->iHitDisable        = *piHitDisable;
     900    pBp->u.Mmio.PhysAddr    = GCPhys;
     901    pBp->u.Mmio.cb          = cb;
     902    pBp->u.Mmio.fAccess     = fAccess;
     903    ASMCompilerBarrier();
     904    pBp->fEnabled           = true;
     905
     906    /*
     907     * Tell IOM.
     908     */
     909    dbgfR3BpUpdateIom(pVM);
     910    *piBp = pBp->iBp;
     911    return VINF_SUCCESS;
     912}
     913
     914
     915/**
     916 * Sets a memory mapped I/O breakpoint.
     917 *
     918 * @returns VBox status code.
     919 * @param   pUvm            The user mode VM handle.
     920 * @param   GCPhys          The first MMIO address.
     921 * @param   cb              The size of the MMIO range to break on.
     922 * @param   fAccess         The access we want to break on.
     923 * @param   iHitTrigger     The hit count at which the breakpoint start
     924 *                          triggering. Use 0 (or 1) if it's gonna trigger at
     925 *                          once.
     926 * @param   iHitDisable     The hit count which disables the breakpoint.
     927 *                          Use ~(uint64_t) if it's never gonna be disabled.
     928 * @param   piBp            Where to store the breakpoint ID. Optional.
     929 */
     930VMMR3DECL(int)  DBGFR3BpSetMmio(PUVM pUVM, RTGCPHYS GCPhys, uint32_t cb, uint32_t fAccess,
     931                                uint64_t iHitTrigger, uint64_t iHitDisable, uint32_t *piBp)
     932{
     933    AssertReturn(!(fAccess & ~DBGFBPIOACCESS_VALID_MASK_MMIO), VERR_INVALID_FLAGS);
     934    AssertReturn(fAccess, VERR_INVALID_FLAGS);
     935    if (iHitTrigger > iHitDisable)
     936        return VERR_INVALID_PARAMETER;
     937    AssertPtrNullReturn(piBp, VERR_INVALID_POINTER);
     938    AssertReturn(cb, VERR_OUT_OF_RANGE);
     939    AssertReturn(GCPhys + cb < GCPhys, VERR_OUT_OF_RANGE);
     940
     941    /*
     942     * This must be done on EMT.
     943     */
     944    uint32_t iBp = -1;
     945    int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpSetMmio, 7,
     946                              pUVM, &GCPhys, cb, fAccess, &iHitTrigger, &iHitDisable, piBp);
     947    if (piBp)
     948        *piBp = iBp;
     949    LogFlow(("DBGFR3BpSetMmio: returns %Rrc *piBp=%d\n", rc, iBp));
     950    return rc;
     951}
     952
     953
    713954/**
    714955 * EMT worker for DBGFR3BpClear().
     
    750991            case DBGFBPTYPE_REM:
    751992#ifdef VBOX_WITH_REM
    752                 rc = REMR3BreakpointClear(pVM, pBp->GCPtr);
     993                rc = REMR3BreakpointClear(pVM, pBp->u.Rem.GCPtr);
    753994#else
    754                 rc = IEMBreakpointClear(pVM, pBp->GCPtr);
     995                rc = IEMBreakpointClear(pVM, pBp->u.Rem.GCPtr);
    755996#endif
     997                break;
     998
     999            case DBGFBPTYPE_PORT_IO:
     1000            case DBGFBPTYPE_MMIO:
     1001                rc = dbgfR3BpUpdateIom(pVM);
    7561002                break;
    7571003
     
    8321078        case DBGFBPTYPE_REM:
    8331079#ifdef VBOX_WITH_REM
    834             rc = REMR3BreakpointSet(pVM, pBp->GCPtr);
     1080            rc = REMR3BreakpointSet(pVM, pBp->u.Rem.GCPtr);
    8351081#else
    836             rc = IEMBreakpointSet(pVM, pBp->GCPtr);
     1082            rc = IEMBreakpointSet(pVM, pBp->u.Rem.GCPtr);
    8371083#endif
     1084            break;
     1085
     1086        case DBGFBPTYPE_PORT_IO:
     1087        case DBGFBPTYPE_MMIO:
     1088            rc = dbgfR3BpUpdateIom(pVM);
    8381089            break;
    8391090
     
    9101161        case DBGFBPTYPE_REM:
    9111162#ifdef VBOX_WITH_REM
    912             rc = REMR3BreakpointClear(pVM, pBp->GCPtr);
     1163            rc = REMR3BreakpointClear(pVM, pBp->u.Rem.GCPtr);
    9131164#else
    914             rc = IEMBreakpointClear(pVM, pBp->GCPtr);
     1165            rc = IEMBreakpointClear(pVM, pBp->u.Rem.GCPtr);
    9151166#endif
     1167            break;
     1168
     1169        case DBGFBPTYPE_PORT_IO:
     1170        case DBGFBPTYPE_MMIO:
     1171            rc = dbgfR3BpUpdateIom(pVM);
    9161172            break;
    9171173
  • trunk/src/VBox/VMM/VMMR3/IOM.cpp

    r58126 r58903  
    16461646
    16471647/**
     1648 * Notification from DBGF that the number of active I/O port or MMIO
     1649 * breakpoints has change.
     1650 *
     1651 * For performance reasons, IOM will only call DBGF before doing I/O and MMIO
     1652 * accesses where there are armed breakpoints.
     1653 *
     1654 * @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 */
     1658VMMR3_INT_DECL(void) IOMR3NotifyBreakpointCountChange(PVM pVM, unsigned cPortIo, unsigned cMmio)
     1659{
     1660    /** @todo I/O breakpoints. */
     1661}
     1662
     1663
     1664/**
     1665 * Notification from DBGF that an event has been enabled or disabled.
     1666 *
     1667 * For performance reasons, IOM may cache the state of events it implements.
     1668 *
     1669 * @param   pVM         The cross context VM structure.
     1670 * @param   enmEvent    The event.
     1671 * @param   fEnabled    The new state.
     1672 */
     1673VMMR3_INT_DECL(void) IOMR3NotifyDebugEventChange(PVM pVM, DBGFEVENT enmEvent, bool fEnabled)
     1674{
     1675    /** @todo IOM debug events. */
     1676}
     1677
     1678
     1679/**
    16481680 * Display a single MMIO range.
    16491681 *
  • trunk/src/VBox/VMM/VMMRZ/DBGFRZ.cpp

    r58123 r58903  
    139139        for (unsigned iBp = 0; iBp < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints); iBp++)
    140140        {
    141             if (    pVM->dbgf.s.aBreakpoints[iBp].GCPtr == (RTGCUINTPTR)pPc
     141            if (    pVM->dbgf.s.aBreakpoints[iBp].u.GCPtr == (RTGCUINTPTR)pPc
    142142                &&  pVM->dbgf.s.aBreakpoints[iBp].enmType == DBGFBPTYPE_INT3)
    143143            {
  • trunk/src/VBox/VMM/include/DBGFInternal.h

    r56287 r58903  
    5050    /** Single step execution - stepping into calls. */
    5151    DBGFCMD_SINGLE_STEP,
    52     /** Set a breakpoint. */
    53     DBGFCMD_BREAKPOINT_SET,
    54     /** Set a access breakpoint. */
    55     DBGFCMD_BREAKPOINT_SET_ACCESS,
    56     /** Set a REM breakpoint. */
    57     DBGFCMD_BREAKPOINT_SET_REM,
    58     /** Clear a breakpoint. */
    59     DBGFCMD_BREAKPOINT_CLEAR,
    60     /** Enable a breakpoint. */
    61     DBGFCMD_BREAKPOINT_ENABLE,
    62     /** Disable a breakpoint. */
    63     DBGFCMD_BREAKPOINT_DISABLE,
    64     /** List breakpoints. */
    65     DBGFCMD_BREAKPOINT_LIST,
    66 
    6752    /** Detaches the debugger.
    6853     * Disabling all breakpoints, watch points and the like. */
    69     DBGFCMD_DETACH_DEBUGGER = 0x7ffffffe,
     54    DBGFCMD_DETACH_DEBUGGER,
    7055    /** Detached the debugger.
    7156     * The isn't a command as such, it's just that it's necessary for the
    7257     * detaching protocol to be racefree. */
    73     DBGFCMD_DETACHED_DEBUGGER = 0x7fffffff
     58    DBGFCMD_DETACHED_DEBUGGER
    7459} DBGFCMD;
    7560
     
    202187    int32_t                     offVM;
    203188
     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;
     193
    204194    /** Debugger Attached flag.
    205195     * Set if a debugger is attached, elsewise it's clear.
     
    247237     * @remark This is currently a fixed size array for reasons of simplicity. */
    248238    DBGFBP                      aBreakpoints[32];
     239
    249240} DBGF;
    250241/** Pointer to DBGF Data. */
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