- Timestamp:
- Oct 25, 2020 6:20:09 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/err.h
r86699 r86701 341 341 /** Internal processing error \#5 in the DBGF breakpoint manager code. */ 342 342 #define VERR_DBGF_BP_IPE_5 (-1230) 343 /** Internal processing error \#6 in the DBGF breakpoint manager code. */ 344 #define VERR_DBGF_BP_IPE_6 (-1231) 345 /** Number of tries to add an int3 breakpoint table to the lookup tables reached. */ 346 #define VERR_DBGF_BP_INT3_ADD_TRIES_REACHED (-1232) 343 347 /** @} */ 344 348 -
trunk/include/VBox/vmm/dbgf.h
r86699 r86701 51 51 */ 52 52 VMMRZ_INT_DECL(int) DBGFRZTrap01Handler(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCUINTREG uDr6, bool fAltStepping); 53 VMMRZ_INT_DECL(int) DBGFRZTrap03Handler(PVM pVM, PVMCPUpVCpu, PCPUMCTXCORE pRegFrame);53 VMMRZ_INT_DECL(int) DBGFRZTrap03Handler(PVMCC pVM, PVMCPUCC pVCpu, PCPUMCTXCORE pRegFrame); 54 54 /** @} */ 55 55 #endif -
trunk/include/VBox/vmm/vm.h
r86118 r86701 1392 1392 /** The number of enabled hardware I/O breakpoints. */ 1393 1393 uint8_t cEnabledHwIoBreakpoints; 1394 #ifndef VBOX_WITH_LOTS_OF_DBGF_BPS 1394 1395 /** The number of enabled INT3 breakpoints. */ 1395 1396 uint8_t cEnabledInt3Breakpoints; 1396 1397 uint8_t abPadding[1]; /**< Unused padding space up for grabs. */ 1398 #else 1399 uint16_t u16Pad; /**< Unused padding space up for grabs. */ 1400 /** The number of enabled INT3 breakpoints. */ 1401 volatile uint32_t cEnabledInt3Breakpoints; 1402 #endif 1397 1403 } const ro; 1398 1404 #endif -
trunk/src/VBox/VMM/VMMR3/DBGFR3Bp.cpp
r86699 r86701 643 643 644 644 /** 645 * Adds the given int3 breakpoint to the appropriate lookup tables. 646 * 647 * @returns VBox status code. 648 * @param pUVM The user mode VM handle. 649 * @param hBp The breakpoint handle to add. 650 * @param pBp The internal breakpoint state. 651 */ 652 static int dbgfR3BpInt3Add(PUVM pUVM, DBGFBP hBp, PDBGFBPINT pBp) 653 { 654 AssertReturn(DBGF_BP_PUB_GET_TYPE(pBp->Pub.fFlagsAndType) == DBGFBPTYPE_INT3, VERR_DBGF_BP_IPE_3); 655 656 int rc = VINF_SUCCESS; 657 uint16_t idxL1 = DBGF_BP_INT3_L1_IDX_EXTRACT_FROM_ADDR(pBp->Pub.u.Int3.GCPtr); 658 uint8_t cTries = 16; 659 660 while (cTries--) 661 { 662 uint32_t u32Entry = ASMAtomicReadU32(&pUVM->dbgf.s.paBpLocL1R3[idxL1]); 663 664 if (u32Entry == DBGF_BP_INT3_L1_ENTRY_TYPE_NULL) 665 { 666 /* 667 * No breakpoint assigned so far for this entry, create an entry containing 668 * the direct breakpoint handle and try to exchange it atomically. 669 */ 670 u32Entry = DBGF_BP_INT3_L1_ENTRY_CREATE_BP_HND(hBp); 671 if (ASMAtomicCmpXchgU32(&pUVM->dbgf.s.paBpLocL1R3[idxL1], u32Entry, DBGF_BP_INT3_L1_ENTRY_TYPE_NULL)) 672 break; 673 } 674 else 675 { 676 uint8_t u8Type = DBGF_BP_INT3_L1_ENTRY_GET_TYPE(u32Entry); 677 if (u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_BP_HND) 678 { 679 /** @todo Allocate a new root entry and one leaf to accomodate for the two handles, 680 * then replace the new entry. */ 681 rc = VERR_NOT_IMPLEMENTED; 682 break; 683 } 684 else if (u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_L2_IDX) 685 { 686 /** @todo Walk the L2 tree searching for the correct spot, add the new entry 687 * and rebalance the tree. */ 688 rc = VERR_NOT_IMPLEMENTED; 689 break; 690 } 691 } 692 } 693 694 if ( RT_SUCCESS(rc) 695 && !cTries) /* Too much contention, abort with an error. */ 696 rc = VERR_DBGF_BP_INT3_ADD_TRIES_REACHED; 697 698 return rc; 699 } 700 701 702 /** 703 * Removes the given int3 breakpoint from all lookup tables. 704 * 705 * @returns VBox status code. 706 * @param pUVM The user mode VM handle. 707 * @param hBp The breakpoint handle to remove. 708 * @param pBp The internal breakpoint state. 709 */ 710 static int dbgfR3BpInt3Remove(PUVM pUVM, DBGFBP hBp, PDBGFBPINT pBp) 711 { 712 AssertReturn(DBGF_BP_PUB_GET_TYPE(pBp->Pub.fFlagsAndType) == DBGFBPTYPE_INT3, VERR_DBGF_BP_IPE_3); 713 714 int rc = VINF_SUCCESS; 715 uint16_t idxL1 = DBGF_BP_INT3_L1_IDX_EXTRACT_FROM_ADDR(pBp->Pub.u.Int3.GCPtr); 716 717 for (;;) 718 { 719 uint32_t u32Entry = ASMAtomicReadU32(&pUVM->dbgf.s.paBpLocL1R3[idxL1]); 720 AssertReturn(u32Entry != DBGF_BP_INT3_L1_ENTRY_TYPE_NULL, VERR_DBGF_BP_IPE_6); 721 722 uint8_t u8Type = DBGF_BP_INT3_L1_ENTRY_GET_TYPE(u32Entry); 723 if (u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_BP_HND) 724 { 725 /* Single breakpoint, just exchange atomically with the null value. */ 726 if (ASMAtomicCmpXchgU32(&pUVM->dbgf.s.paBpLocL1R3[idxL1], DBGF_BP_INT3_L1_ENTRY_TYPE_NULL, u32Entry)) 727 break; 728 break; 729 } 730 else if (u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_L2_IDX) 731 { 732 /** @todo Walk the L2 tree searching for the correct spot, remove the entry 733 * and rebalance the tree. */ 734 RT_NOREF(hBp); 735 rc = VERR_NOT_IMPLEMENTED; 736 break; 737 } 738 } 739 740 return rc; 741 } 742 743 744 /** 645 745 * @callback_method_impl{FNVMMEMTRENDEZVOUS} 646 746 */ … … 678 778 * @param hBp The breakpoint handle to arm. 679 779 * @param pBp The internal breakpoint state pointer for the handle. 780 * 781 * @thread Any thread. 680 782 */ 681 783 static int dbgfR3BpArm(PUVM pUVM, DBGFBP hBp, PDBGFBPINT pBp) … … 704 806 } 705 807 case DBGFBPTYPE_INT3: 808 { 809 dbgfR3BpSetEnabled(pBp, true /*fEnabled*/); 810 811 /** @todo When we enable the first int3 breakpoint we should do this in an EMT rendezvous 812 * as the VMX code intercepts #BP only when at least one int3 breakpoint is enabled. 813 * A racing vCPU might trigger it and forward it to the guest causing panics/crashes/havoc. */ 814 /* 815 * Save current byte and write the int3 instruction byte. 816 */ 817 rc = PGMPhysSimpleReadGCPhys(pVM, &pBp->Pub.u.Int3.bOrg, pBp->Pub.u.Int3.PhysAddr, sizeof(pBp->Pub.u.Int3.bOrg)); 818 if (RT_SUCCESS(rc)) 819 { 820 static const uint8_t s_bInt3 = 0xcc; 821 rc = PGMPhysSimpleWriteGCPhys(pVM, pBp->Pub.u.Int3.PhysAddr, &s_bInt3, sizeof(s_bInt3)); 822 if (RT_SUCCESS(rc)) 823 { 824 ASMAtomicIncU32(&pVM->dbgf.s.cEnabledInt3Breakpoints); 825 Log(("DBGF: Set breakpoint at %RGv (Phys %RGp)\n", pBp->Pub.u.Int3.GCPtr, pBp->Pub.u.Int3.PhysAddr)); 826 } 827 } 828 829 if (RT_FAILURE(rc)) 830 dbgfR3BpSetEnabled(pBp, false /*fEnabled*/); 831 832 break; 833 } 706 834 case DBGFBPTYPE_PORT_IO: 707 835 case DBGFBPTYPE_MMIO: … … 724 852 * @param hBp The breakpoint handle to disarm. 725 853 * @param pBp The internal breakpoint state pointer for the handle. 854 * 855 * @thread Any thread. 726 856 */ 727 857 static int dbgfR3BpDisarm(PUVM pUVM, DBGFBP hBp, PDBGFBPINT pBp) … … 750 880 } 751 881 case DBGFBPTYPE_INT3: 882 { 883 dbgfR3BpSetEnabled(pBp, false /*fEnabled*/); 884 885 /* 886 * Check that the current byte is the int3 instruction, and restore the original one. 887 * We currently ignore invalid bytes. 888 */ 889 uint8_t bCurrent = 0; 890 rc = PGMPhysSimpleReadGCPhys(pVM, &bCurrent, pBp->Pub.u.Int3.PhysAddr, sizeof(bCurrent)); 891 if ( RT_SUCCESS(rc) 892 && bCurrent == 0xcc) 893 { 894 rc = PGMPhysSimpleWriteGCPhys(pVM, pBp->Pub.u.Int3.PhysAddr, &pBp->Pub.u.Int3.bOrg, sizeof(pBp->Pub.u.Int3.bOrg)); 895 if (RT_SUCCESS(rc)) 896 { 897 ASMAtomicDecU32(&pVM->dbgf.s.cEnabledInt3Breakpoints); 898 Log(("DBGF: Removed breakpoint at %RGv (Phys %RGp)\n", pBp->Pub.u.Int3.GCPtr, pBp->Pub.u.Int3.PhysAddr)); 899 } 900 } 901 902 if (RT_FAILURE(rc)) 903 dbgfR3BpSetEnabled(pBp, true /*fEnabled*/); 904 905 break; 906 } 752 907 case DBGFBPTYPE_PORT_IO: 753 908 case DBGFBPTYPE_MMIO: … … 877 1032 pBp->Pub.u.Int3.GCPtr = pAddress->FlatPtr; 878 1033 879 /* Enable the breakpoint. */880 rc = dbgfR3Bp Arm(pUVM, hBp, pBp);1034 /* Add the breakpoint to the lookup tables. */ 1035 rc = dbgfR3BpInt3Add(pUVM, hBp, pBp); 881 1036 if (RT_SUCCESS(rc)) 882 1037 { 883 *phBp = hBp; 884 return VINF_SUCCESS; 1038 /* Enable the breakpoint. */ 1039 rc = dbgfR3BpArm(pUVM, hBp, pBp); 1040 if (RT_SUCCESS(rc)) 1041 { 1042 *phBp = hBp; 1043 return VINF_SUCCESS; 1044 } 1045 1046 int rc2 = dbgfR3BpInt3Remove(pUVM, hBp, pBp); AssertRC(rc2); 885 1047 } 886 1048 } -
trunk/src/VBox/VMM/VMMRZ/DBGFRZ.cpp
r86666 r86701 190 190 } 191 191 192 #ifdef VBOX_WITH_LOTS_OF_DBGF_BPS 193 # ifdef IN_RING0 194 /** 195 * Returns the internal breakpoint state for the given handle. 196 * 197 * @returns Pointer to the internal breakpoint state or NULL if the handle is invalid. 198 * @param pVM The ring-0 VM structure pointer. 199 * @param hBp The breakpoint handle to resolve. 200 * @param ppBpR0 Where to store the pointer to the ring-0 only part of the breakpoint 201 * on success, optional. 202 */ 203 DECLINLINE(PDBGFBPINT) dbgfR0BpGetByHnd(PVMCC pVM, DBGFBP hBp, PDBGFBPINTR0 *ppBpR0) 204 { 205 uint32_t idChunk = DBGF_BP_HND_GET_CHUNK_ID(hBp); 206 uint32_t idxEntry = DBGF_BP_HND_GET_ENTRY(hBp); 207 208 AssertReturn(idChunk < DBGF_BP_CHUNK_COUNT, NULL); 209 AssertReturn(idxEntry < DBGF_BP_COUNT_PER_CHUNK, NULL); 210 211 PDBGFBPCHUNKR0 pBpChunk = &pVM->dbgfr0.s.aBpChunks[idChunk]; 212 AssertPtrReturn(pBpChunk->paBpBaseSharedR0, NULL); 213 214 if (ppBpR0) 215 *ppBpR0 = &pBpChunk->paBpBaseR0Only[idxEntry]; 216 return &pBpChunk->paBpBaseSharedR0[idxEntry]; 217 } 218 # endif 219 220 221 /** 222 * Executes the actions associated with the given breakpoint. 223 * 224 * @returns VBox status code. 225 * @param pVM The cross context VM structure. 226 * @param pVCpu The cross context virtual CPU structure. 227 * @param pRegFrame Pointer to the register frame for the trap. 228 * @param hBp The breakpoint handle which hit. 229 * @param pBp The shared breakpoint state. 230 * @param pBpR0 The ring-0 only breakpoint state. 231 * @param fInHyper Flag whether the breakpoint triggered in hypervisor code. 232 */ 233 DECLINLINE(int) dbgfRZBpHit(PVMCC pVM, PVMCPUCC pVCpu, PCPUMCTXCORE pRegFrame, 234 DBGFBP hBp, PDBGFBPINT pBp, PDBGFBPINTR0 pBpR0, bool fInHyper) 235 { 236 uint64_t cHits = ASMAtomicIncU64(&pBp->Pub.cHits); 237 pVCpu->dbgf.s.hBpActive = hBp; 238 239 /** @todo Owner handling. */ 240 241 LogFlow(("dbgfRZBpHit: hit breakpoint %u at %04x:%RGv cHits=0x%RX64\n", 242 hBp, pRegFrame->cs.Sel, pRegFrame->rip, cHits)); 243 return fInHyper 244 ? VINF_EM_DBG_HYPER_BREAKPOINT 245 : VINF_EM_DBG_BREAKPOINT; 246 } 247 #endif /* !VBOX_WITH_LOTS_OF_DBGF_BPS */ 192 248 193 249 /** … … 202 258 * @param pRegFrame Pointer to the register frame for the trap. 203 259 */ 204 VMMRZ_INT_DECL(int) DBGFRZTrap03Handler(PVM pVM, PVMCPUpVCpu, PCPUMCTXCORE pRegFrame)260 VMMRZ_INT_DECL(int) DBGFRZTrap03Handler(PVMCC pVM, PVMCPUCC pVCpu, PCPUMCTXCORE pRegFrame) 205 261 { 206 262 #ifdef IN_RC … … 247 303 } 248 304 } 305 #else 306 # ifdef IN_RC 307 # error "You lucky person have the pleasure to implement the raw mode part for this!" 308 # endif 309 310 if (pVM->dbgfr0.s.CTX_SUFF(paBpLocL1)) 311 { 312 RTGCPTR GCPtrBp; 313 int rc = SELMValidateAndConvertCSAddr(pVCpu, pRegFrame->eflags, pRegFrame->ss.Sel, pRegFrame->cs.Sel, &pRegFrame->cs, 314 # ifdef IN_RC 315 pRegFrame->eip - 1, 316 # else 317 pRegFrame->rip /* no -1 in R0 */, 318 # endif 319 &GCPtrBp); 320 AssertRCReturn(rc, rc); 321 322 const uint16_t idxL1 = DBGF_BP_INT3_L1_IDX_EXTRACT_FROM_ADDR(GCPtrBp); 323 const uint32_t u32L1Entry = ASMAtomicReadU32(&pVM->dbgfr0.s.CTX_SUFF(paBpLocL1)[idxL1]); 324 325 LogFlowFunc(("GCPtrBp=%RGv idxL1=%u u32L1Entry=%#x\n", GCPtrBp, idxL1, u32L1Entry)); 326 if (u32L1Entry != DBGF_BP_INT3_L1_ENTRY_TYPE_NULL) 327 { 328 uint8_t u8Type = DBGF_BP_INT3_L1_ENTRY_GET_TYPE(u32L1Entry); 329 if (u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_BP_HND) 330 { 331 DBGFBP hBp = DBGF_BP_INT3_L1_ENTRY_GET_BP_HND(u32L1Entry); 332 333 /* Query the internal breakpoint state from the handle. */ 334 PDBGFBPINTR0 pBpR0 = NULL; 335 PDBGFBPINT pBp = dbgfR0BpGetByHnd(pVM, hBp, &pBpR0); 336 if ( pBp 337 && DBGF_BP_PUB_GET_TYPE(pBp->Pub.fFlagsAndType) == DBGFBPTYPE_INT3) 338 { 339 if (pBp->Pub.u.Int3.GCPtr == (RTGCUINTPTR)GCPtrBp) 340 return dbgfRZBpHit(pVM, pVCpu, pRegFrame, hBp, pBp, pBpR0, fInHyper); 341 /* else Genuine guest trap. */ 342 } 343 /** @todo else Guru meditation */ 344 } 345 else if (u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_L2_IDX) 346 { 347 /** @todo Walk the L2 tree searching for the correct spot. */ 348 } 349 /** @todo else Guru meditation */ 350 } 351 } 249 352 #endif /* !VBOX_WITH_LOTS_OF_DBGF_BPS */ 250 353 -
trunk/src/VBox/VMM/include/DBGFInternal.h
r86699 r86701 788 788 789 789 790 /** @name DBGF int3 L1 lookup table entry types. 791 * @{ */ 792 /** No breakpoint handle assigned for this entry - special value which can be used 793 * for comparison with the whole entry. */ 794 #define DBGF_BP_INT3_L1_ENTRY_TYPE_NULL UINT32_C(0) 795 /** Direct breakpoint handle. */ 796 #define DBGF_BP_INT3_L1_ENTRY_TYPE_BP_HND 1 797 /** Index into the L2 tree denoting the root of a search tree. */ 798 #define DBGF_BP_INT3_L1_ENTRY_TYPE_L2_IDX 2 799 /** @} */ 800 801 802 /** Returns the entry type for the given L1 lookup table entry. */ 803 #define DBGF_BP_INT3_L1_ENTRY_GET_TYPE(a_u32Entry) ((a_u32Entry) >> 28) 804 /** Returns a DBGF breakpoint handle from the given L1 lookup table entry, 805 * type needs to be DBGF_BP_INT3_L1_ENTRY_TYPE_BP_HND. */ 806 #define DBGF_BP_INT3_L1_ENTRY_GET_BP_HND(a_u32Entry) ((DBGFBP)((a_u32Entry) & UINT32_C(0x0fffffff))) 807 /** Returns a L2 index from the given L1 lookup table entry, 808 * type needs to be DBGF_BP_INT3_L1_ENTRY_TYPE_L2_IDX. */ 809 #define DBGF_BP_INT3_L1_ENTRY_GET_L2_IDX(a_u32Entry) ((a_u32Entry) & UINT32_C(0x0fffffff)) 810 /** Creates a L1 entry value from the given type and data. */ 811 #define DBGF_BP_INT3_L1_ENTRY_CREATE(a_Type, a_u32Data) ((((uint32_t)(a_Type)) << 28) | ((a_u32Data) & UINT32_C(0x0fffffff))) 812 /** Creates a breakpoint handle type L1 lookup entry. */ 813 #define DBGF_BP_INT3_L1_ENTRY_CREATE_BP_HND(a_hBp) DBGF_BP_INT3_L1_ENTRY_CREATE(DBGF_BP_INT3_L1_ENTRY_TYPE_BP_HND, a_hBp) 814 /** Creates a L2 index type L1 lookup entry. */ 815 #define DBGF_BP_INT3_L1_ENTRY_CREATE_L2_IDX(a_idxL2) DBGF_BP_INT3_L1_ENTRY_CREATE(DBGF_BP_INT3_L1_ENTRY_TYPE_L2_IDX, a_idxL2) 816 817 /** Extracts the lowest bits from the given GC pointer used as an index into the L1 lookup table. */ 818 #define DBGF_BP_INT3_L1_IDX_EXTRACT_FROM_ADDR(a_GCPtr) ((uint16_t)((a_GCPtr) & UINT16_C(0xffff))) 819 790 820 /** 791 821 * The internal breakpoint state, shared part. … … 920 950 uint8_t cEnabledInt3Breakpoints; 921 951 uint8_t abPadding; /**< Unused padding space up for grabs. */ 952 uint32_t uPadding; 922 953 #else 923 uint16_t u16Pad; 954 uint16_t u16Pad; /**< Unused padding space up for grabs. */ 955 /** The number of enabled INT3 breakpoints. */ 956 volatile uint32_t cEnabledInt3Breakpoints; 924 957 #endif 925 uint32_t uPadding;926 958 927 959 /** Debugger Attached flag.
Note:
See TracChangeset
for help on using the changeset viewer.