VirtualBox

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


Ignore:
Timestamp:
Jun 25, 2021 11:24:49 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
145370
Message:

VMM/DBGF: Basic infrastructure to support adding and deleting port I/O breakpoints, next is interfacing them with IOM, bugref:9837

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

Legend:

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

    r87600 r89912  
    7575    }
    7676
    77     pGVM->dbgfr0.s.hMemObjBpLocL1 = NIL_RTR0MEMOBJ;
    78     //pGVM->dbgfr0.s.paBpLocL1R0    = NULL;
    79     //pGVM->dbgfr0.s.fInit          = false;
     77    pGVM->dbgfr0.s.hMemObjBpLocL1     = NIL_RTR0MEMOBJ;
     78    pGVM->dbgfr0.s.hMapObjBpLocL1     = NIL_RTR0MEMOBJ;
     79    pGVM->dbgfr0.s.hMemObjBpLocPortIo = NIL_RTR0MEMOBJ;
     80    pGVM->dbgfr0.s.hMapObjBpLocPortIo = NIL_RTR0MEMOBJ;
     81    //pGVM->dbgfr0.s.paBpLocL1R0      = NULL;
     82    //pGVM->dbgfr0.s.paBpLocPortIoR0  = NULL;
     83    //pGVM->dbgfr0.s.fInit            = false;
    8084}
    8185
     
    118122        RTR0MemObjFree(hMemObj, true);
    119123
     124        if (pGVM->dbgfr0.s.paBpLocPortIoR0)
     125        {
     126            Assert(pGVM->dbgfr0.s.hMemObjBpLocPortIo != NIL_RTR0MEMOBJ);
     127            Assert(pGVM->dbgfr0.s.hMapObjBpLocPortIo != NIL_RTR0MEMOBJ);
     128
     129            hMemObj = pGVM->dbgfr0.s.hMapObjBpLocPortIo;
     130            pGVM->dbgfr0.s.hMapObjBpLocPortIo = NIL_RTR0MEMOBJ;
     131            RTR0MemObjFree(hMemObj, true);
     132
     133            hMemObj = pGVM->dbgfr0.s.hMemObjBpLocPortIo;
     134            pGVM->dbgfr0.s.hMemObjBpLocPortIo = NIL_RTR0MEMOBJ;
     135            pGVM->dbgfr0.s.paBpLocPortIoR0    = NULL;
     136            RTR0MemObjFree(hMemObj, true);
     137        }
     138
    120139        for (uint32_t i = 0; i < RT_ELEMENTS(pGVM->dbgfr0.s.aBpChunks); i++)
    121140        {
     
    167186        Assert(!pGVM->dbgfr0.s.paBpLocL1R0);
    168187
     188        Assert(pGVM->dbgfr0.s.hMemObjBpLocPortIo == NIL_RTR0MEMOBJ);
     189        Assert(!pGVM->dbgfr0.s.paBpLocPortIoR0);
     190
    169191        for (uint32_t i = 0; i < RT_ELEMENTS(pGVM->dbgfr0.s.aBpChunks); i++)
    170192        {
     
    226248        *ppaBpLocL1R3 = RTR0MemObjAddressR3(hMapObj);
    227249        pGVM->dbgfr0.s.fInit = true;
     250        return rc;
     251    }
     252
     253    RTR0MemObjFree(hMemObj, true);
     254    return rc;
     255}
     256
     257
     258/**
     259 * Worker for DBGFR0BpPortIoInitReqHandler() that does the actual initialization.
     260 *
     261 * @returns VBox status code.
     262 * @param   pGVM                The global (ring-0) VM structure.
     263 * @param   ppaBpLocPortIoR3    Where to return the ring-3 L1 lookup table address on success.
     264 * @thread  EMT(0)
     265 */
     266static int dbgfR0BpPortIoInitWorker(PGVM pGVM, R3PTRTYPE(volatile uint32_t *) *ppaBpLocPortIoR3)
     267{
     268    /*
     269     * Figure out how much memory we need for the I/O port breakpoint lookup table and allocate it.
     270     */
     271    uint32_t const cbPortIoLoc = RT_ALIGN_32(UINT16_MAX * sizeof(uint32_t), PAGE_SIZE);
     272
     273    RTR0MEMOBJ hMemObj;
     274    int rc = RTR0MemObjAllocPage(&hMemObj, cbPortIoLoc, false /*fExecutable*/);
     275    if (RT_FAILURE(rc))
     276        return rc;
     277    RT_BZERO(RTR0MemObjAddress(hMemObj), cbPortIoLoc);
     278
     279    /* Map it. */
     280    RTR0MEMOBJ hMapObj;
     281    rc = RTR0MemObjMapUserEx(&hMapObj, hMemObj, (RTR3PTR)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE, RTR0ProcHandleSelf(),
     282                             0 /*offSub*/, cbPortIoLoc);
     283    if (RT_SUCCESS(rc))
     284    {
     285        pGVM->dbgfr0.s.hMemObjBpLocPortIo = hMemObj;
     286        pGVM->dbgfr0.s.hMapObjBpLocPortIo = hMapObj;
     287        pGVM->dbgfr0.s.paBpLocPortIoR0    = (volatile uint32_t *)RTR0MemObjAddress(hMemObj);
     288
     289        /*
     290         * We're done.
     291         */
     292        *ppaBpLocPortIoR3 = RTR0MemObjAddressR3(hMapObj);
    228293        return rc;
    229294    }
     
    412477
    413478/**
    414  * Used by ring-3 DBGF to initialize the breakpoint owner table for operation.
     479 * Used by ring-3 DBGF to initialize the breakpoint manager for port I/O breakpoint operation.
    415480 *
    416481 * @returns VBox status code.
     
    419484 * @thread  EMT(0)
    420485 */
    421 VMMR0_INT_DECL(int) DBGFR0BpOwnerInitReqHandler(PGVM pGVM, PDBGFBPOWNERINITREQ pReq)
    422 {
    423     LogFlow(("DBGFR0BpOwnerInitReqHandler:\n"));
     486VMMR0_INT_DECL(int) DBGFR0BpPortIoInitReqHandler(PGVM pGVM, PDBGFBPINITREQ pReq)
     487{
     488    LogFlow(("DBGFR0BpPortIoInitReqHandler:\n"));
    424489
    425490    /*
     
    431496    AssertRCReturn(rc, rc);
    432497
    433     AssertReturn(!pGVM->dbgfr0.s.paBpOwnersR0, VERR_WRONG_ORDER);
    434 
    435     return dbgfR0BpOwnerInitWorker(pGVM, &pReq->paBpOwnerR3);
    436 }
    437 
    438 
    439 /**
    440  * Used by ring-3 DBGF to allocate a given chunk in the global breakpoint table.
     498    AssertReturn(!pGVM->dbgfr0.s.fInit, VERR_WRONG_ORDER);
     499    AssertReturn(!pGVM->dbgfr0.s.paBpLocPortIoR0, VERR_WRONG_ORDER);
     500
     501    return dbgfR0BpPortIoInitWorker(pGVM, &pReq->paBpLocL1R3);
     502}
     503
     504
     505/**
     506 * Used by ring-3 DBGF to initialize the breakpoint owner table for operation.
    441507 *
    442508 * @returns VBox status code.
     
    445511 * @thread  EMT(0)
    446512 */
     513VMMR0_INT_DECL(int) DBGFR0BpOwnerInitReqHandler(PGVM pGVM, PDBGFBPOWNERINITREQ pReq)
     514{
     515    LogFlow(("DBGFR0BpOwnerInitReqHandler:\n"));
     516
     517    /*
     518     * Validate the request.
     519     */
     520    AssertReturn(pReq->Hdr.cbReq == sizeof(*pReq), VERR_INVALID_PARAMETER);
     521
     522    int rc = GVMMR0ValidateGVMandEMT(pGVM, 0);
     523    AssertRCReturn(rc, rc);
     524
     525    AssertReturn(!pGVM->dbgfr0.s.paBpOwnersR0, VERR_WRONG_ORDER);
     526
     527    return dbgfR0BpOwnerInitWorker(pGVM, &pReq->paBpOwnerR3);
     528}
     529
     530
     531/**
     532 * Used by ring-3 DBGF to allocate a given chunk in the global breakpoint table.
     533 *
     534 * @returns VBox status code.
     535 * @param   pGVM    The global (ring-0) VM structure.
     536 * @param   pReq    Pointer to the request buffer.
     537 * @thread  EMT(0)
     538 */
    447539VMMR0_INT_DECL(int) DBGFR0BpChunkAllocReqHandler(PGVM pGVM, PDBGFBPCHUNKALLOCREQ pReq)
    448540{
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r88347 r89912  
    23792379        }
    23802380
     2381        case VMMR0_DO_DBGF_BP_PORTIO_INIT:
     2382        {
     2383            if (!pReqHdr || u64Arg || idCpu != 0)
     2384                return VERR_INVALID_PARAMETER;
     2385            rc = DBGFR0BpPortIoInitReqHandler(pGVM, (PDBGFBPINITREQ)pReqHdr);
     2386            VMM_CHECK_SMAP_CHECK2(pGVM, RT_NOTHING);
     2387            break;
     2388        }
     2389
     2390
    23812391        /*
    23822392         * TM requests.
  • trunk/src/VBox/VMM/VMMR3/DBGFR3Bp.cpp

    r87832 r89912  
    113113 *        Each entry in the L2 table is 16 bytes big and densly packed to avoid excessive memory usage.
    114114 *
     115 * @section sec_dbgf_bp_ioport  Handling I/O port breakpoints
     116 *
     117 * Because of the limited amount of I/O ports being available (65536) a single table with 65536 entries,
     118 * each 4 byte big will be allocated. This amounts to 256KiB of memory being used additionally as soon as
     119 * an I/O breakpoint is enabled. The entries contain the breakpoint handle directly allowing only one breakpoint
     120 * per port right now, which is something we accept as a limitation right now to keep things relatively simple.
     121 * When there is at least one I/O breakpoint active IOM will be notified and it will afterwards call the DBGF API
     122 * whenever the guest does an I/O port access to decide whether a breakpoint was hit. This keeps the overhead small
     123 * when there is no I/O port breakpoint enabled.
    115124 *
    116125 * @section sec_dbgf_bp_note    Random thoughts and notes for the implementation
     
    217226    }
    218227
    219     //pUVM->dbgf.s.paBpLocL1R3 = NULL;
     228    //pUVM->dbgf.s.paBpLocL1R3     = NULL;
     229    //pUVM->dbgf.s.paBpLocPortIoR3 = NULL;
    220230    pUVM->dbgf.s.hMtxBpL2Wr = NIL_RTSEMFASTMUTEX;
    221231    return RTSemFastMutexCreate(&pUVM->dbgf.s.hMtxBpL2Wr);
     
    324334    /* Gather all EMTs and call into ring-0 to initialize the breakpoint manager. */
    325335    return VMMR3EmtRendezvous(pUVM->pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3BpInitEmtWorker, NULL /*pvUser*/);
     336}
     337
     338
     339/**
     340 * @callback_method_impl{FNVMMEMTRENDEZVOUS}
     341 */
     342static DECLCALLBACK(VBOXSTRICTRC) dbgfR3BpPortIoInitEmtWorker(PVM pVM, PVMCPU pVCpu, void *pvUser)
     343{
     344    RT_NOREF(pvUser);
     345
     346    VMCPU_ASSERT_EMT(pVCpu);
     347    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     348
     349    /*
     350     * The initialization will be done on EMT(0). It is possible that multiple
     351     * initialization attempts are done because dbgfR3BpPortIoEnsureInit() can be called
     352     * from racing non EMT threads when trying to set a breakpoint for the first time.
     353     * Just fake success if the L1 is already present which means that a previous rendezvous
     354     * successfully initialized the breakpoint manager.
     355     */
     356    PUVM pUVM = pVM->pUVM;
     357    if (   pVCpu->idCpu == 0
     358        && !pUVM->dbgf.s.paBpLocPortIoR3)
     359    {
     360        DBGFBPINITREQ Req;
     361        Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     362        Req.Hdr.cbReq    = sizeof(Req);
     363        Req.paBpLocL1R3  = NULL;
     364        int rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_DBGF_BP_PORTIO_INIT, 0 /*u64Arg*/, &Req.Hdr);
     365        AssertLogRelMsgRCReturn(rc, ("VMMR0_DO_DBGF_BP_PORTIO_INIT failed: %Rrc\n", rc), rc);
     366        pUVM->dbgf.s.paBpLocPortIoR3 = Req.paBpLocL1R3;
     367    }
     368
     369    return VINF_SUCCESS;
     370}
     371
     372
     373/**
     374 * Ensures that the breakpoint manager is initialized to handle I/O port breakpoint.
     375 *
     376 * @returns VBox status code.
     377 * @param   pUVM                The user mode VM handle.
     378 *
     379 * @thread Any thread.
     380 */
     381static int dbgfR3BpPortIoEnsureInit(PUVM pUVM)
     382{
     383    /* If the L1 lookup table is allocated initialization succeeded before. */
     384    if (RT_LIKELY(pUVM->dbgf.s.paBpLocPortIoR3))
     385        return VINF_SUCCESS;
     386
     387    /* Ensure that the breakpoint manager is initialized. */
     388    int rc = dbgfR3BpEnsureInit(pUVM);
     389    if (RT_FAILURE(rc))
     390        return rc;
     391
     392    /* Gather all EMTs and call into ring-0 to initialize the breakpoint manager. */
     393    return VMMR3EmtRendezvous(pUVM->pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3BpPortIoInitEmtWorker, NULL /*pvUser*/);
    326394}
    327395
     
    13581426
    13591427/**
     1428 * Adds the given port I/O breakpoint to the appropriate lookup tables.
     1429 *
     1430 * @returns VBox status code.
     1431 * @param   pUVM                The user mode VM handle.
     1432 * @param   hBp                 The breakpoint handle to add.
     1433 * @param   pBp                 The internal breakpoint state.
     1434 */
     1435static int dbgfR3BpPortIoAdd(PUVM pUVM, DBGFBP hBp, PDBGFBPINT pBp)
     1436{
     1437    AssertReturn(DBGF_BP_PUB_GET_TYPE(&pBp->Pub) == DBGFBPTYPE_PORT_IO, VERR_DBGF_BP_IPE_3);
     1438
     1439    uint16_t uPortExcl = pBp->Pub.u.PortIo.uPort + pBp->Pub.u.PortIo.cPorts;
     1440    uint32_t u32Entry  = DBGF_BP_INT3_L1_ENTRY_CREATE_BP_HND(hBp);
     1441    for (uint16_t idxPort = pBp->Pub.u.PortIo.uPort; idxPort < uPortExcl; idxPort++)
     1442    {
     1443        bool fXchg = ASMAtomicCmpXchgU32(&pUVM->dbgf.s.paBpLocPortIoR3[idxPort], u32Entry, DBGF_BP_INT3_L1_ENTRY_TYPE_NULL);
     1444        if (!fXchg)
     1445        {
     1446            /* Something raced us, so roll back the other registrations. */
     1447            while (idxPort > pBp->Pub.u.PortIo.uPort)
     1448            {
     1449                fXchg = ASMAtomicCmpXchgU32(&pUVM->dbgf.s.paBpLocPortIoR3[idxPort], DBGF_BP_INT3_L1_ENTRY_TYPE_NULL, u32Entry);
     1450                Assert(fXchg); RT_NOREF(fXchg);
     1451            }
     1452
     1453            return VERR_DBGF_BP_INT3_ADD_TRIES_REACHED; /** @todo New status code */
     1454        }
     1455    }
     1456
     1457    return VINF_SUCCESS;
     1458}
     1459
     1460
     1461/**
    13601462 * Get a breakpoint give by address.
    13611463 *
     
    14381540            AssertMsgFailed(("enmType=%d\n", enmType));
    14391541            break;
     1542    }
     1543
     1544    if (   hBp != NIL_DBGFBP
     1545        && ppBp)
     1546        *ppBp =  dbgfR3BpGetByHnd(pUVM, hBp);
     1547    return hBp;
     1548}
     1549
     1550
     1551/**
     1552 * Get a port I/O breakpoint given by the range.
     1553 *
     1554 * @returns The breakpoint handle on success or NIL_DBGF if not found.
     1555 * @param   pUVM                The user mode VM handle.
     1556 * @param   uPort               First port in the range.
     1557 * @param   cPorts              Number of ports in the range.
     1558 * @param   ppBp                Where to store the pointer to the internal breakpoint state on success, optional.
     1559 */
     1560static DBGFBP dbgfR3BpPortIoGetByRange(PUVM pUVM, RTIOPORT uPort, RTIOPORT cPorts, PDBGFBPINT *ppBp)
     1561{
     1562    DBGFBP hBp = NIL_DBGFBP;
     1563
     1564    for (RTIOPORT idxPort = uPort; idxPort < uPort + cPorts; idxPort)
     1565    {
     1566        const uint32_t u32Entry = ASMAtomicReadU32(&pUVM->dbgf.s.CTX_SUFF(paBpLocPortIo)[idxPort]);
     1567        if (u32Entry != DBGF_BP_INT3_L1_ENTRY_TYPE_NULL)
     1568        {
     1569            hBp = DBGF_BP_INT3_L1_ENTRY_GET_BP_HND(u32Entry);
     1570            break;
     1571        }
    14401572    }
    14411573
     
    15171649     */
    15181650    return VMMR3EmtRendezvous(pUVM->pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3BpInt3RemoveEmtWorker, (void *)(uintptr_t)hBp);
     1651}
     1652
     1653
     1654/**
     1655 * @callback_method_impl{FNVMMEMTRENDEZVOUS}
     1656 */
     1657static DECLCALLBACK(VBOXSTRICTRC) dbgfR3BpPortIoRemoveEmtWorker(PVM pVM, PVMCPU pVCpu, void *pvUser)
     1658{
     1659    DBGFBP hBp = (DBGFBP)(uintptr_t)pvUser;
     1660
     1661    VMCPU_ASSERT_EMT(pVCpu);
     1662    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     1663
     1664    PUVM pUVM = pVM->pUVM;
     1665    PDBGFBPINT pBp = dbgfR3BpGetByHnd(pUVM, hBp);
     1666    AssertPtrReturn(pBp, VERR_DBGF_BP_IPE_8);
     1667
     1668    int rc = VINF_SUCCESS;
     1669    if (pVCpu->idCpu == 0)
     1670    {
     1671        /*
     1672         * Remove the whole range, there shouldn't be any other breakpoint configured for this range as this is not
     1673         * allowed right now.
     1674         */
     1675        uint16_t uPortExcl = pBp->Pub.u.PortIo.uPort + pBp->Pub.u.PortIo.cPorts;
     1676        for (uint16_t idxPort = pBp->Pub.u.PortIo.uPort; idxPort < uPortExcl; idxPort++)
     1677        {
     1678            uint32_t u32Entry = ASMAtomicReadU32(&pUVM->dbgf.s.paBpLocPortIoR3[idxPort]);
     1679            AssertReturn(u32Entry != DBGF_BP_INT3_L1_ENTRY_TYPE_NULL, VERR_DBGF_BP_IPE_6);
     1680
     1681            uint8_t u8Type = DBGF_BP_INT3_L1_ENTRY_GET_TYPE(u32Entry);
     1682            AssertReturn(u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_BP_HND, VERR_DBGF_BP_IPE_7);
     1683
     1684            bool fXchg = ASMAtomicCmpXchgU32(&pUVM->dbgf.s.paBpLocL1R3[idxPort], DBGF_BP_INT3_L1_ENTRY_TYPE_NULL, u32Entry);
     1685            Assert(fXchg); RT_NOREF(fXchg);
     1686        }
     1687    }
     1688
     1689    return rc;
     1690}
     1691
     1692
     1693/**
     1694 * Removes the given port I/O breakpoint from all lookup tables.
     1695 *
     1696 * @returns VBox status code.
     1697 * @param   pUVM                The user mode VM handle.
     1698 * @param   hBp                 The breakpoint handle to remove.
     1699 * @param   pBp                 The internal breakpoint state.
     1700 */
     1701static int dbgfR3BpPortIoRemove(PUVM pUVM, DBGFBP hBp, PDBGFBPINT pBp)
     1702{
     1703    AssertReturn(DBGF_BP_PUB_GET_TYPE(&pBp->Pub) == DBGFBPTYPE_PORT_IO, VERR_DBGF_BP_IPE_3);
     1704
     1705    /*
     1706     * This has to be done by an EMT rendezvous in order to not have an EMT accessing
     1707     * the breakpoint while it is removed.
     1708     */
     1709    return VMMR3EmtRendezvous(pUVM->pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3BpPortIoRemoveEmtWorker, (void *)(uintptr_t)hBp);
    15191710}
    15201711
     
    20632254{
    20642255    return DBGFR3BpSetPortIoEx(pUVM, NIL_DBGFBPOWNER, NULL /*pvUser*/, uPort, cPorts,
    2065                                fAccess, iHitTrigger, iHitDisable, phBp);
     2256                               DBGF_BP_F_DEFAULT, fAccess, iHitTrigger, iHitDisable, phBp);
    20662257}
    20672258
     
    20772268 * @param   cPorts          The number of I/O ports, see DBGFBPIOACCESS_XXX.
    20782269 * @param   fAccess         The access we want to break on.
     2270 * @param   fFlags          Combination of DBGF_BP_F_XXX.
    20792271 * @param   iHitTrigger     The hit count at which the breakpoint start
    20802272 *                          triggering. Use 0 (or 1) if it's gonna trigger at
     
    20882280VMMR3DECL(int) DBGFR3BpSetPortIoEx(PUVM pUVM, DBGFBPOWNER hOwner, void *pvUser,
    20892281                                   RTIOPORT uPort, RTIOPORT cPorts, uint32_t fAccess,
    2090                                    uint64_t iHitTrigger, uint64_t iHitDisable, PDBGFBP phBp)
     2282                                   uint32_t fFlags, uint64_t iHitTrigger, uint64_t iHitDisable, PDBGFBP phBp)
    20912283{
    20922284    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
     
    20992291    AssertReturn((RTIOPORT)(uPort + cPorts) < uPort, VERR_OUT_OF_RANGE);
    21002292
    2101     int rc = dbgfR3BpEnsureInit(pUVM);
     2293    int rc = dbgfR3BpPortIoEnsureInit(pUVM);
    21022294    AssertRCReturn(rc, rc);
    21032295
    2104     return VERR_NOT_IMPLEMENTED;
     2296    PDBGFBPINT pBp = NULL;
     2297    DBGFBP hBp = dbgfR3BpPortIoGetByRange(pUVM, uPort, cPorts, &pBp);
     2298    if (   hBp != NIL_DBGFBP
     2299        && pBp->Pub.u.PortIo.uPort == uPort
     2300        && pBp->Pub.u.PortIo.cPorts == cPorts
     2301        && pBp->Pub.u.PortIo.fAccess == fAccess)
     2302    {
     2303        rc = VINF_SUCCESS;
     2304        if (!DBGF_BP_PUB_IS_ENABLED(&pBp->Pub))
     2305            rc = dbgfR3BpArm(pUVM, hBp, pBp);
     2306        if (RT_SUCCESS(rc))
     2307        {
     2308            rc = VINF_DBGF_BP_ALREADY_EXIST;
     2309            if (phBp)
     2310                *phBp = hBp;
     2311        }
     2312        return rc;
     2313    }
     2314
     2315    rc = dbgfR3BpAlloc(pUVM, hOwner, pvUser, DBGFBPTYPE_PORT_IO, fFlags, iHitTrigger, iHitDisable, &hBp, &pBp);
     2316    if (RT_SUCCESS(rc))
     2317    {
     2318        pBp->Pub.u.PortIo.uPort   = uPort;
     2319        pBp->Pub.u.PortIo.cPorts  = cPorts;
     2320        pBp->Pub.u.PortIo.fAccess = fAccess;
     2321
     2322        /* Add the breakpoint to the lookup tables. */
     2323        rc = dbgfR3BpPortIoAdd(pUVM, hBp, pBp);
     2324        if (RT_SUCCESS(rc))
     2325        {
     2326            /* Enable the breakpoint if requested. */
     2327            if (fFlags & DBGF_BP_F_ENABLED)
     2328                rc = dbgfR3BpArm(pUVM, hBp, pBp);
     2329            if (RT_SUCCESS(rc))
     2330            {
     2331                *phBp = hBp;
     2332                return VINF_SUCCESS;
     2333            }
     2334
     2335            int rc2 = dbgfR3BpPortIoRemove(pUVM, hBp, pBp); AssertRC(rc2);
     2336        }
     2337
     2338        dbgfR3BpFree(pUVM, hBp, pBp);
     2339    }
     2340
     2341    return rc;
    21052342}
    21062343
     
    22052442        {
    22062443            int rc = dbgfR3BpInt3Remove(pUVM, hBp, pBp);
     2444            AssertRC(rc);
     2445            break;
     2446        }
     2447        case DBGFBPTYPE_PORT_IO:
     2448        {
     2449            int rc = dbgfR3BpPortIoRemove(pUVM, hBp, pBp);
    22072450            AssertRC(rc);
    22082451            break;
  • trunk/src/VBox/VMM/include/DBGFInternal.h

    r87594 r89912  
    12881288    /** The L1 lookup tables mapping object. */
    12891289    RTR0MEMOBJ                          hMapObjBpLocL1;
     1290    /** The I/O port breakpoint lookup tables memory object. */
     1291    RTR0MEMOBJ                          hMemObjBpLocPortIo;
     1292    /** The I/O port breakpoint lookup tables mapping object. */
     1293    RTR0MEMOBJ                          hMapObjBpLocPortIo;
    12901294    /** Base pointer to the L1 locator table. */
    12911295    R0PTRTYPE(volatile uint32_t *)      paBpLocL1R0;
     1296    /** Base pointer to the L1 locator table. */
     1297    R0PTRTYPE(volatile uint32_t *)      paBpLocPortIoR0;
    12921298    /** Flag whether the breakpoint manager was initialized (on demand). */
    12931299    bool                                fInit;
     
    13801386    /** Base pointer to the L1 locator table. */
    13811387    R3PTRTYPE(volatile uint32_t *)  paBpLocL1R3;
     1388    /** Base pointer to the Port I/O breakpoint locator table. */
     1389    R3PTRTYPE(volatile uint32_t *)  paBpLocPortIoR3;
    13821390    /** Fast mutex protecting the L2 table from concurrent write accesses (EMTs
    13831391     * can still do read accesses without holding it while traversing the trees). */
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