- Timestamp:
- Dec 19, 2020 3:10:18 PM (4 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/DBGFR0Bp.cpp
r86704 r87107 52 52 DECLHIDDEN(void) dbgfR0BpInit(PGVM pGVM) 53 53 { 54 pGVM->dbgfr0.s.hMemObjBpOwners = NIL_RTR0MEMOBJ; 55 pGVM->dbgfr0.s.hMapObjBpOwners = NIL_RTR0MEMOBJ; 56 //pGVM->dbgfr0.s.paBpOwnersR0 = NULL; 57 54 58 for (uint32_t i = 0; i < RT_ELEMENTS(pGVM->dbgfr0.s.aBpChunks); i++) 55 59 { … … 87 91 DECLHIDDEN(void) dbgfR0BpDestroy(PGVM pGVM) 88 92 { 93 if (pGVM->dbgfr0.s.hMemObjBpOwners != NIL_RTR0MEMOBJ) 94 { 95 Assert(pGVM->dbgfr0.s.hMapObjBpOwners != NIL_RTR0MEMOBJ); 96 AssertPtr(pGVM->dbgfr0.s.paBpOwnersR0); 97 98 RTR0MEMOBJ hMemObj = pGVM->dbgfr0.s.hMapObjBpOwners; 99 pGVM->dbgfr0.s.hMapObjBpOwners = NIL_RTR0MEMOBJ; 100 RTR0MemObjFree(hMemObj, true); 101 102 hMemObj = pGVM->dbgfr0.s.hMemObjBpOwners; 103 pGVM->dbgfr0.s.hMemObjBpOwners = NIL_RTR0MEMOBJ; 104 RTR0MemObjFree(hMemObj, true); 105 } 106 89 107 if (pGVM->dbgfr0.s.fInit) 90 108 { … … 208 226 *ppaBpLocL1R3 = RTR0MemObjAddressR3(hMapObj); 209 227 pGVM->dbgfr0.s.fInit = true; 228 return rc; 229 } 230 231 RTR0MemObjFree(hMemObj, true); 232 return rc; 233 } 234 235 236 /** 237 * Worker for DBGFR0BpOwnerInitReqHandler() that does the actual initialization. 238 * 239 * @returns VBox status code. 240 * @param pGVM The global (ring-0) VM structure. 241 * @param ppaBpOwnerR3 Where to return the ring-3 breakpoint owner table base address on success. 242 * @thread EMT(0) 243 */ 244 static int dbgfR0BpOwnerInitWorker(PGVM pGVM, R3PTRTYPE(void *) *ppaBpOwnerR3) 245 { 246 /* 247 * Figure out how much memory we need for the L1 lookup table and allocate it. 248 */ 249 uint32_t const cbBpOwnerR0 = RT_ALIGN_32(DBGF_BP_OWNER_COUNT_MAX * sizeof(DBGFBPOWNERINTR0), PAGE_SIZE); 250 uint32_t const cbBpOwnerR3 = RT_ALIGN_32(DBGF_BP_OWNER_COUNT_MAX * sizeof(DBGFBPOWNERINT), PAGE_SIZE); 251 uint32_t const cbTotal = RT_ALIGN_32(cbBpOwnerR0 + cbBpOwnerR3, PAGE_SIZE); 252 253 RTR0MEMOBJ hMemObj; 254 int rc = RTR0MemObjAllocPage(&hMemObj, cbTotal, false /*fExecutable*/); 255 if (RT_FAILURE(rc)) 256 return rc; 257 RT_BZERO(RTR0MemObjAddress(hMemObj), cbTotal); 258 259 /* Map it. */ 260 RTR0MEMOBJ hMapObj; 261 rc = RTR0MemObjMapUserEx(&hMapObj, hMemObj, (RTR3PTR)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE, RTR0ProcHandleSelf(), 262 cbBpOwnerR0 /*offSub*/, cbBpOwnerR3); 263 if (RT_SUCCESS(rc)) 264 { 265 pGVM->dbgfr0.s.hMemObjBpOwners = hMemObj; 266 pGVM->dbgfr0.s.hMapObjBpOwners = hMapObj; 267 pGVM->dbgfr0.s.paBpOwnersR0 = (PDBGFBPOWNERINTR0)RTR0MemObjAddress(hMemObj); 268 269 /* 270 * We're done. 271 */ 272 *ppaBpOwnerR3 = RTR0MemObjAddressR3(hMapObj); 210 273 return rc; 211 274 } … … 349 412 350 413 /** 351 * Used by ring-3 DBGF to allocate a given chunk in the global breakpoint table.414 * Used by ring-3 DBGF to initialize the breakpoint owner table for operation. 352 415 * 353 416 * @returns VBox status code. … … 356 419 * @thread EMT(0) 357 420 */ 421 VMMR0_INT_DECL(int) DBGFR0BpOwnerInitReqHandler(PGVM pGVM, PDBGFBPOWNERINITREQ pReq) 422 { 423 LogFlow(("DBGFR0BpOwnerInitReqHandler:\n")); 424 425 /* 426 * Validate the request. 427 */ 428 AssertReturn(pReq->Hdr.cbReq == sizeof(*pReq), VERR_INVALID_PARAMETER); 429 430 int rc = GVMMR0ValidateGVMandEMT(pGVM, 0); 431 AssertRCReturn(rc, rc); 432 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. 441 * 442 * @returns VBox status code. 443 * @param pGVM The global (ring-0) VM structure. 444 * @param pReq Pointer to the request buffer. 445 * @thread EMT(0) 446 */ 358 447 VMMR0_INT_DECL(int) DBGFR0BpChunkAllocReqHandler(PGVM pGVM, PDBGFBPCHUNKALLOCREQ pReq) 359 448 { -
trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
r86704 r87107 2296 2296 break; 2297 2297 } 2298 2299 case VMMR0_DO_DBGF_BP_OWNER_INIT: 2300 { 2301 if (!pReqHdr || u64Arg || idCpu != 0) 2302 return VERR_INVALID_PARAMETER; 2303 rc = DBGFR0BpOwnerInitReqHandler(pGVM, (PDBGFBPOWNERINITREQ)pReqHdr); 2304 VMM_CHECK_SMAP_CHECK2(pGVM, RT_NOTHING); 2305 break; 2306 } 2298 2307 #endif 2299 2308 -
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 -
trunk/src/VBox/VMM/include/DBGFInternal.h
r86726 r87107 58 58 /** @name Global breakpoint table handling defines. 59 59 * @{ */ 60 /** Maximum number of breakpoint owners supported (power of two). */ 61 #define DBGF_BP_OWNER_COUNT_MAX _32K 60 62 /** Maximum number of breakpoints supported (power of two). */ 61 63 #define DBGF_BP_COUNT_MAX _1M … … 829 831 830 832 /** 833 * The internal breakpoint owner state, shared part. 834 */ 835 typedef struct DBGFBPOWNERINT 836 { 837 /** Reference counter indicating how man breakpoints use this owner currently. */ 838 volatile uint32_t cRefs; 839 /** Padding. */ 840 uint32_t u32Pad0; 841 /** Callback to call when a breakpoint has hit, Ring-3 Ptr. */ 842 R3PTRTYPE(PFNDBGFBPHIT) pfnBpHitR3; 843 } DBGFBPOWNERINT; 844 AssertCompileSize(DBGFBPOWNERINT, 16); 845 /** Pointer to an internal breakpoint owner state, shared part. */ 846 typedef DBGFBPOWNERINT *PDBGFBPOWNERINT; 847 /** Pointer to a constant internal breakpoint owner state, shared part. */ 848 typedef const DBGFBPOWNERINT *PCDBGFBPOWNERINT; 849 850 851 /** 852 * The internal breakpoint owner state, Ring-0 part. 853 */ 854 typedef struct DBGFBPOWNERINTR0 855 { 856 /** Reference counter indicating how man breakpoints use this owner currently. */ 857 volatile uint32_t cRefs; 858 /** Padding. */ 859 uint32_t u32Pad0; 860 /** Callback to call when a breakpoint has hit, Ring-0 Ptr. */ 861 R0PTRTYPE(PFNDBGFBPHIT) pfnBpHitR0; 862 } DBGFBPOWNERINTR0; 863 AssertCompileSize(DBGFBPOWNERINTR0, 16); 864 /** Pointer to an internal breakpoint owner state, shared part. */ 865 typedef DBGFBPOWNERINTR0 *PDBGFBPOWNERINTR0; 866 /** Pointer to a constant internal breakpoint owner state, shared part. */ 867 typedef const DBGFBPOWNERINTR0 *PCDBGFBPOWNERINTR0; 868 869 870 /** 831 871 * The internal breakpoint state, shared part. 832 872 */ … … 1285 1325 /** @name Breakpoint handling related state, Ring-0 only part. 1286 1326 * @{ */ 1327 /** The breakpoint owner table memory object. */ 1328 RTR0MEMOBJ hMemObjBpOwners; 1329 /** The breakpoint owner table mapping object. */ 1330 RTR0MEMOBJ hMapObjBpOwners; 1331 /** Base pointer to the breakpoint owners table. */ 1332 R0PTRTYPE(PDBGFBPOWNERINTR0) paBpOwnersR0; 1333 1287 1334 /** Global breakpoint table chunk array. */ 1288 1335 DBGFBPCHUNKR0 aBpChunks[DBGF_BP_CHUNK_COUNT]; … … 1376 1423 /** @name Breakpoint handling related state. 1377 1424 * @{ */ 1425 /** Base pointer to the breakpoint owners table. */ 1426 R3PTRTYPE(PDBGFBPOWNERINT) paBpOwnersR3; 1427 /** Pointer to the bitmap denoting occupied owner entries. */ 1428 R3PTRTYPE(volatile void *) pbmBpOwnersAllocR3; 1429 1378 1430 /** Global breakpoint table chunk array. */ 1379 1431 DBGFBPCHUNKR3 aBpChunks[DBGF_BP_CHUNK_COUNT];
Note:
See TracChangeset
for help on using the changeset viewer.