Changeset 86726 in vbox
- Timestamp:
- Oct 28, 2020 10:10:29 AM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 141114
- Location:
- trunk
- Files:
-
- 1 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/err.h
r86701 r86726 331 331 /** The breakpoint owner handle is still used by one or more breakpoints. */ 332 332 #define VERR_DBGF_OWNER_BUSY (-1225) 333 /** Number of tries to add an int3 breakpoint table to the lookup tables reached. */ 334 #define VERR_DBGF_BP_INT3_ADD_TRIES_REACHED (-1226) 333 335 /** Internal processing error \#1 in the DBGF breakpoint manager code. */ 334 #define VERR_DBGF_BP_IPE_1 (-122 6)336 #define VERR_DBGF_BP_IPE_1 (-1227) 335 337 /** Internal processing error \#2 in the DBGF breakpoint manager code. */ 336 #define VERR_DBGF_BP_IPE_2 (-122 7)338 #define VERR_DBGF_BP_IPE_2 (-1228) 337 339 /** Internal processing error \#3 in the DBGF breakpoint manager code. */ 338 #define VERR_DBGF_BP_IPE_3 (-122 8)340 #define VERR_DBGF_BP_IPE_3 (-1229) 339 341 /** Internal processing error \#4 in the DBGF breakpoint manager code. */ 340 #define VERR_DBGF_BP_IPE_4 (-12 29)342 #define VERR_DBGF_BP_IPE_4 (-1230) 341 343 /** Internal processing error \#5 in the DBGF breakpoint manager code. */ 342 #define VERR_DBGF_BP_IPE_5 (-123 0)344 #define VERR_DBGF_BP_IPE_5 (-1231) 343 345 /** 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) 346 #define VERR_DBGF_BP_IPE_6 (-1232) 347 /** Internal processing error \#7 in the DBGF breakpoint manager code. */ 348 #define VERR_DBGF_BP_IPE_7 (-1233) 349 /** Internal processing error \#8 in the DBGF breakpoint manager code. */ 350 #define VERR_DBGF_BP_IPE_8 (-1234) 351 /** Internal processing error \#9 in the DBGF breakpoint manager code. */ 352 #define VERR_DBGF_BP_IPE_9 (-1235) 353 /** Level 2 lookup failed because the L1 lookup table is corrupted. */ 354 #define VERR_DBGF_BP_L1_LOOKUP_FAILED (-1236) 355 /** Level 2 lookup failed because the L2 lookup table is corrupted. */ 356 #define VERR_DBGF_BP_L2_LOOKUP_FAILED (-1237) 347 357 /** @} */ 348 358 -
trunk/src/VBox/VMM/VMMR3/DBGFR3Bp.cpp
r86704 r86726 157 157 #include <iprt/mem.h> 158 158 159 #include "DBGFInline.h" 160 159 161 160 162 /********************************************************************************************************************************* … … 855 857 856 858 /** 859 * Returns the pointer to the L2 table entry from the given index. 860 * 861 * @returns Current context pointer to the L2 table entry or NULL if the provided index value is invalid. 862 * @param pUVM The user mode VM handle. 863 * @param idxL2 The L2 table index to resolve. 864 * 865 * @note The content of the resolved L2 table entry is not validated!. 866 */ 867 DECLINLINE(PDBGFBPL2ENTRY) dbgfR3BpL2GetByIdx(PUVM pUVM, uint32_t idxL2) 868 { 869 uint32_t idChunk = DBGF_BP_L2_IDX_GET_CHUNK_ID(idxL2); 870 uint32_t idxEntry = DBGF_BP_L2_IDX_GET_ENTRY(idxL2); 871 872 AssertReturn(idChunk < DBGF_BP_L2_TBL_CHUNK_COUNT, NULL); 873 AssertReturn(idxEntry < DBGF_BP_L2_TBL_ENTRIES_PER_CHUNK, NULL); 874 875 PDBGFBPL2TBLCHUNKR3 pL2Chunk = &pUVM->dbgf.s.aBpL2TblChunks[idChunk]; 876 AssertPtrReturn(pL2Chunk->pbmAlloc, NULL); 877 AssertReturn(ASMBitTest(pL2Chunk->pbmAlloc, idxEntry), NULL); 878 879 return &pL2Chunk->CTX_SUFF(pL2Base)[idxEntry]; 880 } 881 882 883 /** 884 * Creates a binary search tree with the given root and leaf nodes. 885 * 886 * @returns VBox status code. 887 * @param pUVM The user mode VM handle. 888 * @param idxL1 The index into the L1 table where the created tree should be linked into. 889 * @param u32EntryOld The old entry in the L1 table used to compare with in the atomic update. 890 * @param hBpRoot The root node DBGF handle to assign. 891 * @param GCPtrRoot The root nodes GC pointer to use as a key. 892 * @param hBpLeaf The leafs node DBGF handle to assign. 893 * @param GCPtrLeaf The leafs node GC pointer to use as a key. 894 */ 895 static int dbgfR3BpInt3L2BstCreate(PUVM pUVM, uint32_t idxL1, uint32_t u32EntryOld, 896 DBGFBP hBpRoot, RTGCUINTPTR GCPtrRoot, 897 DBGFBP hBpLeaf, RTGCUINTPTR GCPtrLeaf) 898 { 899 AssertReturn(GCPtrRoot != GCPtrLeaf, VERR_DBGF_BP_IPE_9); 900 Assert(DBGF_BP_INT3_L1_IDX_EXTRACT_FROM_ADDR(GCPtrRoot) == DBGF_BP_INT3_L1_IDX_EXTRACT_FROM_ADDR(GCPtrLeaf)); 901 902 /* Allocate two nodes. */ 903 uint32_t idxL2Root = 0; 904 PDBGFBPL2ENTRY pL2Root = NULL; 905 int rc = dbgfR3BpL2TblEntryAlloc(pUVM, &idxL2Root, &pL2Root); 906 if (RT_SUCCESS(rc)) 907 { 908 uint32_t idxL2Leaf = 0; 909 PDBGFBPL2ENTRY pL2Leaf = NULL; 910 rc = dbgfR3BpL2TblEntryAlloc(pUVM, &idxL2Leaf, &pL2Leaf); 911 if (RT_SUCCESS(rc)) 912 { 913 dbgfBpL2TblEntryInit(pL2Leaf, hBpLeaf, GCPtrLeaf, DBGF_BP_L2_ENTRY_IDX_END, DBGF_BP_L2_ENTRY_IDX_END, 0 /*iDepth*/); 914 if (GCPtrLeaf < GCPtrRoot) 915 dbgfBpL2TblEntryInit(pL2Root, hBpRoot, GCPtrRoot, idxL2Leaf, DBGF_BP_L2_ENTRY_IDX_END, 0 /*iDepth*/); 916 else 917 dbgfBpL2TblEntryInit(pL2Root, hBpRoot, GCPtrRoot, DBGF_BP_L2_ENTRY_IDX_END, idxL2Leaf, 0 /*iDepth*/); 918 919 uint32_t const u32Entry = DBGF_BP_INT3_L1_ENTRY_CREATE_L2_IDX(idxL2Root); 920 if (ASMAtomicCmpXchgU32(&pUVM->dbgf.s.paBpLocL1R3[idxL1], u32Entry, u32EntryOld)) 921 return VINF_SUCCESS; 922 923 /* The L1 entry has changed due to another thread racing us during insertion, free nodes and try again. */ 924 rc = VINF_TRY_AGAIN; 925 dbgfR3BpL2TblEntryFree(pUVM, idxL2Leaf, pL2Leaf); 926 } 927 928 dbgfR3BpL2TblEntryFree(pUVM, idxL2Root, pL2Root); 929 } 930 931 return rc; 932 } 933 934 935 /** 936 * Inserts the given breakpoint handle into an existing binary search tree. 937 * 938 * @returns VBox status code. 939 * @param pUVM The user mode VM handle. 940 * @param idxL2Root The index of the tree root in the L2 table. 941 * @param hBpRoot The node DBGF handle to insert. 942 * @param GCPtrRoot The nodes GC pointer to use as a key. 943 */ 944 static int dbgfR3BpInt2L2BstNodeInsert(PUVM pUVM, uint32_t idxL2Root, DBGFBP hBp, RTGCUINTPTR GCPtr) 945 { 946 /* Allocate a new node first. */ 947 uint32_t idxL2Nd = 0; 948 PDBGFBPL2ENTRY pL2Nd = NULL; 949 int rc = dbgfR3BpL2TblEntryAlloc(pUVM, &idxL2Nd, &pL2Nd); 950 if (RT_SUCCESS(rc)) 951 { 952 /* Walk the tree and find the correct node to insert to. */ 953 PDBGFBPL2ENTRY pL2Entry = dbgfR3BpL2GetByIdx(pUVM, idxL2Root); 954 while (RT_LIKELY(pL2Entry)) 955 { 956 /* Make a copy of the entry. */ 957 DBGFBPL2ENTRY L2Entry; 958 L2Entry.u64GCPtrKeyAndBpHnd1 = ASMAtomicReadU64((volatile uint64_t *)&pL2Entry->u64GCPtrKeyAndBpHnd1); 959 L2Entry.u64LeftRightIdxDepthBpHnd2 = ASMAtomicReadU64((volatile uint64_t *)&pL2Entry->u64LeftRightIdxDepthBpHnd2); 960 961 RTGCUINTPTR GCPtrL2Entry = DBGF_BP_L2_ENTRY_GET_GCPTR(L2Entry.u64GCPtrKeyAndBpHnd1); 962 AssertBreak(GCPtr != GCPtrL2Entry); 963 964 /* Not found, get to the next level. */ 965 uint32_t idxL2Next = (GCPtr < GCPtrL2Entry) 966 ? DBGF_BP_L2_ENTRY_GET_IDX_LEFT(L2Entry.u64LeftRightIdxDepthBpHnd2) 967 : DBGF_BP_L2_ENTRY_GET_IDX_RIGHT(L2Entry.u64LeftRightIdxDepthBpHnd2); 968 if (idxL2Next == DBGF_BP_L2_ENTRY_IDX_END) 969 { 970 /* Insert the new node here. */ 971 dbgfBpL2TblEntryInit(pL2Nd, hBp, GCPtr, DBGF_BP_L2_ENTRY_IDX_END, DBGF_BP_L2_ENTRY_IDX_END, 0 /*iDepth*/); 972 if (GCPtr < GCPtrL2Entry) 973 dbgfBpL2TblEntryUpdateLeft(pL2Entry, idxL2Next, 0 /*iDepth*/); 974 else 975 dbgfBpL2TblEntryUpdateRight(pL2Entry, idxL2Next, 0 /*iDepth*/); 976 return VINF_SUCCESS; 977 } 978 979 pL2Entry = dbgfR3BpL2GetByIdx(pUVM, idxL2Next); 980 } 981 982 rc = VERR_DBGF_BP_L2_LOOKUP_FAILED; 983 dbgfR3BpL2TblEntryFree(pUVM, idxL2Nd, pL2Nd); 984 } 985 986 return rc; 987 } 988 989 990 /** 991 * Adds the given breakpoint handle keyed with the GC pointer to the proper L2 binary search tree 992 * possibly creating a new tree. 993 * 994 * @returns VBox status code. 995 * @param pUVM The user mode VM handle. 996 * @param idxL1 The index into the L1 table the breakpoint uses. 997 * @param hBp The breakpoint handle which is to be added. 998 * @param GCPtr The GC pointer the breakpoint is keyed with. 999 */ 1000 static int dbgfR3BpInt3L2BstNodeAdd(PUVM pUVM, uint32_t idxL1, DBGFBP hBp, RTGCUINTPTR GCPtr) 1001 { 1002 int rc = RTSemFastMutexRequest(pUVM->dbgf.s.hMtxBpL2Wr); AssertRC(rc); 1003 1004 uint32_t u32Entry = ASMAtomicReadU32(&pUVM->dbgf.s.paBpLocL1R3[idxL1]); /* Re-read, could get raced by a remove operation. */ 1005 uint8_t u8Type = DBGF_BP_INT3_L1_ENTRY_GET_TYPE(u32Entry); 1006 if (u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_BP_HND) 1007 { 1008 /* Create a new search tree, gather the necessary information first. */ 1009 DBGFBP hBp2 = DBGF_BP_INT3_L1_ENTRY_GET_BP_HND(u32Entry); 1010 PDBGFBPINT pBp2 = dbgfR3BpGetByHnd(pUVM, hBp2); 1011 AssertStmt(VALID_PTR(pBp2), rc = VERR_DBGF_BP_IPE_7); 1012 if (RT_SUCCESS(rc)) 1013 rc = dbgfR3BpInt3L2BstCreate(pUVM, idxL1, u32Entry, hBp, GCPtr, hBp2, pBp2->Pub.u.Int3.GCPtr); 1014 } 1015 else if (u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_L2_IDX) 1016 rc = dbgfR3BpInt2L2BstNodeInsert(pUVM, DBGF_BP_INT3_L1_ENTRY_GET_L2_IDX(u32Entry), hBp, GCPtr); 1017 1018 int rc2 = RTSemFastMutexRelease(pUVM->dbgf.s.hMtxBpL2Wr); AssertRC(rc2); 1019 return rc; 1020 } 1021 1022 1023 /** 1024 * Removes the given breakpoint handle keyed with the GC pointer from the L2 binary search tree 1025 * pointed to by the given L2 root index. 1026 * 1027 * @returns VBox status code. 1028 * @param pUVM The user mode VM handle. 1029 * @param idxL1 The index into the L1 table pointing to the binary search tree. 1030 * @param idxL2Root The L2 table index where the tree root is located. 1031 * @param hBp The breakpoint handle which is to be removed. 1032 * @param GCPtr The GC pointer the breakpoint is keyed with. 1033 */ 1034 static int dbgfR3BpInt2L2BstNodeRemove(PUVM pUVM, uint32_t idxL1, uint32_t idxL2Root, DBGFBP hBp, RTGCUINTPTR GCPtr) 1035 { 1036 int rc = RTSemFastMutexRequest(pUVM->dbgf.s.hMtxBpL2Wr); AssertRC(rc); 1037 1038 RT_NOREF(idxL1, idxL2Root, hBp, GCPtr); 1039 1040 int rc2 = RTSemFastMutexRelease(pUVM->dbgf.s.hMtxBpL2Wr); AssertRC(rc2); 1041 1042 return rc; 1043 } 1044 1045 1046 /** 857 1047 * Adds the given int3 breakpoint to the appropriate lookup tables. 858 1048 * … … 886 1076 else 887 1077 { 888 uint8_t u8Type = DBGF_BP_INT3_L1_ENTRY_GET_TYPE(u32Entry); 889 if (u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_BP_HND) 890 { 891 /** @todo Allocate a new root entry and one leaf to accomodate for the two handles, 892 * then replace the new entry. */ 893 rc = VERR_NOT_IMPLEMENTED; 894 break; 895 } 896 else if (u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_L2_IDX) 897 { 898 /** @todo Walk the L2 tree searching for the correct spot, add the new entry 899 * and rebalance the tree. */ 900 rc = VERR_NOT_IMPLEMENTED; 901 break; 902 } 1078 rc = dbgfR3BpInt3L2BstNodeAdd(pUVM, idxL1, hBp, pBp->Pub.u.Int3.GCPtr); 1079 if (rc == VINF_TRY_AGAIN) 1080 continue; 1081 1082 break; 903 1083 } 904 1084 } … … 913 1093 914 1094 /** 1095 * @callback_method_impl{FNVMMEMTRENDEZVOUS} 1096 */ 1097 static DECLCALLBACK(VBOXSTRICTRC) dbgfR3BpInt3RemoveEmtWorker(PVM pVM, PVMCPU pVCpu, void *pvUser) 1098 { 1099 DBGFBP hBp = (DBGFBP)(uintptr_t)pvUser; 1100 1101 VMCPU_ASSERT_EMT(pVCpu); 1102 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 1103 1104 PUVM pUVM = pVM->pUVM; 1105 PDBGFBPINT pBp = dbgfR3BpGetByHnd(pUVM, hBp); 1106 AssertPtrReturn(pBp, VERR_DBGF_BP_IPE_8); 1107 1108 int rc = VINF_SUCCESS; 1109 if (pVCpu->idCpu == 0) 1110 { 1111 uint16_t idxL1 = DBGF_BP_INT3_L1_IDX_EXTRACT_FROM_ADDR(pBp->Pub.u.Int3.GCPtr); 1112 uint32_t u32Entry = ASMAtomicReadU32(&pUVM->dbgf.s.paBpLocL1R3[idxL1]); 1113 AssertReturn(u32Entry != DBGF_BP_INT3_L1_ENTRY_TYPE_NULL, VERR_DBGF_BP_IPE_6); 1114 1115 uint8_t u8Type = DBGF_BP_INT3_L1_ENTRY_GET_TYPE(u32Entry); 1116 if (u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_BP_HND) 1117 { 1118 /* Single breakpoint, just exchange atomically with the null value. */ 1119 if (!ASMAtomicCmpXchgU32(&pUVM->dbgf.s.paBpLocL1R3[idxL1], DBGF_BP_INT3_L1_ENTRY_TYPE_NULL, u32Entry)) 1120 { 1121 /* 1122 * A breakpoint addition must have raced us converting the L1 entry to an L2 index type, re-read 1123 * and remove the node from the created binary search tree. 1124 * 1125 * This works because after the entry was converted to an L2 index it can only be converted back 1126 * to a direct handle by removing one or more nodes which always goes through the fast mutex 1127 * protecting the L2 table. Likewise adding a new breakpoint requires grabbing the mutex as well 1128 * so there is serialization here and the node can be removed safely without having to worry about 1129 * concurrent tree modifications. 1130 */ 1131 u32Entry = ASMAtomicReadU32(&pUVM->dbgf.s.paBpLocL1R3[idxL1]); 1132 AssertReturn(DBGF_BP_INT3_L1_ENTRY_GET_TYPE(u32Entry) == DBGF_BP_INT3_L1_ENTRY_TYPE_L2_IDX, VERR_DBGF_BP_IPE_9); 1133 1134 rc = dbgfR3BpInt2L2BstNodeRemove(pUVM, idxL1, DBGF_BP_INT3_L1_ENTRY_GET_L2_IDX(u32Entry), 1135 hBp, pBp->Pub.u.Int3.GCPtr); 1136 } 1137 } 1138 else if (u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_L2_IDX) 1139 rc = dbgfR3BpInt2L2BstNodeRemove(pUVM, idxL1, DBGF_BP_INT3_L1_ENTRY_GET_L2_IDX(u32Entry), 1140 hBp, pBp->Pub.u.Int3.GCPtr); 1141 } 1142 1143 return rc; 1144 } 1145 1146 1147 /** 915 1148 * Removes the given int3 breakpoint from all lookup tables. 916 1149 * … … 924 1157 AssertReturn(DBGF_BP_PUB_GET_TYPE(pBp->Pub.fFlagsAndType) == DBGFBPTYPE_INT3, VERR_DBGF_BP_IPE_3); 925 1158 926 int rc = VINF_SUCCESS; 927 uint16_t idxL1 = DBGF_BP_INT3_L1_IDX_EXTRACT_FROM_ADDR(pBp->Pub.u.Int3.GCPtr); 928 929 for (;;) 930 { 931 uint32_t u32Entry = ASMAtomicReadU32(&pUVM->dbgf.s.paBpLocL1R3[idxL1]); 932 AssertReturn(u32Entry != DBGF_BP_INT3_L1_ENTRY_TYPE_NULL, VERR_DBGF_BP_IPE_6); 933 934 uint8_t u8Type = DBGF_BP_INT3_L1_ENTRY_GET_TYPE(u32Entry); 935 if (u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_BP_HND) 936 { 937 /* Single breakpoint, just exchange atomically with the null value. */ 938 if (ASMAtomicCmpXchgU32(&pUVM->dbgf.s.paBpLocL1R3[idxL1], DBGF_BP_INT3_L1_ENTRY_TYPE_NULL, u32Entry)) 939 break; 940 break; 941 } 942 else if (u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_L2_IDX) 943 { 944 /** @todo Walk the L2 tree searching for the correct spot, remove the entry 945 * and rebalance the tree. */ 946 RT_NOREF(hBp); 947 rc = VERR_NOT_IMPLEMENTED; 948 break; 949 } 950 } 951 952 return rc; 1159 /* 1160 * This has to be done by an EMT rendezvous in order to not have an EMT traversing 1161 * any L2 trees while it is being removed. 1162 */ 1163 return VMMR3EmtRendezvous(pUVM->pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3BpInt3RemoveEmtWorker, (void *)(uintptr_t)hBp); 953 1164 } 954 1165 -
trunk/src/VBox/VMM/VMMRZ/DBGFRZ.cpp
r86704 r86726 246 246 : VINF_EM_DBG_BREAKPOINT; 247 247 } 248 249 250 /** 251 * Returns the pointer to the L2 table entry from the given index. 252 * 253 * @returns Current context pointer to the L2 table entry or NULL if the provided index value is invalid. 254 * @param pVM The cross context VM structure. 255 * @param idxL2 The L2 table index to resolve. 256 * 257 * @note The content of the resolved L2 table entry is not validated!. 258 */ 259 DECLINLINE(PCDBGFBPL2ENTRY) dbgfRZBpL2GetByIdx(PVMCC pVM, uint32_t idxL2) 260 { 261 uint32_t idChunk = DBGF_BP_L2_IDX_GET_CHUNK_ID(idxL2); 262 uint32_t idxEntry = DBGF_BP_L2_IDX_GET_ENTRY(idxL2); 263 264 AssertReturn(idChunk < DBGF_BP_L2_TBL_CHUNK_COUNT, NULL); 265 AssertReturn(idxEntry < DBGF_BP_L2_TBL_ENTRIES_PER_CHUNK, NULL); 266 267 PDBGFBPL2TBLCHUNKR0 pL2Chunk = &pVM->dbgfr0.s.aBpL2TblChunks[idChunk]; 268 AssertPtrReturn(pL2Chunk->paBpL2TblBaseSharedR0, NULL); 269 270 return &pL2Chunk->CTX_SUFF(paBpL2TblBaseShared)[idxEntry]; 271 } 272 273 274 /** 275 * Walks the L2 table starting at the given root index searching for the given key. 276 * 277 * @returns VBox status code. 278 * @param pVM The cross context VM structure. 279 * @param pVCpu The cross context virtual CPU structure. 280 * @param pRegFrame Pointer to the register frame for the trap. 281 * @param fInHyper Flag whether the breakpoint triggered in hypervisor code. 282 * @param idxL2Root L2 table index of the table root. 283 * @param GCPtrKey The key to search for. 284 */ 285 static int dbgfRZBpL2Walk(PVMCC pVM, PVMCPUCC pVCpu, PCPUMCTXCORE pRegFrame, bool fInHyper, 286 uint32_t idxL2Root, RTGCUINTPTR GCPtrKey) 287 { 288 /** @todo We don't use the depth right now but abort the walking after a fixed amount of levels. */ 289 uint8_t iDepth = 32; 290 PCDBGFBPL2ENTRY pL2Entry = dbgfRZBpL2GetByIdx(pVM, idxL2Root); 291 292 while (RT_LIKELY( iDepth-- > 0 293 && pL2Entry)) 294 { 295 /* Make a copy of the entry before verification. */ 296 DBGFBPL2ENTRY L2Entry; 297 L2Entry.u64GCPtrKeyAndBpHnd1 = ASMAtomicReadU64((volatile uint64_t *)&pL2Entry->u64GCPtrKeyAndBpHnd1); 298 L2Entry.u64LeftRightIdxDepthBpHnd2 = ASMAtomicReadU64((volatile uint64_t *)&pL2Entry->u64LeftRightIdxDepthBpHnd2); 299 300 RTGCUINTPTR GCPtrL2Entry = DBGF_BP_L2_ENTRY_GET_GCPTR(L2Entry.u64GCPtrKeyAndBpHnd1); 301 if (GCPtrKey == GCPtrL2Entry) 302 { 303 DBGFBP hBp = DBGF_BP_L2_ENTRY_GET_BP_HND(L2Entry.u64GCPtrKeyAndBpHnd1, L2Entry.u64LeftRightIdxDepthBpHnd2); 304 305 /* Query the internal breakpoint state from the handle. */ 306 PDBGFBPINTR0 pBpR0 = NULL; 307 PDBGFBPINT pBp = dbgfR0BpGetByHnd(pVM, hBp, &pBpR0); 308 if ( pBp 309 && DBGF_BP_PUB_GET_TYPE(pBp->Pub.fFlagsAndType) == DBGFBPTYPE_INT3) 310 return dbgfRZBpHit(pVM, pVCpu, pRegFrame, hBp, pBp, pBpR0, fInHyper); 311 312 /* The entry got corrupted, just abort. */ 313 return VERR_DBGF_BP_L2_LOOKUP_FAILED; 314 } 315 316 /* Not found, get to the next level. */ 317 uint32_t idxL2Next = (GCPtrKey < GCPtrL2Entry) 318 ? DBGF_BP_L2_ENTRY_GET_IDX_LEFT(L2Entry.u64LeftRightIdxDepthBpHnd2) 319 : DBGF_BP_L2_ENTRY_GET_IDX_RIGHT(L2Entry.u64LeftRightIdxDepthBpHnd2); 320 /* It is genuine guest trap or we hit some assertion if we are at the end. */ 321 if (idxL2Next == DBGF_BP_L2_ENTRY_IDX_END) 322 return fInHyper 323 ? VINF_EM_DBG_HYPER_ASSERTION 324 : VINF_EM_RAW_GUEST_TRAP; 325 326 pL2Entry = dbgfRZBpL2GetByIdx(pVM, idxL2Next); 327 } 328 329 return VERR_DBGF_BP_L2_LOOKUP_FAILED; 330 } 248 331 #endif /* !VBOX_WITH_LOTS_OF_DBGF_BPS */ 249 332 … … 342 425 /* else Genuine guest trap. */ 343 426 } 344 /** @todo else Guru meditation */ 427 428 return VERR_DBGF_BP_L1_LOOKUP_FAILED; 345 429 } 346 430 else if (u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_L2_IDX) 347 { 348 /** @todo Walk the L2 tree searching for the correct spot. */ 349 } 350 /** @todo else Guru meditation */ 431 return dbgfRZBpL2Walk(pVM, pVCpu, pRegFrame, fInHyper, DBGF_BP_INT3_L1_ENTRY_GET_L2_IDX(u32L1Entry), 432 DBGF_BP_INT3_L2_KEY_EXTRACT_FROM_ADDR((RTGCUINTPTR)GCPtrBp)); 433 434 /* Some invalid type. */ 435 return VERR_DBGF_BP_L1_LOOKUP_FAILED; 351 436 } 352 437 } -
trunk/src/VBox/VMM/include/DBGFInternal.h
r86704 r86726 956 956 typedef const DBGFBPL2ENTRY *PCDBGFBPL2ENTRY; 957 957 958 /** Extracts the part from the given GC pointer used as the key in the L2 binary search tree. */ 959 #define DBGF_BP_INT3_L2_KEY_EXTRACT_FROM_ADDR(a_GCPtr) ((uint64_t)((a_GCPtr) >> 16)) 960 958 961 /** An invalid breakpoint chunk ID. */ 959 962 #define DBGF_BP_L2_IDX_CHUNK_ID_INVALID UINT32_MAX … … 967 970 /** Number of bits for the left/right index pointers. */ 968 971 #define DBGF_BP_L2_ENTRY_LEFT_RIGHT_IDX_BITS 22 972 /** Special index value marking the end of a tree. */ 973 #define DBGF_BP_L2_ENTRY_IDX_END UINT32_C(0x3fffff) 974 /** Number of bits to shift the breakpoint handle in the first part. */ 975 #define DBGF_BP_L2_ENTRY_BP_1ST_SHIFT 48 976 /** Mask for the first part of the breakpoint handle. */ 977 #define DBGF_BP_L2_ENTRY_BP_1ST_MASK UINT32_C(0x0000ffff) 978 /** Number of bits to shift the breakpoint handle in the second part. */ 979 #define DBGF_BP_L2_ENTRY_BP_2ND_SHIFT 52 980 /** Mask for the second part of the breakpoint handle. */ 981 #define DBGF_BP_L2_ENTRY_BP_2ND_MASK UINT32_C(0x0fff0000) 982 /** Mask for the second part of the breakpoint handle stored in the L2 entry. */ 983 #define DBGF_BP_L2_ENTRY_BP_2ND_L2_ENTRY_MASK UINT64_C(0xfff0000000000000) 984 /** Number of bits to shift the depth in the second part. */ 985 #define DBGF_BP_L2_ENTRY_DEPTH_SHIFT 44 986 /** Mask for the depth. */ 987 #define DBGF_BP_L2_ENTRY_DEPTH_MASK UINT8_MAX 988 /** Number of bits to shift the right L2 index in the second part. */ 989 #define DBGF_BP_L2_ENTRY_RIGHT_IDX_SHIFT 22 990 /** Number of bits to shift the left L2 index in the second part. */ 991 #define DBGF_BP_L2_ENTRY_LEFT_IDX_SHIFT 0 969 992 /** Index mask. */ 970 993 #define DBGF_BP_L2_ENTRY_LEFT_RIGHT_IDX_MASK (RT_BIT_32(DBGF_BP_L2_ENTRY_LEFT_RIGHT_IDX_BITS) - 1) 994 /** Left index mask. */ 995 #define DBGF_BP_L2_ENTRY_LEFT_IDX_MASK (DBGF_BP_L2_ENTRY_LEFT_RIGHT_IDX_MASK << DBGF_BP_L2_ENTRY_LEFT_IDX_SHIFT) 996 /** Right index mask. */ 997 #define DBGF_BP_L2_ENTRY_RIGHT_IDX_MASK (DBGF_BP_L2_ENTRY_LEFT_RIGHT_IDX_MASK << DBGF_BP_L2_ENTRY_RIGHT_IDX_SHIFT) 971 998 /** Returns the upper 6 bytes of the GC pointer from the given breakpoint entry. */ 972 999 #define DBGF_BP_L2_ENTRY_GET_GCPTR(a_u64GCPtrKeyAndBpHnd1) ((a_u64GCPtrKeyAndBpHnd1) & UINT64_C(0x0000ffffffffffff)) 973 1000 /** Returns the breakpoint handle from both L2 entry members. */ 974 1001 #define DBGF_BP_L2_ENTRY_GET_BP_HND(a_u64GCPtrKeyAndBpHnd1, a_u64LeftRightIdxDepthBpHnd2) \ 975 ((DBGFBP)(((a_u64GCPtrKeyAndBpHnd1) >> 48) | (((a_u64LeftRightIdxDepthBpHnd2) >> 52) << 16)))1002 ((DBGFBP)(((a_u64GCPtrKeyAndBpHnd1) >> DBGF_BP_L2_ENTRY_BP_1ST_SHIFT) | (((a_u64LeftRightIdxDepthBpHnd2) >> DBGF_BP_L2_ENTRY_BP_2ND_SHIFT) << 16))) 976 1003 /** Extracts the depth of the second 64bit L2 entry value. */ 977 #define DBGF_BP_L2_ENTRY_GET_DEPTH(a_u64LeftRightIdxDepthBpHnd2) ((uint8_t)(((a_u64LeftRightIdxDepthBpHnd2) >> 44) & UINT8_MAX))1004 #define DBGF_BP_L2_ENTRY_GET_DEPTH(a_u64LeftRightIdxDepthBpHnd2) ((uint8_t)(((a_u64LeftRightIdxDepthBpHnd2) >> DBGF_BP_L2_ENTRY_DEPTH_SHIFT) & DBGF_BP_L2_ENTRY_DEPTH_MASK)) 978 1005 /** Extracts the lower right index value from the L2 entry value. */ 979 1006 #define DBGF_BP_L2_ENTRY_GET_IDX_RIGHT(a_u64LeftRightIdxDepthBpHnd2) \
Note:
See TracChangeset
for help on using the changeset viewer.