VirtualBox

Changeset 87107 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Dec 19, 2020 3:10:18 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
141970
Message:

VMM/DBGF: Started implementing the breakpoint owner management, bugref:9837

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/DBGFR3Bp.cpp

    r86754 r87107  
    182182    PVM pVM = pUVM->pVM;
    183183
     184    //pUVM->dbgf.s.paBpOwnersR3       = NULL;
     185    //pUVM->dbgf.s.pbmBpOwnersAllocR3 = NULL;
     186
    184187    /* Init hardware breakpoint states. */
    185188    for (uint32_t i = 0; i < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints); i++)
     
    227230DECLHIDDEN(int) dbgfR3BpTerm(PUVM pUVM)
    228231{
     232    if (pUVM->dbgf.s.pbmBpOwnersAllocR3)
     233    {
     234        RTMemFree((void *)pUVM->dbgf.s.pbmBpOwnersAllocR3);
     235        pUVM->dbgf.s.pbmBpOwnersAllocR3 = NULL;
     236    }
     237
    229238    /* Free all allocated chunk bitmaps (the chunks itself are destroyed during ring-0 VM destruction). */
    230239    for (uint32_t i = 0; i < RT_ELEMENTS(pUVM->dbgf.s.aBpChunks); i++)
     
    314323    /* Gather all EMTs and call into ring-0 to initialize the breakpoint manager. */
    315324    return VMMR3EmtRendezvous(pUVM->pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3BpInitEmtWorker, NULL /*pvUser*/);
     325}
     326
     327
     328/**
     329 * @callback_method_impl{FNVMMEMTRENDEZVOUS}
     330 */
     331static DECLCALLBACK(VBOXSTRICTRC) dbgfR3BpOwnerInitEmtWorker(PVM pVM, PVMCPU pVCpu, void *pvUser)
     332{
     333    RT_NOREF(pvUser);
     334
     335    VMCPU_ASSERT_EMT(pVCpu);
     336    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     337
     338    /*
     339     * The initialization will be done on EMT(0). It is possible that multiple
     340     * initialization attempts are done because dbgfR3BpOwnerEnsureInit() can be called
     341     * from racing non EMT threads when trying to create a breakpoint owner for the first time.
     342     * Just fake success if the pointers are initialized already, meaning that a previous rendezvous
     343     * successfully initialized the breakpoint owner table.
     344     */
     345    int rc = VINF_SUCCESS;
     346    PUVM pUVM = pVM->pUVM;
     347    if (   pVCpu->idCpu == 0
     348        && !pUVM->dbgf.s.pbmBpOwnersAllocR3)
     349    {
     350        pUVM->dbgf.s.pbmBpOwnersAllocR3 = (volatile void *)RTMemAllocZ(DBGF_BP_OWNER_COUNT_MAX / 8);
     351        if (pUVM->dbgf.s.pbmBpOwnersAllocR3)
     352        {
     353            DBGFBPOWNERINITREQ Req;
     354            Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     355            Req.Hdr.cbReq    = sizeof(Req);
     356            Req.paBpOwnerR3  = NULL;
     357            rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_DBGF_BP_OWNER_INIT, 0 /*u64Arg*/, &Req.Hdr);
     358            AssertLogRelMsgRC(rc, ("VMMR0_DO_DBGF_BP_OWNER_INIT failed: %Rrc\n", rc));
     359            if (RT_SUCCESS(rc))
     360            {
     361                pUVM->dbgf.s.paBpOwnersR3 = (PDBGFBPOWNERINT)Req.paBpOwnerR3;
     362                return VINF_SUCCESS;
     363            }
     364
     365            RTMemFree((void *)pUVM->dbgf.s.pbmBpOwnersAllocR3);
     366            pUVM->dbgf.s.pbmBpOwnersAllocR3 = NULL;
     367        }
     368        else
     369            rc = VERR_NO_MEMORY;
     370    }
     371
     372    return rc;
     373}
     374
     375
     376/**
     377 * Ensures that the breakpoint manager is fully initialized.
     378 *
     379 * @returns VBox status code.
     380 * @param   pUVM                The user mode VM handle.
     381 *
     382 * @thread Any thread.
     383 */
     384static int dbgfR3BpOwnerEnsureInit(PUVM pUVM)
     385{
     386    /* If the allocation bitmap is allocated initialization succeeded before. */
     387    if (RT_LIKELY(pUVM->dbgf.s.pbmBpOwnersAllocR3))
     388        return VINF_SUCCESS;
     389
     390    /* Gather all EMTs and call into ring-0 to initialize the breakpoint manager. */
     391    return VMMR3EmtRendezvous(pUVM->pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3BpOwnerInitEmtWorker, NULL /*pvUser*/);
     392}
     393
     394
     395/**
     396 * Returns the internal breakpoint owner state for the given handle.
     397 *
     398 * @returns Pointer to the internal breakpoint owner state or NULL if the handle is invalid.
     399 * @param   pUVM                The user mode VM handle.
     400 * @param   hBpOwner            The breakpoint owner handle to resolve.
     401 */
     402DECLINLINE(PDBGFBPOWNERINT) dbgfR3BpOwnerGetByHnd(PUVM pUVM, DBGFBPOWNER hBpOwner)
     403{
     404    AssertReturn(hBpOwner < DBGF_BP_OWNER_COUNT_MAX, NULL);
     405    AssertPtrReturn(pUVM->dbgf.s.pbmBpOwnersAllocR3, NULL);
     406
     407    AssertReturn(ASMBitTest(pUVM->dbgf.s.pbmBpOwnersAllocR3, hBpOwner), NULL);
     408    return &pUVM->dbgf.s.paBpOwnersR3[hBpOwner];
     409}
     410
     411
     412/**
     413 * Retains the given breakpoint owner handle for use.
     414 *
     415 * @returns VBox status code.
     416 * @retval VERR_INVALID_HANDLE if the given breakpoint owner handle is invalid.
     417 * @param   pUVM                The user mode VM handle.
     418 * @param   hBpOwner            The breakpoint owner handle to retain, NIL_DBGFOWNER is accepted without doing anything.
     419 */
     420DECLINLINE(int) dbgfR3BpOwnerRetain(PUVM pUVM, DBGFBPOWNER hBpOwner)
     421{
     422    if (hBpOwner == NIL_DBGFBPOWNER)
     423        return VINF_SUCCESS;
     424
     425    PDBGFBPOWNERINT pBpOwner = dbgfR3BpOwnerGetByHnd(pUVM, hBpOwner);
     426    if (pBpOwner)
     427    {
     428        ASMAtomicIncU32(&pBpOwner->cRefs);
     429        return VINF_SUCCESS;
     430    }
     431
     432    return VERR_INVALID_HANDLE;
     433}
     434
     435
     436/**
     437 * Releases the given breakpoint owner handle.
     438 *
     439 * @returns VBox status code.
     440 * @retval VERR_INVALID_HANDLE if the given breakpoint owner handle is invalid.
     441 * @param   pUVM                The user mode VM handle.
     442 * @param   hBpOwner            The breakpoint owner handle to retain, NIL_DBGFOWNER is accepted without doing anything.
     443 */
     444DECLINLINE(int) dbgfR3BpOwnerRelease(PUVM pUVM, DBGFBPOWNER hBpOwner)
     445{
     446    if (hBpOwner == NIL_DBGFBPOWNER)
     447        return VINF_SUCCESS;
     448
     449    PDBGFBPOWNERINT pBpOwner = dbgfR3BpOwnerGetByHnd(pUVM, hBpOwner);
     450    if (pBpOwner)
     451    {
     452        Assert(pBpOwner->cRefs > 1);
     453        ASMAtomicDecU32(&pBpOwner->cRefs);
     454        return VINF_SUCCESS;
     455    }
     456
     457    return VERR_INVALID_HANDLE;
    316458}
    317459
     
    438580                         PDBGFBPINT *ppBp)
    439581{
     582    int rc = dbgfR3BpOwnerRetain(pUVM, hOwner);
     583    if (RT_FAILURE(rc))
     584        return rc;
     585
    440586    /*
    441587     * Search for a chunk having a free entry, allocating new chunks
     
    452598        if (idChunk == DBGF_BP_CHUNK_ID_INVALID)
    453599        {
    454             int rc = dbgfR3BpChunkAlloc(pUVM, i);
     600            rc = dbgfR3BpChunkAlloc(pUVM, i);
    455601            if (RT_FAILURE(rc))
    456602            {
     
    509655    }
    510656
     657    rc = dbgfR3BpOwnerRelease(pUVM, hOwner); AssertRC(rc);
    511658    return VERR_DBGF_NO_MORE_BP_SLOTS;
    512659}
     
    534681
    535682    /** @todo Need a trip to Ring-0 if an owner is assigned with a Ring-0 part to clear the breakpoint. */
    536     /** @todo Release owner. */
     683    int rc = dbgfR3BpOwnerRelease(pUVM, pBp->Pub.hOwner); AssertRC(rc); RT_NOREF(rc);
    537684    memset(pBp, 0, sizeof(*pBp));
    538685
     
    15491696 *
    15501697 * @returns VBox status code.
     1698 * @retval  VERR_DBGF_BP_OWNER_NO_MORE_HANDLES if there are no more free owner handles available.
    15511699 * @param   pUVM                The user mode VM handle.
    15521700 * @param   pfnBpHit            The R3 callback which is called when a breakpoint with the owner handle is hit.
    15531701 * @param   phBpOwner           Where to store the owner handle on success.
     1702 *
     1703 * @thread Any thread but might defer work to EMT on the first call.
    15541704 */
    15551705VMMR3DECL(int) DBGFR3BpOwnerCreate(PUVM pUVM, PFNDBGFBPHIT pfnBpHit, PDBGFBPOWNER phBpOwner)
     
    15621712    AssertPtrReturn(phBpOwner, VERR_INVALID_POINTER);
    15631713
    1564     return VERR_NOT_IMPLEMENTED;
     1714    int rc = dbgfR3BpOwnerEnsureInit(pUVM);
     1715    AssertRCReturn(rc ,rc);
     1716
     1717    /* Try to find a free entry in the owner table. */
     1718    for (;;)
     1719    {
     1720        /* Scan the associated bitmap for a free entry. */
     1721        int32_t iClr = ASMBitFirstClear(pUVM->dbgf.s.pbmBpOwnersAllocR3, DBGF_BP_OWNER_COUNT_MAX);
     1722        if (iClr != -1)
     1723        {
     1724            /*
     1725             * Try to allocate, we could get raced here as well. In that case
     1726             * we try again.
     1727             */
     1728            if (!ASMAtomicBitTestAndSet(pUVM->dbgf.s.pbmBpOwnersAllocR3, iClr))
     1729            {
     1730                PDBGFBPOWNERINT pBpOwner = &pUVM->dbgf.s.paBpOwnersR3[iClr];
     1731                pBpOwner->cRefs      = 1;
     1732                pBpOwner->pfnBpHitR3 = pfnBpHit;
     1733
     1734                *phBpOwner = (DBGFBPOWNER)iClr;
     1735                return VINF_SUCCESS;
     1736            }
     1737            /* else Retry with another spot. */
     1738        }
     1739        else /* no free entry in bitmap, out of entries. */
     1740        {
     1741            rc = VERR_DBGF_BP_OWNER_NO_MORE_HANDLES;
     1742            break;
     1743        }
     1744    }
     1745
     1746    return rc;
    15651747}
    15661748
     
    15701752 *
    15711753 * @returns VBox status code.
     1754 * @retval  VERR_INVALID_HANDLE if the given owner handle is invalid.
    15721755 * @retval  VERR_DBGF_OWNER_BUSY if there are still breakpoints set with the given owner handle.
    15731756 * @param   pUVM                The user mode VM handle.
     
    15821765    AssertReturn(hBpOwner != NIL_DBGFBPOWNER, VERR_INVALID_HANDLE);
    15831766
    1584     return VERR_NOT_IMPLEMENTED;
     1767    int rc = dbgfR3BpOwnerEnsureInit(pUVM);
     1768    AssertRCReturn(rc ,rc);
     1769
     1770    PDBGFBPOWNERINT pBpOwner = dbgfR3BpOwnerGetByHnd(pUVM, hBpOwner);
     1771    if (RT_LIKELY(pBpOwner))
     1772    {
     1773        if (ASMAtomicReadU32(&pBpOwner->cRefs) == 1)
     1774        {
     1775            pBpOwner->pfnBpHitR3 = NULL;
     1776            ASMAtomicDecU32(&pBpOwner->cRefs);
     1777            ASMAtomicBitClear(pUVM->dbgf.s.pbmBpOwnersAllocR3, hBpOwner);
     1778        }
     1779        else
     1780            rc = VERR_DBGF_OWNER_BUSY;
     1781    }
     1782    else
     1783        rc = VERR_INVALID_HANDLE;
     1784
     1785    return rc;
    15851786}
    15861787
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette