- Timestamp:
- Oct 29, 2020 7:59:22 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/DBGFR3Bp.cpp
r86749 r86754 342 342 343 343 /** 344 * Get a breakpoint give by address.345 *346 * @returns The breakpoint handle on success or NIL_DBGF if not found.347 * @param pUVM The user mode VM handle.348 * @param enmType The breakpoint type.349 * @param GCPtr The breakpoint address.350 * @param ppBp Where to store the pointer to the internal breakpoint state on success, optional.351 */352 static DBGFBP dbgfR3BpGetByAddr(PUVM pUVM, DBGFBPTYPE enmType, RTGCUINTPTR GCPtr, PDBGFBPINT *ppBp)353 {354 DBGFBP hBp = NIL_DBGFBP;355 356 switch (enmType)357 {358 case DBGFBPTYPE_REG:359 {360 PVM pVM = pUVM->pVM;361 VM_ASSERT_VALID_EXT_RETURN(pVM, NIL_DBGFBP);362 363 for (uint32_t i = 0; i < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints); i++)364 {365 PDBGFBPHW pHwBp = &pVM->dbgf.s.aHwBreakpoints[i];366 367 AssertCompileSize(DBGFBP, sizeof(uint32_t));368 DBGFBP hBpTmp = ASMAtomicReadU32(&pHwBp->hBp);369 if ( pHwBp->GCPtr == GCPtr370 && hBpTmp != NIL_DBGFBP)371 {372 hBp = hBpTmp;373 break;374 }375 }376 377 break;378 }379 380 case DBGFBPTYPE_INT3:381 break;382 383 default:384 AssertMsgFailed(("enmType=%d\n", enmType));385 break;386 }387 388 if ( hBp != NIL_DBGFBP389 && ppBp)390 *ppBp = dbgfR3BpGetByHnd(pUVM, hBp);391 return hBp;392 }393 394 395 /**396 344 * @callback_method_impl{FNVMMEMTRENDEZVOUS} 397 345 */ … … 1264 1212 1265 1213 /** 1214 * Get a breakpoint give by address. 1215 * 1216 * @returns The breakpoint handle on success or NIL_DBGF if not found. 1217 * @param pUVM The user mode VM handle. 1218 * @param enmType The breakpoint type. 1219 * @param GCPtr The breakpoint address. 1220 * @param ppBp Where to store the pointer to the internal breakpoint state on success, optional. 1221 */ 1222 static DBGFBP dbgfR3BpGetByAddr(PUVM pUVM, DBGFBPTYPE enmType, RTGCUINTPTR GCPtr, PDBGFBPINT *ppBp) 1223 { 1224 DBGFBP hBp = NIL_DBGFBP; 1225 1226 switch (enmType) 1227 { 1228 case DBGFBPTYPE_REG: 1229 { 1230 PVM pVM = pUVM->pVM; 1231 VM_ASSERT_VALID_EXT_RETURN(pVM, NIL_DBGFBP); 1232 1233 for (uint32_t i = 0; i < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints); i++) 1234 { 1235 PDBGFBPHW pHwBp = &pVM->dbgf.s.aHwBreakpoints[i]; 1236 1237 AssertCompileSize(DBGFBP, sizeof(uint32_t)); 1238 DBGFBP hBpTmp = ASMAtomicReadU32(&pHwBp->hBp); 1239 if ( pHwBp->GCPtr == GCPtr 1240 && hBpTmp != NIL_DBGFBP) 1241 { 1242 hBp = hBpTmp; 1243 break; 1244 } 1245 } 1246 1247 break; 1248 } 1249 1250 case DBGFBPTYPE_INT3: 1251 { 1252 const uint16_t idxL1 = DBGF_BP_INT3_L1_IDX_EXTRACT_FROM_ADDR(GCPtr); 1253 const uint32_t u32L1Entry = ASMAtomicReadU32(&pUVM->dbgf.s.CTX_SUFF(paBpLocL1)[idxL1]); 1254 1255 if (u32L1Entry != DBGF_BP_INT3_L1_ENTRY_TYPE_NULL) 1256 { 1257 uint8_t u8Type = DBGF_BP_INT3_L1_ENTRY_GET_TYPE(u32L1Entry); 1258 if (u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_BP_HND) 1259 hBp = DBGF_BP_INT3_L1_ENTRY_GET_BP_HND(u32L1Entry); 1260 else if (u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_L2_IDX) 1261 { 1262 RTGCUINTPTR GCPtrKey = DBGF_BP_INT3_L2_KEY_EXTRACT_FROM_ADDR(GCPtr); 1263 PDBGFBPL2ENTRY pL2Nd = dbgfR3BpL2GetByIdx(pUVM, DBGF_BP_INT3_L1_ENTRY_GET_L2_IDX(u32L1Entry)); 1264 1265 for (;;) 1266 { 1267 AssertPtr(pL2Nd); 1268 1269 RTGCUINTPTR GCPtrL2Entry = DBGF_BP_L2_ENTRY_GET_GCPTR(pL2Nd->u64GCPtrKeyAndBpHnd1); 1270 if (GCPtrKey == GCPtrL2Entry) 1271 { 1272 hBp = DBGF_BP_L2_ENTRY_GET_BP_HND(pL2Nd->u64GCPtrKeyAndBpHnd1, pL2Nd->u64LeftRightIdxDepthBpHnd2); 1273 break; 1274 } 1275 1276 /* Not found, get to the next level. */ 1277 uint32_t idxL2Next = (GCPtrKey < GCPtrL2Entry) 1278 ? DBGF_BP_L2_ENTRY_GET_IDX_LEFT(pL2Nd->u64LeftRightIdxDepthBpHnd2) 1279 : DBGF_BP_L2_ENTRY_GET_IDX_RIGHT(pL2Nd->u64LeftRightIdxDepthBpHnd2); 1280 /* Address not found if the entry denotes the end. */ 1281 if (idxL2Next == DBGF_BP_L2_ENTRY_IDX_END) 1282 break; 1283 1284 pL2Nd = dbgfR3BpL2GetByIdx(pUVM, idxL2Next); 1285 } 1286 } 1287 } 1288 break; 1289 } 1290 1291 default: 1292 AssertMsgFailed(("enmType=%d\n", enmType)); 1293 break; 1294 } 1295 1296 if ( hBp != NIL_DBGFBP 1297 && ppBp) 1298 *ppBp = dbgfR3BpGetByHnd(pUVM, hBp); 1299 return hBp; 1300 } 1301 1302 1303 /** 1266 1304 * @callback_method_impl{FNVMMEMTRENDEZVOUS} 1267 1305 */ … … 1603 1641 AssertRCReturn(rc, rc); 1604 1642 1605 DBGFBP hBp = NIL_DBGFBP; 1606 PDBGFBPINT pBp = NULL; 1607 rc = dbgfR3BpAlloc(pUVM, hOwner, pvUser, DBGFBPTYPE_INT3, iHitTrigger, iHitDisable, &hBp, &pBp); 1643 /* 1644 * Translate & save the breakpoint address into a guest-physical address. 1645 */ 1646 RTGCPHYS GCPhysBpAddr = NIL_RTGCPHYS; 1647 rc = DBGFR3AddrToPhys(pUVM, idSrcCpu, pAddress, &GCPhysBpAddr); 1608 1648 if (RT_SUCCESS(rc)) 1609 1649 { 1610 1650 /* 1611 * Translate & save the breakpoint address into a guest-physical address. 1651 * The physical address from DBGFR3AddrToPhys() is the start of the page, 1652 * we need the exact byte offset into the page while writing to it in dbgfR3BpInt3Arm(). 1612 1653 */ 1613 rc = DBGFR3AddrToPhys(pUVM, idSrcCpu, pAddress, &pBp->Pub.u.Int3.PhysAddr); 1654 GCPhysBpAddr |= (pAddress->FlatPtr & X86_PAGE_OFFSET_MASK); 1655 1656 PDBGFBPINT pBp = NULL; 1657 DBGFBP hBp = dbgfR3BpGetByAddr(pUVM, DBGFBPTYPE_INT3, pAddress->FlatPtr, &pBp); 1658 if ( hBp != NIL_DBGFBP 1659 && pBp->Pub.u.Int3.PhysAddr == GCPhysBpAddr) 1660 { 1661 rc = VINF_SUCCESS; 1662 if (!DBGF_BP_PUB_IS_ENABLED(pBp->Pub.fFlagsAndType)) 1663 rc = dbgfR3BpArm(pUVM, hBp, pBp); 1664 if (RT_SUCCESS(rc)) 1665 { 1666 rc = VINF_DBGF_BP_ALREADY_EXIST; 1667 if (phBp) 1668 *phBp = hBp; 1669 } 1670 return rc; 1671 } 1672 1673 rc = dbgfR3BpAlloc(pUVM, hOwner, pvUser, DBGFBPTYPE_INT3, iHitTrigger, iHitDisable, &hBp, &pBp); 1614 1674 if (RT_SUCCESS(rc)) 1615 1675 { 1616 /* 1617 * The physical address from DBGFR3AddrToPhys() is the start of the page, 1618 * we need the exact byte offset into the page while writing to it in dbgfR3BpInt3Arm(). 1619 */ 1620 pBp->Pub.u.Int3.PhysAddr |= (pAddress->FlatPtr & X86_PAGE_OFFSET_MASK); 1621 pBp->Pub.u.Int3.GCPtr = pAddress->FlatPtr; 1676 pBp->Pub.u.Int3.PhysAddr = GCPhysBpAddr; 1677 pBp->Pub.u.Int3.GCPtr = pAddress->FlatPtr; 1622 1678 1623 1679 /* Add the breakpoint to the lookup tables. */ … … 1635 1691 int rc2 = dbgfR3BpInt3Remove(pUVM, hBp, pBp); AssertRC(rc2); 1636 1692 } 1637 } 1638 1639 dbgfR3BpFree(pUVM, hBp, pBp);1693 1694 dbgfR3BpFree(pUVM, hBp, pBp); 1695 } 1640 1696 } 1641 1697 … … 2012 2068 2013 2069 /** 2014 * E MT worker for DBGFR3BpEnum().2070 * Enumerate the breakpoints. 2015 2071 * 2016 2072 * @returns VBox status code. … … 2019 2075 * @param pvUser The user argument to pass to the callback. 2020 2076 * 2021 * @thread EMT 2022 * @internal 2023 */ 2024 static DECLCALLBACK(int) dbgfR3BpEnum(PUVM pUVM, PFNDBGFBPENUM pfnCallback, void *pvUser) 2025 { 2026 /* 2027 * Validate input. 2028 */ 2029 PVM pVM = pUVM->pVM; 2030 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 2031 AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER); 2032 2033 RT_NOREF(pvUser); 2034 2035 return VERR_NOT_IMPLEMENTED; 2036 } 2037 2038 2039 /** 2040 * Enumerate the breakpoints. 2041 * 2042 * @returns VBox status code. 2043 * @param pUVM The user mode VM handle. 2044 * @param pfnCallback The callback function. 2045 * @param pvUser The user argument to pass to the callback. 2046 * 2047 * @thread Any thread but the callback will be called from EMT. 2077 * @thread Any thread. 2048 2078 */ 2049 2079 VMMR3DECL(int) DBGFR3BpEnum(PUVM pUVM, PFNDBGFBPENUM pfnCallback, void *pvUser) 2050 2080 { 2051 /* 2052 * This must be done on EMT. 2053 */ 2054 int rc = VMR3ReqPriorityCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3BpEnum, 3, pUVM, pfnCallback, pvUser); 2055 LogFlow(("DBGFR3BpEnum: returns %Rrc\n", rc)); 2056 return rc; 2057 } 2058 2081 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); 2082 2083 for (uint32_t idChunk = 0; idChunk < RT_ELEMENTS(pUVM->dbgf.s.aBpChunks); idChunk++) 2084 { 2085 PDBGFBPCHUNKR3 pBpChunk = &pUVM->dbgf.s.aBpChunks[idChunk]; 2086 2087 if (pBpChunk->idChunk == DBGF_BP_CHUNK_ID_INVALID) 2088 break; /* Stop here as the first non allocated chunk means there is no one allocated afterwards as well. */ 2089 2090 if (pBpChunk->cBpsFree < DBGF_BP_COUNT_PER_CHUNK) 2091 { 2092 /* Scan the bitmap for allocated entries. */ 2093 int32_t iAlloc = ASMBitFirstSet(pBpChunk->pbmAlloc, DBGF_BP_COUNT_PER_CHUNK); 2094 if (iAlloc != -1) 2095 { 2096 do 2097 { 2098 DBGFBP hBp = DBGF_BP_HND_CREATE(idChunk, (uint32_t)iAlloc); 2099 PDBGFBPINT pBp = dbgfR3BpGetByHnd(pUVM, hBp); 2100 2101 /* Make a copy of the breakpoints public data to have a consistent view. */ 2102 DBGFBPPUB BpPub; 2103 BpPub.cHits = ASMAtomicReadU64((volatile uint64_t *)&pBp->Pub.cHits); 2104 BpPub.iHitTrigger = ASMAtomicReadU64((volatile uint64_t *)&pBp->Pub.iHitTrigger); 2105 BpPub.iHitDisable = ASMAtomicReadU64((volatile uint64_t *)&pBp->Pub.iHitDisable); 2106 BpPub.hOwner = ASMAtomicReadU32((volatile uint32_t *)&pBp->Pub.hOwner); 2107 BpPub.fFlagsAndType = ASMAtomicReadU32((volatile uint32_t *)&pBp->Pub.fFlagsAndType); 2108 memcpy(&BpPub.u, &pBp->Pub.u, sizeof(pBp->Pub.u)); /* Is constant after allocation. */ 2109 2110 /* Check if a removal raced us. */ 2111 if (ASMBitTest(pBpChunk->pbmAlloc, iAlloc)) 2112 { 2113 int rc = pfnCallback(pUVM, pvUser, hBp, &BpPub); 2114 if (RT_FAILURE(rc) || rc == VINF_CALLBACK_RETURN) 2115 return rc; 2116 } 2117 2118 iAlloc = ASMBitNextSet(pBpChunk->pbmAlloc, DBGF_BP_COUNT_PER_CHUNK, iAlloc); 2119 } while (iAlloc != -1); 2120 } 2121 } 2122 } 2123 2124 return VINF_SUCCESS; 2125 } 2126
Note:
See TracChangeset
for help on using the changeset viewer.