Changeset 87107 in vbox for trunk/src/VBox/VMM/VMMR3
- Timestamp:
- Dec 19, 2020 3:10:18 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 141970
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/DBGFR3Bp.cpp
r86754 r87107 182 182 PVM pVM = pUVM->pVM; 183 183 184 //pUVM->dbgf.s.paBpOwnersR3 = NULL; 185 //pUVM->dbgf.s.pbmBpOwnersAllocR3 = NULL; 186 184 187 /* Init hardware breakpoint states. */ 185 188 for (uint32_t i = 0; i < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints); i++) … … 227 230 DECLHIDDEN(int) dbgfR3BpTerm(PUVM pUVM) 228 231 { 232 if (pUVM->dbgf.s.pbmBpOwnersAllocR3) 233 { 234 RTMemFree((void *)pUVM->dbgf.s.pbmBpOwnersAllocR3); 235 pUVM->dbgf.s.pbmBpOwnersAllocR3 = NULL; 236 } 237 229 238 /* Free all allocated chunk bitmaps (the chunks itself are destroyed during ring-0 VM destruction). */ 230 239 for (uint32_t i = 0; i < RT_ELEMENTS(pUVM->dbgf.s.aBpChunks); i++) … … 314 323 /* Gather all EMTs and call into ring-0 to initialize the breakpoint manager. */ 315 324 return VMMR3EmtRendezvous(pUVM->pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3BpInitEmtWorker, NULL /*pvUser*/); 325 } 326 327 328 /** 329 * @callback_method_impl{FNVMMEMTRENDEZVOUS} 330 */ 331 static 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 */ 384 static 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 */ 402 DECLINLINE(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 */ 420 DECLINLINE(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 */ 444 DECLINLINE(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; 316 458 } 317 459 … … 438 580 PDBGFBPINT *ppBp) 439 581 { 582 int rc = dbgfR3BpOwnerRetain(pUVM, hOwner); 583 if (RT_FAILURE(rc)) 584 return rc; 585 440 586 /* 441 587 * Search for a chunk having a free entry, allocating new chunks … … 452 598 if (idChunk == DBGF_BP_CHUNK_ID_INVALID) 453 599 { 454 intrc = dbgfR3BpChunkAlloc(pUVM, i);600 rc = dbgfR3BpChunkAlloc(pUVM, i); 455 601 if (RT_FAILURE(rc)) 456 602 { … … 509 655 } 510 656 657 rc = dbgfR3BpOwnerRelease(pUVM, hOwner); AssertRC(rc); 511 658 return VERR_DBGF_NO_MORE_BP_SLOTS; 512 659 } … … 534 681 535 682 /** @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); 537 684 memset(pBp, 0, sizeof(*pBp)); 538 685 … … 1549 1696 * 1550 1697 * @returns VBox status code. 1698 * @retval VERR_DBGF_BP_OWNER_NO_MORE_HANDLES if there are no more free owner handles available. 1551 1699 * @param pUVM The user mode VM handle. 1552 1700 * @param pfnBpHit The R3 callback which is called when a breakpoint with the owner handle is hit. 1553 1701 * @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. 1554 1704 */ 1555 1705 VMMR3DECL(int) DBGFR3BpOwnerCreate(PUVM pUVM, PFNDBGFBPHIT pfnBpHit, PDBGFBPOWNER phBpOwner) … … 1562 1712 AssertPtrReturn(phBpOwner, VERR_INVALID_POINTER); 1563 1713 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; 1565 1747 } 1566 1748 … … 1570 1752 * 1571 1753 * @returns VBox status code. 1754 * @retval VERR_INVALID_HANDLE if the given owner handle is invalid. 1572 1755 * @retval VERR_DBGF_OWNER_BUSY if there are still breakpoints set with the given owner handle. 1573 1756 * @param pUVM The user mode VM handle. … … 1582 1765 AssertReturn(hBpOwner != NIL_DBGFBPOWNER, VERR_INVALID_HANDLE); 1583 1766 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; 1585 1786 } 1586 1787
Note:
See TracChangeset
for help on using the changeset viewer.