Changeset 86701 in vbox for trunk/src/VBox/VMM/VMMR3
- Timestamp:
- Oct 25, 2020 6:20:09 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 141085
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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 }
Note:
See TracChangeset
for help on using the changeset viewer.