儲存庫 vbox 的更動 89924
- 時間撮記:
- 2021-6-28 上午08:16:29 (4 年 以前)
- svn:sync-xref-src-repo-rev:
- 145382
- 位置:
- trunk
- 檔案:
-
- 修改 7 筆資料
圖例:
- 未更動
- 新增
- 刪除
-
trunk/include/VBox/vmm/dbgf.h
r89912 r89924 854 854 /** All kind of access (read, write, all sizes). */ 855 855 #define DBGFBPIOACCESS_ALL UINT32_C(0x00001f1f) 856 /** All kind of access for MMIO (read, write, all sizes). */ 857 #define DBGFBPIOACCESS_ALL_MMIO DBGFBPIOACCESS_ALL 858 /** All kind of access (read, write, all sizes). */ 859 #define DBGFBPIOACCESS_ALL_PORT_IO UINT32_C(0x00000303) 856 860 857 861 /** The acceptable mask for I/O ports. */ … … 970 974 * after the instruction causing the breakpoint to hit was executed. */ 971 975 #define DBGF_BP_F_HIT_EXEC_AFTER RT_BIT(2) 976 /** The acceptable flags mask. */ 977 #define DBGF_BP_F_VALID_MASK UINT32_C(0x00000007) 972 978 /** @} */ 973 979 … … 998 1004 999 1005 1006 /** 1007 * I/O breakpoint hit handler. 1008 * 1009 * @returns Strict VBox status code. 1010 * @retval VINF_SUCCESS if the breakpoint was handled and guest execution can resume. 1011 * @retval VINF_DBGF_BP_HALT if guest execution should be stopped and the debugger should be invoked. 1012 * @retval VINF_DBGF_R3_BP_OWNER_DEFER return to ring-3 and invoke the owner callback there again. 1013 * 1014 * @param pVM The cross-context VM structure pointer. 1015 * @param idCpu ID of the vCPU triggering the breakpoint. 1016 * @param pvUserBp User argument of the set breakpoint. 1017 * @param hBp The breakpoint handle. 1018 * @param pBpPub Pointer to the readonly public state of the breakpoint. 1019 * @param fFlags Flags indicating when the handler was called (DBGF_BP_F_HIT_EXEC_BEFORE vs DBGF_BP_F_HIT_EXEC_AFTER). 1020 * @param fAccess Access flags, see DBGFBPIOACCESS_XXX. 1021 * @param uAddr The address of the access, for port I/O this will hold the port number. 1022 * @param uValue The value read or written (the value for reads is only valid when DBGF_BP_F_HIT_EXEC_AFTER is set). 1023 * 1024 * @remarks The handler is called on the EMT of vCPU triggering the breakpoint and no locks are held. 1025 * @remarks Any status code returned other than the ones mentioned will send the VM straight into a 1026 * guru meditation. 1027 */ 1028 typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNDBGFBPIOHIT,(PVM pVM, VMCPUID idCpu, void *pvUserBp, DBGFBP hBp, PCDBGFBPPUB pBpPub, 1029 uint16_t fFlags, uint32_t fAccess, uint64_t uAddr, uint64_t uValue)); 1030 /** Pointer to a FNDBGFBPIOHIT(). */ 1031 typedef FNDBGFBPIOHIT *PFNDBGFBPIOHIT; 1032 1033 1000 1034 #ifdef IN_RING3 1001 1035 /** @defgroup grp_dbgf_bp_r3 The DBGF Breakpoint Host Context Ring-3 API 1002 1036 * @{ */ 1003 VMMR3DECL(int) DBGFR3BpOwnerCreate(PUVM pUVM, PFNDBGFBPHIT pfnBpHit, P DBGFBPOWNER phBpOwner);1037 VMMR3DECL(int) DBGFR3BpOwnerCreate(PUVM pUVM, PFNDBGFBPHIT pfnBpHit, PFNDBGFBPIOHIT pfnBpIoHit, PDBGFBPOWNER phBpOwner); 1004 1038 VMMR3DECL(int) DBGFR3BpOwnerDestroy(PUVM pUVM, DBGFBPOWNER hBpOwner); 1005 1039 … … 1026 1060 VMMR3DECL(int) DBGFR3BpSetMmioEx(PUVM pUVM, DBGFBPOWNER hOwner, void *pvUser, 1027 1061 RTGCPHYS GCPhys, uint32_t cb, uint32_t fAccess, 1028 uint 64_t iHitTrigger, uint64_t iHitDisable, PDBGFBP phBp);1062 uint32_t fFlags, uint64_t iHitTrigger, uint64_t iHitDisable, PDBGFBP phBp); 1029 1063 VMMR3DECL(int) DBGFR3BpClear(PUVM pUVM, DBGFBP hBp); 1030 1064 VMMR3DECL(int) DBGFR3BpEnable(PUVM pUVM, DBGFBP hBp); … … 1058 1092 VMMR0_INT_DECL(void) DBGFR0CleanupVM(PGVM pGVM); 1059 1093 1060 VMMR0_INT_DECL(int) DBGFR0BpOwnerSetUpContext(PGVM pGVM, DBGFBPOWNER hBpOwner, PFNDBGFBPHIT pfnBpHit );1094 VMMR0_INT_DECL(int) DBGFR0BpOwnerSetUpContext(PGVM pGVM, DBGFBPOWNER hBpOwner, PFNDBGFBPHIT pfnBpHit, PFNDBGFBPIOHIT pfnBpIoHit); 1061 1095 VMMR0_INT_DECL(int) DBGFR0BpOwnerDestroyContext(PGVM pGVM, DBGFBPOWNER hBpOwner); 1062 1096 … … 1076 1110 VMM_INT_DECL(bool) DBGFIsStepping(PVMCPU pVCpu); 1077 1111 VMM_INT_DECL(VBOXSTRICTRC) DBGFBpCheckIo(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, RTIOPORT uIoPort, uint8_t cbValue); 1112 VMM_INT_DECL(VBOXSTRICTRC) DBGFBpCheckPortIo(PVMCC pVM, PVMCPU pVCpu, RTIOPORT uIoPort, 1113 uint32_t fAccess, uint32_t uValue, bool fBefore); 1078 1114 VMM_INT_DECL(VBOXSTRICTRC) DBGFEventGenericWithArgs(PVM pVM, PVMCPU pVCpu, DBGFEVENTTYPE enmEvent, DBGFEVENTCTX enmCtx, 1079 1115 unsigned cArgs, ...); -
trunk/src/VBox/VMM/VMMAll/DBGFAllBp.cpp
r87776 r89924 169 169 if (pBpOwnerR0) 170 170 { 171 AssertReturn(pBpOwnerR0->pfnBpIoHitR0, VERR_DBGF_BP_IPE_1); 172 171 173 VBOXSTRICTRC rcStrict = VINF_SUCCESS; 172 174 … … 234 236 235 237 /** 238 * Executes the actions associated with the given port I/O breakpoint. 239 * 240 * @returns VBox status code. 241 * @param pVM The cross context VM structure. 242 * @param pVCpu The cross context virtual CPU structure. 243 * @param fBefore Flag whether the check is done before the access is carried out, 244 * false if it is done after the access. 245 * @param fAccess Access flags, see DBGFBPIOACCESS_XXX. 246 * @param uAddr The address of the access, for port I/O this will hold the port number. 247 * @param uValue The value read or written (the value for reads is only valid when DBGF_BP_F_HIT_EXEC_AFTER is set). 248 * @param hBp The breakpoint handle which hit. 249 * @param pBp The shared breakpoint state. 250 * @param pBpR0 The ring-0 only breakpoint state. 251 */ 252 #ifdef IN_RING0 253 DECLINLINE(VBOXSTRICTRC) dbgfBpPortIoHit(PVMCC pVM, PVMCPU pVCpu, bool fBefore, uint32_t fAccess, uint64_t uAddr, uint64_t uValue, 254 DBGFBP hBp, PDBGFBPINT pBp, PDBGFBPINTR0 pBpR0) 255 #else 256 DECLINLINE(VBOXSTRICTRC) dbgfBpPortIoHit(PVMCC pVM, PVMCPU pVCpu, bool fBefore, uint32_t fAccess, uint64_t uAddr, uint64_t uValue, 257 DBGFBP hBp, PDBGFBPINT pBp) 258 #endif 259 { 260 ASMAtomicIncU64(&pBp->Pub.cHits); 261 262 VBOXSTRICTRC rcStrict = VINF_EM_DBG_BREAKPOINT; 263 #ifdef IN_RING0 264 PCDBGFBPOWNERINTR0 pBpOwnerR0 = dbgfR0BpOwnerGetByHnd(pVM, 265 pBpR0->fInUse 266 ? pBpR0->hOwner 267 : NIL_DBGFBPOWNER); 268 if (pBpOwnerR0) 269 { 270 AssertReturn(pBpOwnerR0->pfnBpIoHitR0, VERR_DBGF_BP_IPE_1); 271 rcStrict = pBpOwnerR0->pfnBpIoHitR0(pVM, pVCpu->idCpuUnsafe, pBpR0->pvUserR0, hBp, &pBp->Pub, 272 fBefore 273 ? DBGF_BP_F_HIT_EXEC_BEFORE 274 : DBGF_BP_F_HIT_EXEC_AFTER, 275 fAccess, uAddr, uValue); 276 } 277 else 278 { 279 pVCpu->dbgf.s.fBpInvokeOwnerCallback = true; /* Need to check this for ring-3 only owners. */ 280 pVCpu->dbgf.s.hBpActive = hBp; 281 pVCpu->dbgf.s.fBpIoActive = true; 282 pVCpu->dbgf.s.fBpIoBefore = fBefore; 283 pVCpu->dbgf.s.uBpIoAddress = uAddr; 284 pVCpu->dbgf.s.fBpIoAccess = fAccess; 285 pVCpu->dbgf.s.uBpIoValue = uValue; 286 } 287 #else 288 /* Resolve owner (can be NIL_DBGFBPOWNER) and invoke callback if there is one. */ 289 if (pBp->Pub.hOwner != NIL_DBGFBPOWNER) 290 { 291 PCDBGFBPOWNERINT pBpOwner = dbgfR3BpOwnerGetByHnd(pVM->pUVM, pBp->Pub.hOwner); 292 if (pBpOwner) 293 { 294 AssertReturn(pBpOwner->pfnBpIoHitR3, VERR_DBGF_BP_IPE_1); 295 rcStrict = pBpOwner->pfnBpIoHitR3(pVM, pVCpu->idCpu, pBp->pvUserR3, hBp, &pBp->Pub, 296 fBefore 297 ? DBGF_BP_F_HIT_EXEC_BEFORE 298 : DBGF_BP_F_HIT_EXEC_AFTER, 299 fAccess, uAddr, uValue); 300 } 301 } 302 #endif 303 if ( rcStrict == VINF_DBGF_BP_HALT 304 || rcStrict == VINF_DBGF_R3_BP_OWNER_DEFER) 305 { 306 pVCpu->dbgf.s.hBpActive = hBp; 307 if (rcStrict == VINF_DBGF_R3_BP_OWNER_DEFER) 308 pVCpu->dbgf.s.fBpInvokeOwnerCallback = true; 309 else 310 pVCpu->dbgf.s.fBpInvokeOwnerCallback = false; 311 rcStrict = VINF_EM_DBG_BREAKPOINT; 312 } 313 else if ( rcStrict != VINF_SUCCESS 314 && rcStrict != VINF_EM_DBG_BREAKPOINT) 315 rcStrict = VERR_DBGF_BP_OWNER_CALLBACK_WRONG_STATUS; /* Guru meditation. */ 316 317 return rcStrict; 318 } 319 320 321 /** 236 322 * Walks the L2 table starting at the given root index searching for the given key. 237 323 * … … 294 380 295 381 return VERR_DBGF_BP_L2_LOOKUP_FAILED; 382 } 383 384 385 /** 386 * Checks whether there is a port I/O breakpoint for the given range and access size. 387 * 388 * @returns VBox status code. 389 * @retval VINF_EM_DBG_BREAKPOINT means there is a breakpoint pending. 390 * @retval VINF_SUCCESS means everything is fine to continue. 391 * @retval anything else means a fatal error causing a guru meditation. 392 * 393 * @param pVM The current context VM structure. 394 * @param pVCpu The cross context virtual CPU structure. 395 * @param uIoPort The I/O port being accessed. 396 * @param fAccess Appropriate DBGFBPIOACCESS_XXX. 397 * @param uValue The value being written to or read from the device 398 * (The value is only valid for a read when the 399 * call is made after the access, writes are always valid). 400 * @param fBefore Flag whether the check is done before the access is carried out, 401 * false if it is done after the access. 402 */ 403 VMM_INT_DECL(VBOXSTRICTRC) DBGFBpCheckPortIo(PVMCC pVM, PVMCPU pVCpu, RTIOPORT uIoPort, 404 uint32_t fAccess, uint32_t uValue, bool fBefore) 405 { 406 RT_NOREF(uValue); /** @todo Trigger only on specific values. */ 407 408 /* Don't trigger in single stepping mode. */ 409 if (pVCpu->dbgf.s.fSingleSteppingRaw) 410 return VINF_SUCCESS; 411 412 #if defined(IN_RING0) 413 uint32_t volatile *paBpLocPortIo = pVM->dbgfr0.s.CTX_SUFF(paBpLocPortIo); 414 #elif defined(IN_RING3) 415 PUVM pUVM = pVM->pUVM; 416 uint32_t volatile *paBpLocPortIo = pUVM->dbgf.s.CTX_SUFF(paBpLocPortIo); 417 #else 418 # error "Unsupported host context" 419 #endif 420 if (paBpLocPortIo) 421 { 422 const uint32_t u32Entry = ASMAtomicReadU32(&paBpLocPortIo[uIoPort]); 423 if (u32Entry != DBGF_BP_INT3_L1_ENTRY_TYPE_NULL) 424 { 425 uint8_t u8Type = DBGF_BP_INT3_L1_ENTRY_GET_TYPE(u32Entry); 426 if (RT_LIKELY(u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_BP_HND)) 427 { 428 DBGFBP hBp = DBGF_BP_INT3_L1_ENTRY_GET_BP_HND(u32Entry); 429 430 /* Query the internal breakpoint state from the handle. */ 431 #ifdef IN_RING3 432 PDBGFBPINT pBp = dbgfBpGetByHnd(pVM, hBp); 433 #else 434 PDBGFBPINTR0 pBpR0 = NULL; 435 PDBGFBPINT pBp = dbgfBpGetByHnd(pVM, hBp, &pBpR0); 436 #endif 437 if ( pBp 438 && DBGF_BP_PUB_GET_TYPE(&pBp->Pub) == DBGFBPTYPE_PORT_IO) 439 { 440 if ( uIoPort >= pBp->Pub.u.PortIo.uPort 441 && uIoPort < pBp->Pub.u.PortIo.uPort + pBp->Pub.u.PortIo.cPorts 442 && pBp->Pub.u.PortIo.fAccess & fAccess 443 && ( ( fBefore 444 && DBGF_BP_PUB_IS_EXEC_BEFORE(&pBp->Pub)) 445 || ( !fBefore 446 && DBGF_BP_PUB_IS_EXEC_AFTER(&pBp->Pub)))) 447 #ifdef IN_RING3 448 return dbgfBpPortIoHit(pVM, pVCpu, fBefore, fAccess, uIoPort, uValue, hBp, pBp); 449 #else 450 return dbgfBpPortIoHit(pVM, pVCpu, fBefore, fAccess, uIoPort, uValue, hBp, pBp, pBpR0); 451 #endif 452 /* else: No matching port I/O breakpoint. */ 453 } 454 else /* Invalid breakpoint handle or not an port I/O breakpoint. */ 455 return VERR_DBGF_BP_L1_LOOKUP_FAILED; 456 } 457 else /* Some invalid type. */ 458 return VERR_DBGF_BP_L1_LOOKUP_FAILED; 459 } 460 } 461 462 return VINF_SUCCESS; 296 463 } 297 464 -
trunk/src/VBox/VMM/VMMR0/DBGFR0Bp.cpp
r89912 r89924 496 496 AssertRCReturn(rc, rc); 497 497 498 AssertReturn( !pGVM->dbgfr0.s.fInit, VERR_WRONG_ORDER);498 AssertReturn(pGVM->dbgfr0.s.fInit, VERR_WRONG_ORDER); 499 499 AssertReturn(!pGVM->dbgfr0.s.paBpLocPortIoR0, VERR_WRONG_ORDER); 500 500 -
trunk/src/VBox/VMM/VMMR3/DBGFR3Bp.cpp
r89913 r89924 91 91 * | . | | . | 92 92 * +------------+ +-----------+ 93 * L2 idx AVL93 * L2 idx BST 94 94 * @endverbatim 95 95 * … … 107 107 * matching the lowest 16bits and the search must continue in the L2 table with the 108 108 * remaining 28bits acting as an index into the L2 table indicating the search root. 109 * -# The L2 table consists of multiple index based AVLtrees, there is one for each reference109 * -# The L2 table consists of multiple index based binary search trees, there is one for each reference 110 110 * from the L1 table. The key for the table are the upper 6 bytes of the breakpoint address 111 111 * used for searching. This tree is traversed until either a matching address is found and … … 133 133 * are always mapped into ring-0 and ring-3 with different base addresses. 134 134 * - Efficent breakpoint allocation is done by having a global bitmap indicating free 135 * and occupied breakpoint entries. Same applies for the L2 AVLtable.135 * and occupied breakpoint entries. Same applies for the L2 BST table. 136 136 * - Special care must be taken when modifying the L1 and L2 tables as other EMTs 137 137 * might still access it (want to try a lockless approach first using … … 139 139 * - Each BP entry is supposed to be 64 byte big and each chunk should contain 65536 140 140 * breakpoints which results in 4MiB for each chunk plus the allocation bitmap. 141 * - ring-0 has to take special care when traversing the L2 AVL treeto not run into cycles141 * - ring-0 has to take special care when traversing the L2 BST to not run into cycles 142 142 * and do strict bounds checking before accessing anything. The L1 and L2 table 143 143 * are written to from ring-3 only. Same goes for the breakpoint table with the … … 463 463 464 464 /** 465 * Returns the internal breakpoint owner state for the given handle.466 *467 * @returns Pointer to the internal breakpoint owner state or NULL if the handle is invalid.468 * @param pUVM The user mode VM handle.469 * @param hBpOwner The breakpoint owner handle to resolve.470 */471 DECLINLINE(PDBGFBPOWNERINT) dbgfR3BpOwnerGetByHnd(PUVM pUVM, DBGFBPOWNER hBpOwner)472 {473 AssertReturn(hBpOwner < DBGF_BP_OWNER_COUNT_MAX, NULL);474 AssertPtrReturn(pUVM->dbgf.s.pbmBpOwnersAllocR3, NULL);475 476 AssertReturn(ASMBitTest(pUVM->dbgf.s.pbmBpOwnersAllocR3, hBpOwner), NULL);477 return &pUVM->dbgf.s.paBpOwnersR3[hBpOwner];478 }479 480 481 /**482 465 * Retains the given breakpoint owner handle for use. 483 466 * … … 486 469 * @param pUVM The user mode VM handle. 487 470 * @param hBpOwner The breakpoint owner handle to retain, NIL_DBGFOWNER is accepted without doing anything. 488 */ 489 DECLINLINE(int) dbgfR3BpOwnerRetain(PUVM pUVM, DBGFBPOWNER hBpOwner) 471 * @param fIo Flag whether the owner must have the I/O handler set because it used by an I/O breakpoint. 472 */ 473 DECLINLINE(int) dbgfR3BpOwnerRetain(PUVM pUVM, DBGFBPOWNER hBpOwner, bool fIo) 490 474 { 491 475 if (hBpOwner == NIL_DBGFBPOWNER) … … 495 479 if (pBpOwner) 496 480 { 481 AssertReturn ( ( fIo 482 && pBpOwner->pfnBpIoHitR3) 483 || ( !fIo 484 && pBpOwner->pfnBpHitR3), 485 VERR_INVALID_HANDLE); 497 486 ASMAtomicIncU32(&pBpOwner->cRefs); 498 487 return VINF_SUCCESS; … … 650 639 PDBGFBPINT *ppBp) 651 640 { 652 int rc = dbgfR3BpOwnerRetain(pUVM, hOwner); 641 bool fIo = enmType == DBGFBPTYPE_PORT_IO 642 || enmType == DBGFBPTYPE_MMIO; 643 int rc = dbgfR3BpOwnerRetain(pUVM, hOwner, fIo); 653 644 if (RT_FAILURE(rc)) 654 645 return rc; … … 1682 1673 AssertReturn(u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_BP_HND, VERR_DBGF_BP_IPE_7); 1683 1674 1684 bool fXchg = ASMAtomicCmpXchgU32(&pUVM->dbgf.s.paBpLoc L1R3[idxPort], DBGF_BP_INT3_L1_ENTRY_TYPE_NULL, u32Entry);1675 bool fXchg = ASMAtomicCmpXchgU32(&pUVM->dbgf.s.paBpLocPortIoR3[idxPort], DBGF_BP_INT3_L1_ENTRY_TYPE_NULL, u32Entry); 1685 1676 Assert(fXchg); RT_NOREF(fXchg); 1686 1677 } … … 1752 1743 static int dbgfR3BpArm(PUVM pUVM, DBGFBP hBp, PDBGFBPINT pBp) 1753 1744 { 1754 int rc ;1745 int rc = VINF_SUCCESS; 1755 1746 PVM pVM = pUVM->pVM; 1756 1747 … … 1802 1793 } 1803 1794 case DBGFBPTYPE_PORT_IO: 1795 { 1796 dbgfR3BpSetEnabled(pBp, true /*fEnabled*/); 1797 ASMAtomicIncU32(&pUVM->dbgf.s.cPortIoBps); 1798 IOMR3NotifyBreakpointCountChange(pVM, true /*fPortIo*/, false /*fMmio*/); 1799 break; 1800 } 1804 1801 case DBGFBPTYPE_MMIO: 1805 1802 rc = VERR_NOT_IMPLEMENTED; … … 1826 1823 static int dbgfR3BpDisarm(PUVM pUVM, DBGFBP hBp, PDBGFBPINT pBp) 1827 1824 { 1828 int rc ;1825 int rc = VINF_SUCCESS; 1829 1826 PVM pVM = pUVM->pVM; 1830 1827 … … 1870 1867 } 1871 1868 case DBGFBPTYPE_PORT_IO: 1869 { 1870 dbgfR3BpSetEnabled(pBp, false /*fEnabled*/); 1871 uint32_t cPortIoBps = ASMAtomicDecU32(&pUVM->dbgf.s.cPortIoBps); 1872 if (!cPortIoBps) /** @todo Need to gather all EMTs to not have a stray EMT accessing BP data when it might go away. */ 1873 IOMR3NotifyBreakpointCountChange(pVM, false /*fPortIo*/, false /*fMmio*/); 1874 break; 1875 } 1872 1876 case DBGFBPTYPE_MMIO: 1873 1877 rc = VERR_NOT_IMPLEMENTED; … … 1883 1887 1884 1888 /** 1889 * Worker for DBGFR3BpHit() differnetiating on the breakpoint type. 1890 * 1891 * @returns Strict VBox status code. 1892 * @param pVM The cross context VM structure. 1893 * @param pVCpu The vCPU the breakpoint event happened on. 1894 * @param hBp The breakpoint handle. 1895 * @param pBp The breakpoint data. 1896 * @param pBpOwner The breakpoint owner data. 1897 * 1898 * @thread EMT 1899 */ 1900 static VBOXSTRICTRC dbgfR3BpHit(PVM pVM, PVMCPU pVCpu, DBGFBP hBp, PDBGFBPINT pBp, PCDBGFBPOWNERINT pBpOwner) 1901 { 1902 VBOXSTRICTRC rcStrict; 1903 1904 switch (DBGF_BP_PUB_GET_TYPE(&pBp->Pub)) 1905 { 1906 case DBGFBPTYPE_REG: 1907 case DBGFBPTYPE_INT3: 1908 { 1909 if (DBGF_BP_PUB_IS_EXEC_BEFORE(&pBp->Pub)) 1910 rcStrict = pBpOwner->pfnBpHitR3(pVM, pVCpu->idCpu, pBp->pvUserR3, hBp, &pBp->Pub, DBGF_BP_F_HIT_EXEC_BEFORE); 1911 if (rcStrict == VINF_SUCCESS) 1912 { 1913 uint8_t abInstr[DBGF_BP_INSN_MAX]; 1914 RTGCPTR const GCPtrInstr = pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base; 1915 int rc = PGMPhysSimpleReadGCPtr(pVCpu, &abInstr[0], GCPtrInstr, sizeof(abInstr)); 1916 AssertRC(rc); 1917 if (RT_SUCCESS(rc)) 1918 { 1919 /* Replace the int3 with the original instruction byte. */ 1920 abInstr[0] = pBp->Pub.u.Int3.bOrg; 1921 rcStrict = IEMExecOneWithPrefetchedByPC(pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx), GCPtrInstr, &abInstr[0], sizeof(abInstr)); 1922 if ( rcStrict == VINF_SUCCESS 1923 && DBGF_BP_PUB_IS_EXEC_AFTER(&pBp->Pub)) 1924 { 1925 VBOXSTRICTRC rcStrict2 = pBpOwner->pfnBpHitR3(pVM, pVCpu->idCpu, pBp->pvUserR3, hBp, &pBp->Pub, DBGF_BP_F_HIT_EXEC_AFTER); 1926 if (rcStrict2 == VINF_SUCCESS) 1927 return VBOXSTRICTRC_VAL(rcStrict); 1928 else if (rcStrict2 != VINF_DBGF_BP_HALT) 1929 return VERR_DBGF_BP_OWNER_CALLBACK_WRONG_STATUS; 1930 } 1931 else 1932 return VBOXSTRICTRC_VAL(rcStrict); 1933 } 1934 } 1935 break; 1936 } 1937 case DBGFBPTYPE_PORT_IO: 1938 case DBGFBPTYPE_MMIO: 1939 { 1940 pVCpu->dbgf.s.fBpIoActive = false; 1941 rcStrict = pBpOwner->pfnBpIoHitR3(pVM, pVCpu->idCpu, pBp->pvUserR3, hBp, &pBp->Pub, 1942 pVCpu->dbgf.s.fBpIoBefore 1943 ? DBGF_BP_F_HIT_EXEC_BEFORE 1944 : DBGF_BP_F_HIT_EXEC_AFTER, 1945 pVCpu->dbgf.s.fBpIoAccess, pVCpu->dbgf.s.uBpIoAddress, 1946 pVCpu->dbgf.s.uBpIoValue); 1947 1948 break; 1949 } 1950 default: 1951 AssertMsgFailedReturn(("Invalid breakpoint type %d\n", DBGF_BP_PUB_GET_TYPE(&pBp->Pub)), 1952 VERR_IPE_NOT_REACHED_DEFAULT_CASE); 1953 } 1954 1955 return rcStrict; 1956 } 1957 1958 1959 /** 1885 1960 * Creates a new breakpoint owner returning a handle which can be used when setting breakpoints. 1886 1961 * … … 1889 1964 * @param pUVM The user mode VM handle. 1890 1965 * @param pfnBpHit The R3 callback which is called when a breakpoint with the owner handle is hit. 1966 * @param pfnBpIoHit The R3 callback which is called when a I/O breakpoint with the owner handle is hit. 1891 1967 * @param phBpOwner Where to store the owner handle on success. 1892 1968 * 1893 1969 * @thread Any thread but might defer work to EMT on the first call. 1894 1970 */ 1895 VMMR3DECL(int) DBGFR3BpOwnerCreate(PUVM pUVM, PFNDBGFBPHIT pfnBpHit, P DBGFBPOWNER phBpOwner)1971 VMMR3DECL(int) DBGFR3BpOwnerCreate(PUVM pUVM, PFNDBGFBPHIT pfnBpHit, PFNDBGFBPIOHIT pfnBpIoHit, PDBGFBPOWNER phBpOwner) 1896 1972 { 1897 1973 /* … … 1899 1975 */ 1900 1976 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); 1901 Assert PtrReturn(pfnBpHit, VERR_INVALID_PARAMETER);1977 AssertReturn(pfnBpHit || pfnBpIoHit, VERR_INVALID_PARAMETER); 1902 1978 AssertPtrReturn(phBpOwner, VERR_INVALID_POINTER); 1903 1979 … … 1919 1995 { 1920 1996 PDBGFBPOWNERINT pBpOwner = &pUVM->dbgf.s.paBpOwnersR3[iClr]; 1921 pBpOwner->cRefs = 1; 1922 pBpOwner->pfnBpHitR3 = pfnBpHit; 1997 pBpOwner->cRefs = 1; 1998 pBpOwner->pfnBpHitR3 = pfnBpHit; 1999 pBpOwner->pfnBpIoHitR3 = pfnBpIoHit; 1923 2000 1924 2001 *phBpOwner = (DBGFBPOWNER)iClr; … … 2253 2330 uint64_t iHitTrigger, uint64_t iHitDisable, PDBGFBP phBp) 2254 2331 { 2255 return DBGFR3BpSetPortIoEx(pUVM, NIL_DBGFBPOWNER, NULL /*pvUser*/, uPort, cPorts, 2256 DBGF_BP_F_DEFAULT, fAccess,iHitTrigger, iHitDisable, phBp);2332 return DBGFR3BpSetPortIoEx(pUVM, NIL_DBGFBPOWNER, NULL /*pvUser*/, uPort, cPorts, fAccess, 2333 DBGF_BP_F_DEFAULT, iHitTrigger, iHitDisable, phBp); 2257 2334 } 2258 2335 … … 2286 2363 AssertReturn(!(fAccess & ~DBGFBPIOACCESS_VALID_MASK_PORT_IO), VERR_INVALID_FLAGS); 2287 2364 AssertReturn(fAccess, VERR_INVALID_FLAGS); 2365 AssertReturn(!(fFlags & ~DBGF_BP_F_VALID_MASK), VERR_INVALID_FLAGS); 2366 AssertReturn(fFlags, VERR_INVALID_FLAGS); 2288 2367 AssertReturn(iHitTrigger <= iHitDisable, VERR_INVALID_PARAMETER); 2289 2368 AssertPtrReturn(phBp, VERR_INVALID_POINTER); 2290 2369 AssertReturn(cPorts > 0, VERR_OUT_OF_RANGE); 2291 AssertReturn((RTIOPORT)(uPort + cPorts) <uPort, VERR_OUT_OF_RANGE);2370 AssertReturn((RTIOPORT)(uPort + (cPorts - 1)) >= uPort, VERR_OUT_OF_RANGE); 2292 2371 2293 2372 int rc = dbgfR3BpPortIoEnsureInit(pUVM); … … 2364 2443 { 2365 2444 return DBGFR3BpSetMmioEx(pUVM, NIL_DBGFBPOWNER, NULL /*pvUser*/, GCPhys, cb, fAccess, 2366 iHitTrigger, iHitDisable, phBp);2445 DBGF_BP_F_DEFAULT, iHitTrigger, iHitDisable, phBp); 2367 2446 } 2368 2447 … … 2378 2457 * @param cb The size of the MMIO range to break on. 2379 2458 * @param fAccess The access we want to break on. 2459 * @param fFlags Combination of DBGF_BP_F_XXX. 2380 2460 * @param iHitTrigger The hit count at which the breakpoint start 2381 2461 * triggering. Use 0 (or 1) if it's gonna trigger at … … 2389 2469 VMMR3DECL(int) DBGFR3BpSetMmioEx(PUVM pUVM, DBGFBPOWNER hOwner, void *pvUser, 2390 2470 RTGCPHYS GCPhys, uint32_t cb, uint32_t fAccess, 2391 uint 64_t iHitTrigger, uint64_t iHitDisable, PDBGFBP phBp)2471 uint32_t fFlags, uint64_t iHitTrigger, uint64_t iHitDisable, PDBGFBP phBp) 2392 2472 { 2393 2473 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); … … 2395 2475 AssertReturn(!(fAccess & ~DBGFBPIOACCESS_VALID_MASK_MMIO), VERR_INVALID_FLAGS); 2396 2476 AssertReturn(fAccess, VERR_INVALID_FLAGS); 2477 AssertReturn(!(fFlags & ~DBGF_BP_F_VALID_MASK), VERR_INVALID_FLAGS); 2478 AssertReturn(fFlags, VERR_INVALID_FLAGS); 2397 2479 AssertReturn(iHitTrigger <= iHitDisable, VERR_INVALID_PARAMETER); 2398 2480 AssertPtrReturn(phBp, VERR_INVALID_POINTER); … … 2595 2677 { 2596 2678 DBGFBP hBp = pVCpu->dbgf.s.hBpActive; 2597 PDBGFBPINT pBp = dbgfR3BpGetByHnd(pVM->pUVM, pVCpu->dbgf.s.hBpActive); 2679 pVCpu->dbgf.s.hBpActive = NIL_DBGFBP; 2680 pVCpu->dbgf.s.fBpInvokeOwnerCallback = false; 2681 2682 PDBGFBPINT pBp = dbgfR3BpGetByHnd(pVM->pUVM, hBp); 2598 2683 AssertReturn(pBp, VERR_DBGF_BP_IPE_9); 2599 2684 … … 2604 2689 if (pBpOwner) 2605 2690 { 2606 VBOXSTRICTRC rcStrict = VINF_SUCCESS; 2607 2608 if (DBGF_BP_PUB_IS_EXEC_BEFORE(&pBp->Pub)) 2609 rcStrict = pBpOwner->pfnBpHitR3(pVM, pVCpu->idCpu, pBp->pvUserR3, hBp, &pBp->Pub, DBGF_BP_F_HIT_EXEC_BEFORE); 2610 if (rcStrict == VINF_SUCCESS) 2611 { 2612 uint8_t abInstr[DBGF_BP_INSN_MAX]; 2613 RTGCPTR const GCPtrInstr = pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base; 2614 int rc = PGMPhysSimpleReadGCPtr(pVCpu, &abInstr[0], GCPtrInstr, sizeof(abInstr)); 2615 AssertRC(rc); 2616 if (RT_SUCCESS(rc)) 2617 { 2618 /* Replace the int3 with the original instruction byte. */ 2619 abInstr[0] = pBp->Pub.u.Int3.bOrg; 2620 rcStrict = IEMExecOneWithPrefetchedByPC(pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx), GCPtrInstr, &abInstr[0], sizeof(abInstr)); 2621 if ( rcStrict == VINF_SUCCESS 2622 && DBGF_BP_PUB_IS_EXEC_AFTER(&pBp->Pub)) 2623 { 2624 VBOXSTRICTRC rcStrict2 = pBpOwner->pfnBpHitR3(pVM, pVCpu->idCpu, pBp->pvUserR3, hBp, &pBp->Pub, DBGF_BP_F_HIT_EXEC_AFTER); 2625 if (rcStrict2 == VINF_SUCCESS) 2626 return VBOXSTRICTRC_VAL(rcStrict); 2627 else if (rcStrict2 != VINF_DBGF_BP_HALT) 2628 return VERR_DBGF_BP_OWNER_CALLBACK_WRONG_STATUS; 2629 } 2630 else 2631 return VBOXSTRICTRC_VAL(rcStrict); 2632 } 2633 } 2634 else if (rcStrict != VINF_DBGF_BP_HALT) /* Guru meditation. */ 2691 VBOXSTRICTRC rcStrict = dbgfR3BpHit(pVM, pVCpu, hBp, pBp, pBpOwner); 2692 if (VBOXSTRICTRC_VAL(rcStrict) == VINF_SUCCESS) 2693 return VINF_SUCCESS; 2694 else if (VBOXSTRICTRC_VAL(rcStrict) != VINF_DBGF_BP_HALT) /* Guru meditation. */ 2635 2695 return VERR_DBGF_BP_OWNER_CALLBACK_WRONG_STATUS; 2636 2696 /* else: Halt in the debugger. */ -
trunk/src/VBox/VMM/VMMR3/DBGFR3FlowTrace.cpp
r87787 r89924 1209 1209 if (RT_SUCCESS(rc)) 1210 1210 { 1211 rc = DBGFR3BpOwnerCreate(pUVM, dbgfR3FlowTraceModProbeFiredWorker, &pThis->hBpOwner);1211 rc = DBGFR3BpOwnerCreate(pUVM, dbgfR3FlowTraceModProbeFiredWorker, NULL /*pfnBpIoHit*/, &pThis->hBpOwner); 1212 1212 if (RT_SUCCESS(rc)) 1213 1213 { -
trunk/src/VBox/VMM/include/DBGFInline.h
r86728 r89924 109 109 } 110 110 111 #ifdef IN_RING3 112 /** 113 * Returns the internal breakpoint owner state for the given handle. 114 * 115 * @returns Pointer to the internal breakpoint owner state or NULL if the handle is invalid. 116 * @param pUVM The user mode VM handle. 117 * @param hBpOwner The breakpoint owner handle to resolve. 118 */ 119 DECLINLINE(PDBGFBPOWNERINT) dbgfR3BpOwnerGetByHnd(PUVM pUVM, DBGFBPOWNER hBpOwner) 120 { 121 AssertReturn(hBpOwner < DBGF_BP_OWNER_COUNT_MAX, NULL); 122 AssertPtrReturn(pUVM->dbgf.s.pbmBpOwnersAllocR3, NULL); 123 124 AssertReturn(ASMBitTest(pUVM->dbgf.s.pbmBpOwnersAllocR3, hBpOwner), NULL); 125 return &pUVM->dbgf.s.paBpOwnersR3[hBpOwner]; 126 } 127 #endif 128 111 129 #endif /* !VMM_INCLUDED_SRC_include_DBGFInline_h */ -
trunk/src/VBox/VMM/include/DBGFInternal.h
r89912 r89924 824 824 /** Callback to call when a breakpoint has hit, Ring-3 Ptr. */ 825 825 R3PTRTYPE(PFNDBGFBPHIT) pfnBpHitR3; 826 /** Callback to call when a I/O breakpoint has hit, Ring-3 Ptr. */ 827 R3PTRTYPE(PFNDBGFBPIOHIT) pfnBpIoHitR3; 828 /** Padding. */ 829 uint64_t u64Pad1; 826 830 } DBGFBPOWNERINT; 827 AssertCompileSize(DBGFBPOWNERINT, 16);831 AssertCompileSize(DBGFBPOWNERINT, 32); 828 832 /** Pointer to an internal breakpoint owner state, shared part. */ 829 833 typedef DBGFBPOWNERINT *PDBGFBPOWNERINT; … … 843 847 /** Callback to call when a breakpoint has hit, Ring-0 Ptr. */ 844 848 R0PTRTYPE(PFNDBGFBPHIT) pfnBpHitR0; 849 /** Callback to call when a I/O breakpoint has hit, Ring-0 Ptr. */ 850 R0PTRTYPE(PFNDBGFBPIOHIT) pfnBpIoHitR0; 851 /** Padding. */ 852 uint64_t u64Pad1; 845 853 } DBGFBPOWNERINTR0; 846 AssertCompileSize(DBGFBPOWNERINTR0, 16);854 AssertCompileSize(DBGFBPOWNERINTR0, 32); 847 855 /** Pointer to an internal breakpoint owner state, shared part. */ 848 856 typedef DBGFBPOWNERINTR0 *PDBGFBPOWNERINTR0; … … 1211 1219 * This is checked and cleared in the \#DB handler. */ 1212 1220 bool fSingleSteppingRaw; 1213 /** Alignment padding. */ 1214 bool afPadding[2]; 1221 /** Flag whether an I/O breakpoint is pending. */ 1222 bool fBpIoActive; 1223 /** Flagh whether the I/O breakpoint hit before the access or after. */ 1224 bool fBpIoBefore; 1215 1225 /** Current active breakpoint handle. 1216 1226 * This is NIL_DBGFBP if not active. It is set when a execution engine … … 1219 1229 * @todo drop this in favor of aEvents! */ 1220 1230 DBGFBP hBpActive; 1231 /** The access mask for a pending I/O breakpoint. */ 1232 uint32_t fBpIoAccess; 1233 /** The address of the access. */ 1234 uint64_t uBpIoAddress; 1235 /** The value of the access. */ 1236 uint64_t uBpIoValue; 1221 1237 1222 1238 /** The number of events on the stack (aEvents). … … 1391 1407 * can still do read accesses without holding it while traversing the trees). */ 1392 1408 RTSEMFASTMUTEX hMtxBpL2Wr; 1409 /** Number of armed port I/O breakpoints. */ 1410 volatile uint32_t cPortIoBps; 1393 1411 /** @} */ 1394 1412
注意:
瀏覽 TracChangeset
來幫助您使用更動檢視器