Changeset 58909 in vbox
- Timestamp:
- Nov 29, 2015 7:23:46 PM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 104409
- Location:
- trunk
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/dbgf.h
r58903 r58909 189 189 */ 190 190 DBGFEVENT_POWERING_OFF, 191 192 /** Hardware Interrupt break. 193 * @todo not yet implemented. */ 194 DBGFEVENT_INTERRUPT_HARDWARE, 195 /** Software Interrupt break. 196 * @todo not yet implemented. */ 197 DBGFEVENT_INTERRUPT_SOFTWARE, 191 198 192 199 /** The first selectable event. … … 435 442 } u; 436 443 } DBGFEVENT; 444 AssertCompileSizeAlignment(DBGFEVENT, 8); 437 445 /** Pointer to VMM Debug Event. */ 438 446 typedef DBGFEVENT *PDBGFEVENT; … … 478 486 VMMR3DECL(int) DBGFR3InjectNMI(PUVM pUVM, VMCPUID idCpu); 479 487 488 /** 489 * Event configuration array element, see DBGFR3EventConfigEx. 490 */ 491 typedef struct DBGFEVENTCONFIG 492 { 493 /** The event to configure */ 494 DBGFEVENTTYPE enmType; 495 /** The new state. */ 496 bool fEnabled; 497 } DBGFEVENTCONFIG; 498 /** Pointer to an event config. */ 499 typedef DBGFEVENTCONFIG *PDBGFEVENTCONFIG; 500 /** Pointer to a const event config. */ 501 typedef const DBGFEVENTCONFIG *PCDBGFEVENTCONFIG; 502 503 VMMR3DECL(int) DBGFR3EventConfigEx(PUVM pUVM, PCDBGFEVENTCONFIG paConfigs, size_t cConfigs); 504 VMMR3DECL(int) DBGFR3EventConfig(PUVM pUVM, DBGFEVENTTYPE enmEvent, bool fEnabled); 505 VMMR3DECL(bool) DBGFR3EventIsEnabled(PUVM pUVM, DBGFEVENTTYPE enmEvent); 506 VMMR3DECL(int) DBGFR3EventQuery(PUVM pUVM, PDBGFEVENTCONFIG paConfigs, size_t cConfigs); 507 508 /** @name DBGFINTERRUPTSTATE_XXX - interrupt break state. 509 * @{ */ 510 #define DBGFINTERRUPTSTATE_DISABLED 0 511 #define DBGFINTERRUPTSTATE_ENABLED 1 512 #define DBGFINTERRUPTSTATE_DONT_TOUCH 2 513 /** @} */ 514 515 /** 516 * Interrupt break state configuration entry. 517 */ 518 typedef struct DBGFINTERRUPTCONFIG 519 { 520 /** The interrupt number. */ 521 uint8_t iInterrupt; 522 /** The hardware interrupt state (DBGFINTERRUPTSTATE_XXX). */ 523 uint8_t enmHardState; 524 /** The software interrupt state (DBGFINTERRUPTSTATE_XXX). */ 525 uint8_t enmSoftState; 526 } DBGFINTERRUPTCONFIG; 527 /** Pointer to an interrupt break state config entyr. */ 528 typedef DBGFINTERRUPTCONFIG *PDBGFINTERRUPTCONFIG; 529 /** Pointer to a const interrupt break state config entyr. */ 530 typedef DBGFINTERRUPTCONFIG const *PCDBGFINTERRUPTCONFIG; 531 532 VMMR3DECL(int) DBGFR3InterruptConfigEx(PUVM pUVM, PCDBGFINTERRUPTCONFIG paConfigs, size_t cConfigs); 533 VMMR3DECL(int) DBGFR3InterruptHardwareConfig(PUVM pUVM, uint8_t iInterrupt, bool fEnabled); 534 VMMR3DECL(int) DBGFR3InterruptSoftwareConfig(PUVM pUVM, uint8_t iInterrupt, bool fEnabled); 535 VMMR3DECL(int) DBGFR3InterruptHardwareIsEnabled(PUVM pUVM, uint8_t iInterrupt); 536 VMMR3DECL(int) DBGFR3InterruptSoftwareIsEnabled(PUVM pUVM, uint8_t iInterrupt); 537 480 538 #endif /* IN_RING3 */ 539 540 /** @def DBGF_IS_EVENT_ENABLED 541 * Checks if a selectable debug event is enabled or not (fast). 542 * 543 * @returns true/false. 544 * @param a_pVM Pointer to the cross context VM structure. 545 * @param a_enmEvent The selectable event to check. 546 * @remarks Only for use internally in the VMM. Use DBGFR3EventIsEnabled elsewhere. 547 */ 548 #if defined(VBOX_STRICT) && defined(RT_COMPILER_SUPPORTS_LAMBDA) 549 # define DBGF_IS_EVENT_ENABLED(a_pVM, a_enmEvent) \ 550 ([](PVM a_pLambdaVM, DBGFEVENTTYPE a_enmLambdaEvent) -> bool { \ 551 Assert(a_enmLambdaEvent >= DBGFEVENT_FIRST_SELECTABLE); \ 552 Assert(a_enmLambdaEvent < DBGFEVENT_END); \ 553 return ASMBitTest(&a_pLambdaVM->dbgf.ro.bmSelectedEvents, a_enmLambdaEvent); \ 554 }(a_pVM, a_enmEvent)) 555 #elif defined(VBOX_STRICT) && defined(__GNUC__) 556 # define DBGF_IS_EVENT_ENABLED(a_pVM, a_enmEvent) \ 557 __extension__ ({ \ 558 Assert((a_enmEvent) >= DBGFEVENT_FIRST_SELECTABLE); \ 559 Assert((a_enmEvent) < DBGFEVENT_END); \ 560 ASMBitTest(&(a_pVM)->dbgf.ro.bmSelectedEvents, (a_enmEvent)); \ 561 }) 562 #else 563 # define DBGF_IS_EVENT_ENABLED(a_pVM, a_enmEvent) \ 564 ASMBitTest(&(a_pVM)->dbgf.ro.bmSelectedEvents, (a_enmEvent)) 565 #endif 566 567 568 /** @def DBGF_IS_HARDWARE_INT_ENABLED 569 * Checks if hardware interrupt interception is enabled or not for an interrupt. 570 * 571 * @returns true/false. 572 * @param a_pVM Pointer to the cross context VM structure. 573 * @param a_iInterrupt Interrupt to check. 574 * @remarks Only for use internally in the VMM. Use 575 * DBGFR3InterruptHardwareIsEnabled elsewhere. 576 */ 577 #define DBGF_IS_HARDWARE_INT_ENABLED(a_pVM, a_iInterrupt) \ 578 ASMBitTest(&(a_pVM)->dbgf.ro.bmHardIntBreakpoints, (uint8_t)(a_iInterrupt)) 579 580 /** @def DBGF_IS_SOFTWARE_INT_ENABLED 581 * Checks if software interrupt interception is enabled or not for an interrupt. 582 * 583 * @returns true/false. 584 * @param a_pVM Pointer to the cross context VM structure. 585 * @param a_iInterrupt Interrupt to check. 586 * @remarks Only for use internally in the VMM. Use 587 * DBGFR3InterruptSoftwareIsEnabled elsewhere. 588 */ 589 #define DBGF_IS_SOFTWARE_INT_ENABLED(a_pVM, a_iInterrupt) \ 590 ASMBitTest(&(a_pVM)->dbgf.ro.bmSoftIntBreakpoints, (uint8_t)(a_iInterrupt)) 481 591 482 592 … … 644 754 * Breakpoint enumeration callback function. 645 755 * 646 * @returns VBox status code. Any failure will stop the enumeration. 756 * @returns VBox status code. 757 * The enumeration stops on failure status and VINF_CALLBACK_RETURN. 647 758 * @param pUVM The user mode VM handle. 648 759 * @param pvUser The user argument. -
trunk/include/VBox/vmm/iom.h
r58903 r58909 339 339 VMMR3_INT_DECL(int) IOMR3MmioDeregister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange); 340 340 341 VMMR3_INT_DECL(void) IOMR3NotifyBreakpointCountChange(PVM pVM, unsigned cPortIo, unsigned cMmio);341 VMMR3_INT_DECL(void) IOMR3NotifyBreakpointCountChange(PVM pVM, bool fPortIo, bool fMmio); 342 342 VMMR3_INT_DECL(void) IOMR3NotifyDebugEventChange(PVM pVM, DBGFEVENT enmEvent, bool fEnabled); 343 343 -
trunk/include/VBox/vmm/vm.h
r58283 r58909 217 217 struct DBGFCPU s; 218 218 #endif 219 uint8_t padding[ 64];/* multiple of 64 */219 uint8_t padding[256]; /* multiple of 64 */ 220 220 } dbgf; 221 221 … … 230 230 231 231 /** Align the following members on page boundary. */ 232 uint8_t abAlignment2[3 584];232 uint8_t abAlignment2[3392]; 233 233 234 234 /** PGM part. */ … … 983 983 #endif 984 984 #ifdef ___VBox_vmm_cpum_h 985 /** Read only info exposed about the host and guest CPUs. 985 /** Read only info exposed about the host and guest CPUs. */ 986 986 struct 987 987 { … … 1111 1111 struct DBGF s; 1112 1112 #endif 1113 #ifdef ___VBox_vmm_dbgf_h 1114 /** Read only info exposed about interrupt breakpoints and selected events. */ 1115 struct 1116 { 1117 /** Bitmap of enabled hardware interrupt breakpoints. */ 1118 uint32_t bmHardIntBreakpoints[256 / 32]; 1119 /** Bitmap of enabled software interrupt breakpoints. */ 1120 uint32_t bmSoftIntBreakpoints[256 / 32]; 1121 /** Bitmap of selected events. 1122 * This includes non-selectable events too for simplicity, we maintain the 1123 * state for some of these, as it may come in handy. */ 1124 uint32_t bmSelectedEvents[(DBGFEVENT_END + 31) / 32]; 1125 /** Enabled hardware interrupt breakpoints. */ 1126 uint32_t cHardIntBreakpoints; 1127 /** Enabled software interrupt breakpoints. */ 1128 uint32_t cSoftIntBreakpoints; 1129 /** Number of selected events. */ 1130 uint32_t cSelectedEvents; 1131 } const ro; 1132 #endif 1113 1133 uint8_t padding[2368]; /* multiple of 64 */ 1114 1134 } dbgf; -
trunk/include/VBox/vmm/vm.mac
r56291 r58909 142 142 .pdm resb 256 143 143 .iom resb 512 144 .dbgf resb 64144 .dbgf resb 256 145 145 .gim resb 64 146 146 -
trunk/src/VBox/Debugger/DBGConsole.cpp
r58170 r58909 657 657 658 658 case DBGFEVENT_BREAKPOINT: 659 case DBGFEVENT_BREAKPOINT_IO: 660 case DBGFEVENT_BREAKPOINT_MMIO: 659 661 case DBGFEVENT_BREAKPOINT_HYPER: 660 662 { 661 663 bool fRegCtxGuest = pDbgc->fRegCtxGuest; 662 pDbgc->fRegCtxGuest = pEvent->enmType == DBGFEVENT_BREAKPOINT;664 pDbgc->fRegCtxGuest = pEvent->enmType != DBGFEVENT_BREAKPOINT_HYPER; 663 665 664 666 rc = dbgcBpExec(pDbgc, pEvent->u.Bp.iBp); -
trunk/src/VBox/VMM/VMMAll/DBGFAll.cpp
r58903 r58909 26 26 #include <VBox/err.h> 27 27 #include <iprt/assert.h> 28 29 30 /* 31 * Check the read-only VM members. 32 */ 33 AssertCompileMembersSameSizeAndOffset(VM, dbgf.s.bmSoftIntBreakpoints, VM, dbgf.ro.bmSoftIntBreakpoints); 34 AssertCompileMembersSameSizeAndOffset(VM, dbgf.s.bmHardIntBreakpoints, VM, dbgf.ro.bmHardIntBreakpoints); 35 AssertCompileMembersSameSizeAndOffset(VM, dbgf.s.bmSelectedEvents, VM, dbgf.ro.bmSelectedEvents); 36 AssertCompileMembersSameSizeAndOffset(VM, dbgf.s.cHardIntBreakpoints, VM, dbgf.ro.cHardIntBreakpoints); 37 AssertCompileMembersSameSizeAndOffset(VM, dbgf.s.cSoftIntBreakpoints, VM, dbgf.ro.cSoftIntBreakpoints); 38 AssertCompileMembersSameSizeAndOffset(VM, dbgf.s.cSelectedEvents, VM, dbgf.ro.cSelectedEvents); 28 39 29 40 … … 120 131 * @returns true if armed, false if not. 121 132 * @param pVM The cross context VM structure. 133 * @remarks Don't call this from CPUMRecalcHyperDRx! 122 134 */ 123 135 VMM_INT_DECL(bool) DBGFBpIsHwArmed(PVM pVM) 124 136 { 125 Assert(RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints) == 4); 126 return (pVM->dbgf.s.aHwBreakpoints[0].fEnabled && pVM->dbgf.s.aHwBreakpoints[0].enmType == DBGFBPTYPE_REG) 127 || (pVM->dbgf.s.aHwBreakpoints[1].fEnabled && pVM->dbgf.s.aHwBreakpoints[1].enmType == DBGFBPTYPE_REG) 128 || (pVM->dbgf.s.aHwBreakpoints[2].fEnabled && pVM->dbgf.s.aHwBreakpoints[2].enmType == DBGFBPTYPE_REG) 129 || (pVM->dbgf.s.aHwBreakpoints[3].fEnabled && pVM->dbgf.s.aHwBreakpoints[3].enmType == DBGFBPTYPE_REG); 137 return pVM->dbgf.s.cEnabledHwBreakpoints > 0; 130 138 } 131 139 … … 136 144 * @returns true if armed, false if not. 137 145 * @param pVM The cross context VM structure. 146 * @remarks Don't call this from CPUMRecalcHyperDRx! 138 147 */ 139 148 VMM_INT_DECL(bool) DBGFBpIsHwIoArmed(PVM pVM) 140 149 { 141 Assert(RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints) == 4); 142 /** @todo cache this! */ 143 return ( pVM->dbgf.s.aHwBreakpoints[0].u.Reg.fType == X86_DR7_RW_IO 144 && pVM->dbgf.s.aHwBreakpoints[0].fEnabled 145 && pVM->dbgf.s.aHwBreakpoints[0].enmType == DBGFBPTYPE_REG 146 ) 147 || ( pVM->dbgf.s.aHwBreakpoints[1].u.Reg.fType == X86_DR7_RW_IO 148 && pVM->dbgf.s.aHwBreakpoints[1].fEnabled 149 && pVM->dbgf.s.aHwBreakpoints[1].enmType == DBGFBPTYPE_REG 150 ) 151 || ( pVM->dbgf.s.aHwBreakpoints[2].u.Reg.fType == X86_DR7_RW_IO 152 && pVM->dbgf.s.aHwBreakpoints[2].fEnabled 153 && pVM->dbgf.s.aHwBreakpoints[2].enmType == DBGFBPTYPE_REG 154 ) 155 || ( pVM->dbgf.s.aHwBreakpoints[3].u.Reg.fType == X86_DR7_RW_IO 156 && pVM->dbgf.s.aHwBreakpoints[3].fEnabled 157 && pVM->dbgf.s.aHwBreakpoints[3].enmType == DBGFBPTYPE_REG 158 ); 150 return pVM->dbgf.s.cEnabledHwIoBreakpoints > 0; 159 151 } 160 152 … … 185 177 * the guest. 186 178 */ 187 for (unsigned iBp = 0; iBp < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints); iBp++)179 if (pVM->dbgf.s.cEnabledHwIoBreakpoints > 0) 188 180 { 189 if ( pVM->dbgf.s.aHwBreakpoints[iBp].u.Reg.fType == X86_DR7_RW_IO 190 && pVM->dbgf.s.aHwBreakpoints[iBp].fEnabled 191 && pVM->dbgf.s.aHwBreakpoints[iBp].enmType == DBGFBPTYPE_REG ) 181 for (unsigned iBp = 0; iBp < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints); iBp++) 192 182 { 193 uint8_t cbReg = pVM->dbgf.s.aHwBreakpoints[iBp].u.Reg.cb; Assert(RT_IS_POWER_OF_TWO(cbReg)); 194 uint64_t uDrXFirst = pVM->dbgf.s.aHwBreakpoints[iBp].u.Reg.GCPtr & ~(uint64_t)(cbReg - 1); 195 uint64_t uDrXLast = uDrXFirst + cbReg - 1; 196 if (uDrXFirst <= uIoPortLast && uDrXLast >= uIoPortFirst) 183 if ( pVM->dbgf.s.aHwBreakpoints[iBp].u.Reg.fType == X86_DR7_RW_IO 184 && pVM->dbgf.s.aHwBreakpoints[iBp].fEnabled 185 && pVM->dbgf.s.aHwBreakpoints[iBp].enmType == DBGFBPTYPE_REG ) 197 186 { 198 /* (See also DBGFRZTrap01Handler.) */ 199 pVCpu->dbgf.s.iActiveBp = pVM->dbgf.s.aHwBreakpoints[iBp].iBp; 200 pVCpu->dbgf.s.fSingleSteppingRaw = false; 201 202 LogFlow(("DBGFBpCheckIo: hit hw breakpoint %d at %04x:%RGv (iop %#x)\n", 203 pVM->dbgf.s.aHwBreakpoints[iBp].iBp, pCtx->cs.Sel, pCtx->rip, uIoPort)); 204 return VINF_EM_DBG_BREAKPOINT; 187 uint8_t cbReg = pVM->dbgf.s.aHwBreakpoints[iBp].u.Reg.cb; Assert(RT_IS_POWER_OF_TWO(cbReg)); 188 uint64_t uDrXFirst = pVM->dbgf.s.aHwBreakpoints[iBp].u.Reg.GCPtr & ~(uint64_t)(cbReg - 1); 189 uint64_t uDrXLast = uDrXFirst + cbReg - 1; 190 if (uDrXFirst <= uIoPortLast && uDrXLast >= uIoPortFirst) 191 { 192 /* (See also DBGFRZTrap01Handler.) */ 193 pVCpu->dbgf.s.iActiveBp = pVM->dbgf.s.aHwBreakpoints[iBp].iBp; 194 pVCpu->dbgf.s.fSingleSteppingRaw = false; 195 196 LogFlow(("DBGFBpCheckIo: hit hw breakpoint %d at %04x:%RGv (iop %#x)\n", 197 pVM->dbgf.s.aHwBreakpoints[iBp].iBp, pCtx->cs.Sel, pCtx->rip, uIoPort)); 198 return VINF_EM_DBG_BREAKPOINT; 199 } 205 200 } 206 201 } -
trunk/src/VBox/VMM/VMMR3/DBGF.cpp
r58903 r58909 1218 1218 1219 1219 /** 1220 * @callback_method_impl{FNVMMEMTRENDEZVOUS} 1221 */ 1222 static DECLCALLBACK(VBOXSTRICTRC) dbgfR3EventConfigNotifyAllCpus(PVM pVM, PVMCPU pVCpu, void *pvUser) 1223 { 1224 /* Don't do anything, just make sure all CPUs goes thru EM. */ 1225 NOREF(pVM); NOREF(pVCpu); NOREF(pvUser); 1226 return VINF_SUCCESS; 1227 } 1228 1229 1230 /** 1231 * Worker for DBGFR3EventConfigEx. 1232 * 1233 * @returns VBox status code. Will not return VBOX_INTERRUPTED. 1234 * @param pUVM The user mode VM handle. 1235 * @param paConfigs The event to configure and their new state. 1236 * @param cConfigs Number of entries in @a paConfigs. 1237 */ 1238 static DECLCALLBACK(int) dbgfR3EventConfigEx(PUVM pUVM, DBGFEVENTCONFIG volatile const *paConfigs, size_t cConfigs) 1239 { 1240 PVM pVM = pUVM->pVM; 1241 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 1242 1243 /* 1244 * Apply the changes. 1245 */ 1246 unsigned cChanges = 0; 1247 for (uint32_t i = 0; i < cConfigs; i++) 1248 { 1249 DBGFEVENTTYPE enmType = paConfigs[i].enmType; 1250 AssertReturn(enmType >= DBGFEVENT_FIRST_SELECTABLE && enmType < DBGFEVENT_END, VERR_INVALID_PARAMETER); 1251 if (paConfigs[i].fEnabled) 1252 cChanges += ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmSelectedEvents, enmType) == false; 1253 else 1254 cChanges += ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmSelectedEvents, enmType) == true; 1255 } 1256 1257 /* 1258 * If this is an SMP setup, we must interrupt the other CPUs if there were 1259 * changes just to make sure their execution engines are aware of them. 1260 */ 1261 int rc = VINF_SUCCESS; 1262 if (cChanges > 0 && pVM->cCpus > 1) 1263 rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3EventConfigNotifyAllCpus, NULL); 1264 return rc; 1265 } 1266 1267 1268 /** 1269 * Configures (enables/disables) multiple selectable debug events. 1270 * 1271 * @returns VBox status code. 1272 * @param pUVM The user mode VM handle. 1273 * @param paConfigs The event to configure and their new state. 1274 * @param cConfigs Number of entries in @a paConfigs. 1275 */ 1276 VMMR3DECL(int) DBGFR3EventConfigEx(PUVM pUVM, PCDBGFEVENTCONFIG paConfigs, size_t cConfigs) 1277 { 1278 /* 1279 * Validate input. 1280 */ 1281 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); 1282 size_t i = cConfigs; 1283 while (i-- > 0) 1284 { 1285 AssertReturn(paConfigs[i].enmType >= DBGFEVENT_FIRST_SELECTABLE, VERR_INVALID_PARAMETER); 1286 AssertReturn(paConfigs[i].enmType < DBGFEVENT_END, VERR_INVALID_PARAMETER); 1287 } 1288 1289 /* 1290 * Apply the changes in EMT(0). 1291 */ 1292 return VMR3ReqPriorityCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3EventConfigEx, 3, pUVM, paConfigs, cConfigs); 1293 } 1294 1295 1296 /** 1297 * Enables or disables a selectable debug event. 1298 * 1299 * @returns VBox status code. 1300 * @param pUVM The user mode VM handle. 1301 * @param enmEvent The selectable debug event. 1302 * @param fEnabled The new state. 1303 */ 1304 VMMR3DECL(int) DBGFR3EventConfig(PUVM pUVM, DBGFEVENTTYPE enmEvent, bool fEnabled) 1305 { 1306 /* 1307 * Convert to an array call. 1308 */ 1309 DBGFEVENTCONFIG EvtCfg = { enmEvent, fEnabled }; 1310 return DBGFR3EventConfigEx(pUVM, &EvtCfg, 1); 1311 } 1312 1313 1314 /** 1315 * Checks if the given selectable event is enabled. 1316 * 1317 * @returns true if enabled, false if not or invalid input. 1318 * @param pUVM The user mode VM handle. 1319 * @param enmEvent The selectable debug event. 1320 * @sa DBGFR3EventQuery 1321 */ 1322 VMMR3DECL(bool) DBGFR3EventIsEnabled(PUVM pUVM, DBGFEVENTTYPE enmEvent) 1323 { 1324 /* 1325 * Validate input. 1326 */ 1327 AssertReturn( enmEvent >= DBGFEVENT_HALT_DONE 1328 && enmEvent < DBGFEVENT_END, false); 1329 Assert( enmEvent >= DBGFEVENT_FIRST_SELECTABLE 1330 || enmEvent == DBGFEVENT_BREAKPOINT 1331 || enmEvent == DBGFEVENT_BREAKPOINT_IO 1332 || enmEvent == DBGFEVENT_BREAKPOINT_MMIO); 1333 1334 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false); 1335 PVM pVM = pUVM->pVM; 1336 VM_ASSERT_VALID_EXT_RETURN(pVM, false); 1337 1338 /* 1339 * Check the event status. 1340 */ 1341 return ASMBitTest(&pVM->dbgf.s.bmSelectedEvents, enmEvent); 1342 } 1343 1344 1345 /** 1346 * Queries the status of a set of events. 1347 * 1348 * @returns VBox status code. 1349 * @param pUVM The user mode VM handle. 1350 * @param paConfigs The events to query and where to return the state. 1351 * @param cConfigs The number of elements in @a paConfigs. 1352 * @sa DBGFR3EventIsEnabled, DBGF_IS_EVENT_ENABLED 1353 */ 1354 VMMR3DECL(int) DBGFR3EventQuery(PUVM pUVM, PDBGFEVENTCONFIG paConfigs, size_t cConfigs) 1355 { 1356 /* 1357 * Validate input. 1358 */ 1359 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false); 1360 PVM pVM = pUVM->pVM; 1361 VM_ASSERT_VALID_EXT_RETURN(pVM, false); 1362 1363 for (size_t i = 0; i < cConfigs; i++) 1364 { 1365 DBGFEVENTTYPE enmType = paConfigs[i].enmType; 1366 AssertReturn( enmType >= DBGFEVENT_HALT_DONE 1367 && enmType < DBGFEVENT_END, VERR_INVALID_PARAMETER); 1368 Assert( enmType >= DBGFEVENT_FIRST_SELECTABLE 1369 || enmType == DBGFEVENT_BREAKPOINT 1370 || enmType == DBGFEVENT_BREAKPOINT_IO 1371 || enmType == DBGFEVENT_BREAKPOINT_MMIO); 1372 paConfigs[i].fEnabled = ASMBitTest(&pVM->dbgf.s.bmSelectedEvents, paConfigs[i].enmType); 1373 } 1374 1375 return VINF_SUCCESS; 1376 } 1377 1378 1379 /** 1380 * Worker for DBGFR3InterruptConfigEx. 1381 * 1382 * @returns VBox status code. Will not return VBOX_INTERRUPTED. 1383 * @param pUVM The user mode VM handle. 1384 * @param paConfigs The event to configure and their new state. 1385 * @param cConfigs Number of entries in @a paConfigs. 1386 */ 1387 static DECLCALLBACK(int) dbgfR3InterruptConfigEx(PUVM pUVM, PCDBGFINTERRUPTCONFIG paConfigs, size_t cConfigs) 1388 { 1389 PVM pVM = pUVM->pVM; 1390 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 1391 1392 /* 1393 * Apply the changes. 1394 */ 1395 bool fChanged; 1396 for (uint32_t i = 0; i < cConfigs; i++) 1397 { 1398 /* 1399 * Hardware interrupts. 1400 */ 1401 if (paConfigs[i].enmHardState == DBGFINTERRUPTSTATE_ENABLED) 1402 { 1403 fChanged = ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmHardIntBreakpoints, paConfigs[i].iInterrupt) == false; 1404 if (fChanged) 1405 { 1406 Assert(pVM->dbgf.s.cHardIntBreakpoints < 256); 1407 pVM->dbgf.s.cHardIntBreakpoints++; 1408 } 1409 } 1410 else if (paConfigs[i].enmHardState == DBGFINTERRUPTSTATE_DISABLED) 1411 { 1412 fChanged = ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmHardIntBreakpoints, paConfigs[i].iInterrupt) == true; 1413 if (fChanged) 1414 { 1415 Assert(pVM->dbgf.s.cHardIntBreakpoints > 0); 1416 pVM->dbgf.s.cHardIntBreakpoints--; 1417 } 1418 } 1419 1420 /* 1421 * Software interrupts. 1422 */ 1423 if (paConfigs[i].enmHardState == DBGFINTERRUPTSTATE_ENABLED) 1424 { 1425 fChanged = ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmSoftIntBreakpoints, paConfigs[i].iInterrupt) == false; 1426 if (fChanged) 1427 { 1428 Assert(pVM->dbgf.s.cSoftIntBreakpoints < 256); 1429 pVM->dbgf.s.cSoftIntBreakpoints++; 1430 } 1431 } 1432 else if (paConfigs[i].enmSoftState == DBGFINTERRUPTSTATE_DISABLED) 1433 { 1434 fChanged = ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmSoftIntBreakpoints, paConfigs[i].iInterrupt) == true; 1435 if (fChanged) 1436 { 1437 Assert(pVM->dbgf.s.cSoftIntBreakpoints > 0); 1438 pVM->dbgf.s.cSoftIntBreakpoints--; 1439 } 1440 } 1441 } 1442 1443 /* 1444 * Update the event bitmap entries and see if we need to notify other CPUs. 1445 */ 1446 fChanged = false; 1447 if (pVM->dbgf.s.cHardIntBreakpoints > 0) 1448 fChanged |= ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_INTERRUPT_HARDWARE) == false; 1449 else 1450 fChanged |= ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_INTERRUPT_HARDWARE) == true; 1451 1452 if (pVM->dbgf.s.cSoftIntBreakpoints > 0) 1453 fChanged |= ASMAtomicBitTestAndSet(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_INTERRUPT_SOFTWARE) == false; 1454 else 1455 fChanged |= ASMAtomicBitTestAndClear(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_INTERRUPT_SOFTWARE) == true; 1456 1457 int rc = VINF_SUCCESS; 1458 if (fChanged && pVM->cCpus > 1) 1459 rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE, dbgfR3EventConfigNotifyAllCpus, NULL); 1460 return rc; 1461 } 1462 1463 1464 /** 1465 * Changes 1466 * 1467 * @returns VBox status code. 1468 * @param pUVM The user mode VM handle. 1469 * @param paConfigs The events to query and where to return the state. 1470 * @param cConfigs The number of elements in @a paConfigs. 1471 * @sa DBGFR3InterruptConfigHardware, DBGFR3InterruptConfigSoftware 1472 */ 1473 VMMR3DECL(int) DBGFR3InterruptConfigEx(PUVM pUVM, PCDBGFINTERRUPTCONFIG paConfigs, size_t cConfigs) 1474 { 1475 /* 1476 * Validate input. 1477 */ 1478 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE); 1479 size_t i = cConfigs; 1480 while (i-- > 0) 1481 { 1482 AssertReturn(paConfigs[i].enmHardState <= DBGFINTERRUPTSTATE_DONT_TOUCH, VERR_INVALID_PARAMETER); 1483 AssertReturn(paConfigs[i].enmSoftState <= DBGFINTERRUPTSTATE_DONT_TOUCH, VERR_INVALID_PARAMETER); 1484 } 1485 1486 /* 1487 * Apply the changes in EMT(0). 1488 */ 1489 return VMR3ReqPriorityCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3InterruptConfigEx, 3, pUVM, paConfigs, cConfigs); 1490 } 1491 1492 1493 /** 1494 * Configures interception of a hardware interrupt. 1495 * 1496 * @returns VBox status code. 1497 * @param pUVM The user mode VM handle. 1498 * @param iInterrupt The interrupt number. 1499 * @param fEnabled Whether interception is enabled or not. 1500 * @sa DBGFR3InterruptSoftwareConfig, DBGFR3InterruptConfigEx 1501 */ 1502 VMMR3DECL(int) DBGFR3InterruptHardwareConfig(PUVM pUVM, uint8_t iInterrupt, bool fEnabled) 1503 { 1504 /* 1505 * Convert to DBGFR3InterruptConfigEx call. 1506 */ 1507 DBGFINTERRUPTCONFIG IntCfg = { iInterrupt, (uint8_t)fEnabled, DBGFINTERRUPTSTATE_DONT_TOUCH }; 1508 return DBGFR3InterruptConfigEx(pUVM, &IntCfg, 1); 1509 } 1510 1511 1512 /** 1513 * Configures interception of a software interrupt. 1514 * 1515 * @returns VBox status code. 1516 * @param pUVM The user mode VM handle. 1517 * @param iInterrupt The interrupt number. 1518 * @param fEnabled Whether interception is enabled or not. 1519 * @sa DBGFR3InterruptHardwareConfig, DBGFR3InterruptConfigEx 1520 */ 1521 VMMR3DECL(int) DBGFR3InterruptSoftwareConfig(PUVM pUVM, uint8_t iInterrupt, bool fEnabled) 1522 { 1523 /* 1524 * Convert to DBGFR3InterruptConfigEx call. 1525 */ 1526 DBGFINTERRUPTCONFIG IntCfg = { iInterrupt, DBGFINTERRUPTSTATE_DONT_TOUCH, (uint8_t)fEnabled }; 1527 return DBGFR3InterruptConfigEx(pUVM, &IntCfg, 1); 1528 } 1529 1530 1531 /** 1532 * Checks whether interception is enabled for a hardware interrupt. 1533 * 1534 * @returns true if enabled, false if not or invalid input. 1535 * @param pUVM The user mode VM handle. 1536 * @param iInterrupt The interrupt number. 1537 * @sa DBGFR3InterruptSoftwareIsEnabled, DBGF_IS_HARDWARE_INT_ENABLED, 1538 * DBGF_IS_SOFTWARE_INT_ENABLED 1539 */ 1540 VMMR3DECL(int) DBGFR3InterruptHardwareIsEnabled(PUVM pUVM, uint8_t iInterrupt) 1541 { 1542 /* 1543 * Validate input. 1544 */ 1545 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false); 1546 PVM pVM = pUVM->pVM; 1547 VM_ASSERT_VALID_EXT_RETURN(pVM, false); 1548 1549 /* 1550 * Check it. 1551 */ 1552 return ASMBitTest(&pVM->dbgf.s.bmHardIntBreakpoints, iInterrupt); 1553 } 1554 1555 1556 /** 1557 * Checks whether interception is enabled for a software interrupt. 1558 * 1559 * @returns true if enabled, false if not or invalid input. 1560 * @param pUVM The user mode VM handle. 1561 * @param iInterrupt The interrupt number. 1562 * @sa DBGFR3InterruptHardwareIsEnabled, DBGF_IS_SOFTWARE_INT_ENABLED, 1563 * DBGF_IS_HARDWARE_INT_ENABLED, 1564 */ 1565 VMMR3DECL(int) DBGFR3InterruptSoftwareIsEnabled(PUVM pUVM, uint8_t iInterrupt) 1566 { 1567 /* 1568 * Validate input. 1569 */ 1570 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false); 1571 PVM pVM = pUVM->pVM; 1572 VM_ASSERT_VALID_EXT_RETURN(pVM, false); 1573 1574 /* 1575 * Check it. 1576 */ 1577 return ASMBitTest(&pVM->dbgf.s.bmSoftIntBreakpoints, iInterrupt); 1578 } 1579 1580 1581 1582 /** 1220 1583 * Call this to single step programmatically. 1221 1584 * -
trunk/src/VBox/VMM/VMMR3/DBGFBp.cpp
r58903 r58909 103 103 { 104 104 /* 105 * Determine which array to search. 106 */ 105 * Determine which array to search and where in the array to start 106 * searching (latter for grouping similar BPs, reducing runtime overhead). 107 */ 108 unsigned iStart; 107 109 unsigned cBps; 108 uint32_t *pcBpsCur;109 110 PDBGFBP paBps; 110 111 switch (enmType) … … 113 114 cBps = RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints); 114 115 paBps = &pVM->dbgf.s.aHwBreakpoints[0]; 115 pcBpsCur = &pVM->dbgf.s.cHwBreakpoints;116 iStart = 0; 116 117 break; 117 118 118 119 case DBGFBPTYPE_INT3: 119 120 case DBGFBPTYPE_REM: 121 case DBGFBPTYPE_PORT_IO: 122 case DBGFBPTYPE_MMIO: 120 123 cBps = RT_ELEMENTS(pVM->dbgf.s.aBreakpoints); 121 124 paBps = &pVM->dbgf.s.aBreakpoints[0]; 122 pcBpsCur = &pVM->dbgf.s.cBreakpoints; 125 if (enmType == DBGFBPTYPE_PORT_IO) 126 iStart = cBps / 4 * 2; 127 else if (enmType == DBGFBPTYPE_MMIO) 128 iStart = cBps / 4 * 1; 129 else if (enmType == DBGFBPTYPE_REM) 130 iStart = cBps / 4 * 3; 131 else 132 iStart = 0; 123 133 break; 124 134 … … 129 139 130 140 /* 131 * Search. 132 */ 133 for (unsigned iBp = 0; iBp < cBps; iBp++) 141 * Search for a free breakpoint entry. 142 */ 143 unsigned iBp; 144 for (iBp = iStart; iBp < cBps; iBp++) 134 145 if (paBps[iBp].enmType == DBGFBPTYPE_FREE) 146 break; 147 if (iBp >= cBps && iStart != 0) 148 for (iBp = 0; iBp < cBps; iBp++) 149 if (paBps[iBp].enmType == DBGFBPTYPE_FREE) 150 break; 151 if (iBp < cBps) 152 { 153 /* 154 * Return what we found. 155 */ 156 paBps[iBp].fEnabled = false; 157 paBps[iBp].cHits = 0; 158 paBps[iBp].enmType = enmType; 159 return &paBps[iBp]; 160 } 161 162 LogFlow(("dbgfR3BpAlloc: returns NULL - we're out of breakpoint slots! cBps=%u\n", cBps)); 163 return NULL; 164 } 165 166 167 /** 168 * Updates IOM on whether we've got any armed I/O port or MMIO breakpoints. 169 * 170 * @returns VINF_SUCCESS 171 * @param pVM The cross context VM structure. 172 * @param enmType The breakpoint type. 173 * @param pOpt The breakpoint optimization structure to update. 174 */ 175 static int dbgfR3BpUpdateSearchOptimizations(PVM pVM, DBGFBPTYPE enmType, PDBGFBPSEARCHOPT pOpt) 176 { 177 DBGFBPSEARCHOPT Opt = { UINT32_MAX, 0 }; 178 179 for (uint32_t iBp = 0; iBp < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints); iBp++) 180 if ( pVM->dbgf.s.aBreakpoints[iBp].enmType == enmType 181 && pVM->dbgf.s.aBreakpoints[iBp].fEnabled) 135 182 { 136 ++*pcBpsCur; 137 paBps[iBp].cHits = 0; 138 paBps[iBp].enmType = enmType; 139 return &paBps[iBp]; 183 if (Opt.iStartSearch > iBp) 184 Opt.iStartSearch = iBp; 185 Opt.cToSearch = iBp - Opt.iStartSearch + 1; 140 186 } 141 187 142 LogFlow(("dbgfR3BpAlloc: returns NULL - we're out of breakpoint slots! %u/%u\n", *pcBpsCur, cBps));143 return NULL;188 *pOpt = Opt; 189 return VINF_SUCCESS; 144 190 } 145 191 … … 176 222 case DBGFBPTYPE_INT3: 177 223 case DBGFBPTYPE_REM: 224 case DBGFBPTYPE_PORT_IO: 225 case DBGFBPTYPE_MMIO: 178 226 break; 179 227 … … 248 296 249 297 case DBGFBPTYPE_REG: 250 Assert(pVM->dbgf.s.cHwBreakpoints > 0); 251 pVM->dbgf.s.cHwBreakpoints--; 298 Assert(pBp - &pVM->dbgf.s.aHwBreakpoints[0] < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints)); 252 299 break; 253 300 254 301 case DBGFBPTYPE_INT3: 255 302 case DBGFBPTYPE_REM: 256 Assert(pVM->dbgf.s.cBreakpoints > 0); 257 pVM->dbgf.s.cBreakpoints--; 303 case DBGFBPTYPE_PORT_IO: 304 case DBGFBPTYPE_MMIO: 305 Assert(pBp - &pVM->dbgf.s.aBreakpoints[0] < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints)); 258 306 break; 259 307 … … 264 312 } 265 313 pBp->enmType = DBGFBPTYPE_FREE; 314 NOREF(pVM); 266 315 } 267 316 … … 325 374 ASMCompilerBarrier(); 326 375 pBp->fEnabled = true; 376 dbgfR3BpUpdateSearchOptimizations(pVM, DBGFBPTYPE_INT3, &pVM->dbgf.s.Int3); 327 377 328 378 /* … … 360 410 * This must be done on EMT. 361 411 */ 362 /** @todo SMP? */ 363 int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpSetInt3, 5, 412 int rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3BpSetInt3, 5, 364 413 pUVM, pAddress, &iHitTrigger, &iHitDisable, piBp); 365 414 LogFlow(("DBGFR3BpSet: returns %Rrc\n", rc)); … … 556 605 * This must be done on EMT. 557 606 */ 558 int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpSetReg, 7,607 int rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3BpSetReg, 7, 559 608 pUVM, pAddress, &iHitTrigger, &iHitDisable, fType, cb, piBp); 560 609 LogFlow(("DBGFR3BpSetReg: returns %Rrc\n", rc)); … … 567 616 * @callback_method_impl{FNVMMEMTRENDEZVOUS} 568 617 */ 569 DECLCALLBACK(VBOXSTRICTRC) dbgfR3BpRegRecalcOnCpu(PVM pVM, PVMCPU pVCpu, void *pvUser)618 static DECLCALLBACK(VBOXSTRICTRC) dbgfR3BpRegRecalcOnCpu(PVM pVM, PVMCPU pVCpu, void *pvUser) 570 619 { 571 620 NOREF(pVM); NOREF(pvUser); 621 622 /* 623 * CPU 0 updates the enabled hardware breakpoint counts. 624 */ 625 if (pVCpu->idCpu == 0) 626 { 627 pVM->dbgf.s.cEnabledHwBreakpoints = 0; 628 pVM->dbgf.s.cEnabledHwIoBreakpoints = 0; 629 630 for (uint32_t iBp = 0; iBp < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints); iBp++) 631 if ( pVM->dbgf.s.aHwBreakpoints[iBp].fEnabled 632 && pVM->dbgf.s.aHwBreakpoints[iBp].enmType == DBGFBPTYPE_REG) 633 { 634 pVM->dbgf.s.cEnabledHwBreakpoints += 1; 635 pVM->dbgf.s.cEnabledHwIoBreakpoints += pVM->dbgf.s.aHwBreakpoints[iBp].u.Reg.fType == X86_DR7_RW_IO; 636 } 637 } 638 572 639 return CPUMRecalcHyperDRx(pVCpu, UINT8_MAX, false); 573 640 } … … 576 643 /** 577 644 * Arms a debug register breakpoint. 645 * 578 646 * This is used to implement both DBGFR3BpSetReg() and DBGFR3BpEnable(). 579 647 * … … 581 649 * @param pVM The cross context VM structure. 582 650 * @param pBp The breakpoint. 651 * @thread EMT(0) 583 652 */ 584 653 static int dbgfR3BpRegArm(PVM pVM, PDBGFBP pBp) … … 591 660 /** 592 661 * Disarms a debug register breakpoint. 662 * 593 663 * This is used to implement both DBGFR3BpClear() and DBGFR3BpDisable(). 594 664 * … … 596 666 * @param pVM The cross context VM structure. 597 667 * @param pBp The breakpoint. 668 * @thread EMT(0) 598 669 */ 599 670 static int dbgfR3BpRegDisarm(PVM pVM, PDBGFBP pBp) … … 615 686 * Use ~(uint64_t) if it's never gonna be disabled. 616 687 * @param piBp Where to store the breakpoint id. (optional) 617 * @thread EMT 688 * @thread EMT(0) 618 689 * @internal 619 690 */ … … 707 778 * This must be done on EMT. 708 779 */ 709 int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpSetREM, 5,780 int rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3BpSetREM, 5, 710 781 pUVM, pAddress, &iHitTrigger, &iHitDisable, piBp); 711 782 LogFlow(("DBGFR3BpSetREM: returns %Rrc\n", rc)); … … 714 785 715 786 716 717 787 /** 718 788 * Updates IOM on whether we've got any armed I/O port or MMIO breakpoints. … … 720 790 * @returns VINF_SUCCESS 721 791 * @param pVM The cross context VM structure. 792 * @thread EMT(0) 722 793 */ 723 794 static int dbgfR3BpUpdateIom(PVM pVM) 724 795 { 725 unsigned cPortIo = 0; 726 unsigned cMmio = 0; 727 for (uint32_t iBp = 0; iBp < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints); iBp++) 728 if (pVM->dbgf.s.aBreakpoints[iBp].fEnabled) 729 { 730 if (pVM->dbgf.s.aBreakpoints[iBp].enmType == DBGFBPTYPE_PORT_IO) 731 cPortIo++; 732 else if (pVM->dbgf.s.aBreakpoints[iBp].enmType == DBGFBPTYPE_MMIO) 733 cMmio++; 734 } 735 736 pVM->dbgf.s.fHasPortIoBps = cPortIo != 0; 737 pVM->dbgf.s.fHasMmioBps = cMmio != 0; 738 739 IOMR3NotifyBreakpointCountChange(pVM, cPortIo, cMmio); 796 dbgfR3BpUpdateSearchOptimizations(pVM, DBGFBPTYPE_PORT_IO, &pVM->dbgf.s.PortIo); 797 if (pVM->dbgf.s.PortIo.cToSearch) 798 ASMAtomicBitSet(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_BREAKPOINT_IO); 799 else 800 ASMAtomicBitClear(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_BREAKPOINT_IO); 801 802 dbgfR3BpUpdateSearchOptimizations(pVM, DBGFBPTYPE_MMIO, &pVM->dbgf.s.Mmio); 803 if (pVM->dbgf.s.Mmio.cToSearch) 804 ASMAtomicBitSet(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_BREAKPOINT_MMIO); 805 else 806 ASMAtomicBitClear(&pVM->dbgf.s.bmSelectedEvents, DBGFEVENT_BREAKPOINT_MMIO); 807 808 IOMR3NotifyBreakpointCountChange(pVM, pVM->dbgf.s.PortIo.cToSearch != 0, pVM->dbgf.s.Mmio.cToSearch != 0); 740 809 return VINF_SUCCESS; 741 810 } … … 755 824 * Use ~(uint64_t) if it's never gonna be disabled. 756 825 * @param piBp Where to store the breakpoint ID. 826 * @thread EMT(0) 757 827 */ 758 828 static DECLCALLBACK(int) dbgfR3BpSetPortIo(PUVM pUVM, RTIOPORT uPort, RTIOPORT cPorts, uint32_t fAccess, … … 821 891 * Use ~(uint64_t) if it's never gonna be disabled. 822 892 * @param piBp Where to store the breakpoint ID. Optional. 893 * @thread Any thread. 823 894 */ 824 895 VMMR3DECL(int) DBGFR3BpSetPortIo(PUVM pUVM, RTIOPORT uPort, RTIOPORT cPorts, uint32_t fAccess, … … 837 908 */ 838 909 uint32_t iBp = -1; 839 int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpSetPortIo, 7,910 int rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3BpSetPortIo, 7, 840 911 pUVM, uPort, cPorts, fAccess, &iHitTrigger, &iHitDisable, piBp); 841 912 if (piBp) 842 913 *piBp = iBp; 843 LogFlow(("DBGFR3BpSetPortIo: returns %Rrc *piBp=%d\n", rc, iBp));914 LogFlow(("DBGFR3BpSetPortIo: returns %Rrc iBp=%d\n", rc, iBp)); 844 915 return rc; 845 916 } … … 859 930 * Use ~(uint64_t) if it's never gonna be disabled. 860 931 * @param piBp Where to store the breakpoint ID. 932 * @thread EMT(0) 861 933 */ 862 934 static DECLCALLBACK(int) dbgfR3BpSetMmio(PUVM pUVM, PCRTGCPHYS pGCPhys, uint32_t cb, uint32_t fAccess, … … 927 999 * Use ~(uint64_t) if it's never gonna be disabled. 928 1000 * @param piBp Where to store the breakpoint ID. Optional. 1001 * @thread Any thread. 929 1002 */ 930 1003 VMMR3DECL(int) DBGFR3BpSetMmio(PUVM pUVM, RTGCPHYS GCPhys, uint32_t cb, uint32_t fAccess, … … 943 1016 */ 944 1017 uint32_t iBp = -1; 945 int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpSetMmio, 7,1018 int rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3BpSetMmio, 7, 946 1019 pUVM, &GCPhys, cb, fAccess, &iHitTrigger, &iHitDisable, piBp); 947 1020 if (piBp) 948 1021 *piBp = iBp; 949 LogFlow(("DBGFR3BpSetMmio: returns %Rrc *piBp=%d\n", rc, iBp));1022 LogFlow(("DBGFR3BpSetMmio: returns %Rrc iBp=%d\n", rc, iBp)); 950 1023 return rc; 951 1024 } … … 958 1031 * @param pUVM The user mode VM handle. 959 1032 * @param iBp The id of the breakpoint which should be removed (cleared). 960 * @thread EMT 1033 * @thread EMT(0) 961 1034 * @internal 962 1035 */ … … 987 1060 case DBGFBPTYPE_INT3: 988 1061 rc = dbgfR3BpInt3Disarm(pUVM, pBp); 1062 dbgfR3BpUpdateSearchOptimizations(pVM, DBGFBPTYPE_INT3, &pVM->dbgf.s.Int3); 989 1063 break; 990 1064 … … 1029 1103 * This must be done on EMT. 1030 1104 */ 1031 int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpClear, 2, pUVM, iBp);1105 int rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3BpClear, 2, pUVM, iBp); 1032 1106 LogFlow(("DBGFR3BpClear: returns %Rrc\n", rc)); 1033 1107 return rc; … … 1041 1115 * @param pUVM The user mode VM handle. 1042 1116 * @param iBp The id of the breakpoint which should be enabled. 1043 * @thread EMT 1117 * @thread EMT(0) 1044 1118 * @internal 1045 1119 */ … … 1073 1147 1074 1148 case DBGFBPTYPE_INT3: 1149 dbgfR3BpUpdateSearchOptimizations(pVM, DBGFBPTYPE_INT3, &pVM->dbgf.s.Int3); 1075 1150 rc = dbgfR3BpInt3Arm(pUVM, pBp); 1076 1151 break; … … 1112 1187 * This must be done on EMT. 1113 1188 */ 1114 int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpEnable, 2, pUVM, iBp);1189 int rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3BpEnable, 2, pUVM, iBp); 1115 1190 LogFlow(("DBGFR3BpEnable: returns %Rrc\n", rc)); 1116 1191 return rc; … … 1124 1199 * @param pUVM The user mode VM handle. 1125 1200 * @param iBp The id of the breakpoint which should be disabled. 1126 * @thread EMT 1201 * @thread EMT(0) 1127 1202 * @internal 1128 1203 */ … … 1157 1232 case DBGFBPTYPE_INT3: 1158 1233 rc = dbgfR3BpInt3Disarm(pUVM, pBp); 1234 dbgfR3BpUpdateSearchOptimizations(pVM, DBGFBPTYPE_INT3, &pVM->dbgf.s.Int3); 1159 1235 break; 1160 1236 … … 1193 1269 * This must be done on EMT. 1194 1270 */ 1195 int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpDisable, 2, pUVM, iBp);1271 int rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3BpDisable, 2, pUVM, iBp); 1196 1272 LogFlow(("DBGFR3BpDisable: returns %Rrc\n", rc)); 1197 1273 return rc; … … 1226 1302 { 1227 1303 int rc = pfnCallback(pUVM, pvUser, &pVM->dbgf.s.aHwBreakpoints[i]); 1228 if (RT_FAILURE(rc) )1304 if (RT_FAILURE(rc) || rc == VINF_CALLBACK_RETURN) 1229 1305 return rc; 1230 1306 } … … 1237 1313 { 1238 1314 int rc = pfnCallback(pUVM, pvUser, &pVM->dbgf.s.aBreakpoints[i]); 1239 if (RT_FAILURE(rc) )1315 if (RT_FAILURE(rc) || rc == VINF_CALLBACK_RETURN) 1240 1316 return rc; 1241 1317 } … … 1259 1335 * This must be done on EMT. 1260 1336 */ 1261 int rc = VMR3ReqPriorityCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)dbgfR3BpEnum, 3, pUVM, pfnCallback, pvUser);1337 int rc = VMR3ReqPriorityCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)dbgfR3BpEnum, 3, pUVM, pfnCallback, pvUser); 1262 1338 LogFlow(("DBGFR3BpClear: returns %Rrc\n", rc)); 1263 1339 return rc; -
trunk/src/VBox/VMM/VMMR3/HM.cpp
r58396 r58909 252 252 EXIT_REASON(SVM_EXIT_LDTR_READ ,104, "Read LDTR."), 253 253 EXIT_REASON(SVM_EXIT_TR_READ ,105, "Read TR."), 254 EXIT_REASON(SVM_EXIT_ TR_READ,106, "Write IDTR."),255 EXIT_REASON(SVM_EXIT_ TR_READ,107, "Write GDTR."),256 EXIT_REASON(SVM_EXIT_ TR_READ,108, "Write LDTR."),257 EXIT_REASON(SVM_EXIT_TR_ READ,109, "Write TR."),254 EXIT_REASON(SVM_EXIT_IDTR_WRITE ,106, "Write IDTR."), 255 EXIT_REASON(SVM_EXIT_GDTR_WRITE ,107, "Write GDTR."), 256 EXIT_REASON(SVM_EXIT_LDTR_WRITE ,108, "Write LDTR."), 257 EXIT_REASON(SVM_EXIT_TR_WRITE ,109, "Write TR."), 258 258 EXIT_REASON(SVM_EXIT_RDTSC ,110, "RDTSC instruction."), 259 259 EXIT_REASON(SVM_EXIT_RDPMC ,111, "RDPMC instruction."), … … 287 287 EXIT_REASON(SVM_EXIT_MWAIT ,139, "MWAIT instruction."), 288 288 EXIT_REASON(SVM_EXIT_MWAIT_ARMED ,140, "MWAIT instruction when armed."), 289 EXIT_REASON(SVM_EXIT_XSETBV ,141, "XSETBV instruction."), 289 290 EXIT_REASON(SVM_EXIT_NPF ,1024, "Nested paging fault."), 291 EXIT_REASON(SVM_EXIT_AVIC_INCOMPLETE_IPI,1025, "AVIC incomplete IPI delivery."), 292 EXIT_REASON(SVM_EXIT_AVIC_NOACCEL ,1026, "AVIC unaccelerated register."), 290 293 EXIT_REASON_NIL() 291 294 }; -
trunk/src/VBox/VMM/VMMR3/IOM.cpp
r58903 r58909 1653 1653 * 1654 1654 * @param pVM The cross context VM structure. 1655 * @param cPortIo Number ofarmed I/O port breakpoints.1656 * @param cMmio Number ofarmed MMIO breakpoints.1657 */ 1658 VMMR3_INT_DECL(void) IOMR3NotifyBreakpointCountChange(PVM pVM, unsigned cPortIo, unsigned cMmio)1655 * @param fPortIo True if there are armed I/O port breakpoints. 1656 * @param fMmio True if there are armed MMIO breakpoints. 1657 */ 1658 VMMR3_INT_DECL(void) IOMR3NotifyBreakpointCountChange(PVM pVM, bool fPortIo, bool fMmio) 1659 1659 { 1660 1660 /** @todo I/O breakpoints. */ -
trunk/src/VBox/VMM/VMMRZ/DBGFRZ.cpp
r58903 r58909 57 57 * A breakpoint? 58 58 */ 59 if (uDr6 & (X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3)) 59 AssertCompile(X86_DR6_B0 == 1 && X86_DR6_B1 == 2 && X86_DR6_B2 == 4 && X86_DR6_B3 == 8); 60 if ( (uDr6 & (X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3)) 61 && pVM->dbgf.s.cEnabledHwBreakpoints > 0) 60 62 { 61 Assert(X86_DR6_B0 == 1 && X86_DR6_B1 == 2 && X86_DR6_B2 == 4 && X86_DR6_B3 == 8);62 63 for (unsigned iBp = 0; iBp < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints); iBp++) 63 64 { … … 125 126 * Don't bother if we don't have any breakpoints. 126 127 */ 127 if (pVM->dbgf.s.cBreakpoints > 0) 128 unsigned cToSearch = pVM->dbgf.s.Int3.cToSearch; 129 if (cToSearch > 0) 128 130 { 129 131 RTGCPTR pPc; … … 137 139 AssertRCReturn(rc, rc); 138 140 139 for (unsigned iBp = 0; iBp < RT_ELEMENTS(pVM->dbgf.s.aBreakpoints); iBp++) 141 unsigned iBp = pVM->dbgf.s.Int3.iStartSearch; 142 while (cToSearch-- > 0) 140 143 { 141 if ( 142 && 144 if ( pVM->dbgf.s.aBreakpoints[iBp].u.GCPtr == (RTGCUINTPTR)pPc 145 && pVM->dbgf.s.aBreakpoints[iBp].enmType == DBGFBPTYPE_INT3) 143 146 { 144 147 pVM->dbgf.s.aBreakpoints[iBp].cHits++; … … 152 155 : VINF_EM_DBG_BREAKPOINT; 153 156 } 157 iBp++; 154 158 } 155 159 } -
trunk/src/VBox/VMM/include/DBGFInternal.h
r58903 r58909 170 170 171 171 172 173 /** 174 * Converts a DBGF pointer into a VM pointer. 175 * @returns Pointer to the VM structure the CPUM is part of. 176 * @param pDBGF Pointer to DBGF instance data. 177 */ 178 #define DBGF2VM(pDBGF) ( (PVM)((char*)pDBGF - pDBGF->offVM) ) 172 /** 173 * Breakpoint search optimization. 174 */ 175 typedef struct DBGFBPSEARCHOPT 176 { 177 /** Where to start searching for hits. 178 * (First enabled is #DBGF::aBreakpoints[iStartSearch]). */ 179 uint32_t volatile iStartSearch; 180 /** The number of aBreakpoints entries to search. 181 * (Last enabled is #DBGF::aBreakpoints[iStartSearch + cToSearch - 1]) */ 182 uint32_t volatile cToSearch; 183 } DBGFBPSEARCHOPT; 184 /** Pointer to a breakpoint search optimziation structure. */ 185 typedef DBGFBPSEARCHOPT *PDBGFBPSEARCHOPT; 186 179 187 180 188 … … 184 192 typedef struct DBGF 185 193 { 186 /** Offset to the VM structure. */ 187 int32_t offVM; 188 189 /** Set if we've got armed port I/O breakpoints. */ 190 bool fHasPortIoBps : 1; 191 /** Set if we've got armed memory mapped I/O breakpoints. */ 192 bool fHasMmioBps : 1; 194 /** Bitmap of enabled hardware interrupt breakpoints. */ 195 uint32_t bmHardIntBreakpoints[256 / 32]; 196 /** Bitmap of enabled software interrupt breakpoints. */ 197 uint32_t bmSoftIntBreakpoints[256 / 32]; 198 /** Bitmap of selected events. 199 * This includes non-selectable events too for simplicity, we maintain the 200 * state for some of these, as it may come in handy. */ 201 uint32_t bmSelectedEvents[(DBGFEVENT_END + 31) / 32]; 202 203 /** Enabled hardware interrupt breakpoints. */ 204 uint32_t cHardIntBreakpoints; 205 /** Enabled software interrupt breakpoints. */ 206 uint32_t cSoftIntBreakpoints; 207 208 /** Number of selected events. */ 209 uint32_t cSelectedEvents; 193 210 194 211 /** Debugger Attached flag. … … 208 225 */ 209 226 RTPINGPONG PingPong; 227 RTHCUINTPTR uPtrPadding; /**< Alignment padding. */ 210 228 211 229 /** The Event to the debugger. … … 227 245 DBGFCMDDATA VMMCmdData; 228 246 229 /** The number of hardware breakpoints. */ 230 uint32_t cHwBreakpoints; 231 /** The number of active breakpoints. */ 232 uint32_t cBreakpoints; 247 uint32_t u32Padding; /**< Alignment padding. */ 248 249 /** The number of enabled hardware breakpoints. */ 250 uint8_t cEnabledHwBreakpoints; 251 /** The number of enabled hardware I/O breakpoints. */ 252 uint8_t cEnabledHwIoBreakpoints; 253 uint8_t abPadding[2]; /**< Unused padding space up for grabs. */ 254 233 255 /** Array of hardware breakpoints. (0..3) 234 256 * This is shared among all the CPUs because life is much simpler that way. */ … … 238 260 DBGFBP aBreakpoints[32]; 239 261 262 /** MMIO breakpoint search optimizations. */ 263 DBGFBPSEARCHOPT Mmio; 264 /** I/O port breakpoint search optimizations. */ 265 DBGFBPSEARCHOPT PortIo; 266 /** INT3 breakpoint search optimizations. */ 267 DBGFBPSEARCHOPT Int3; 240 268 } DBGF; 269 AssertCompileMemberAlignment(DBGF, DbgEvent, 8); 270 AssertCompileMemberAlignment(DBGF, aHwBreakpoints, 8); 271 AssertCompileMemberAlignment(DBGF, bmHardIntBreakpoints, 8); 241 272 /** Pointer to DBGF Data. */ 242 273 typedef DBGF *PDBGF; 274 275 276 /** 277 * Event state (for DBGFCPU::aEvents). 278 */ 279 typedef enum DBGFEVENTSTATE 280 { 281 /** Invalid event stack entry. */ 282 DBGFEVENTSTATE_INVALID = 0, 283 /** The current event stack entry. */ 284 DBGFEVENTSTATE_CURRENT, 285 /** Event that should be ignored but hasn't yet actually been ignored. */ 286 DBGFEVENTSTATE_IGNORE, 287 /** Event that has been ignored but may be restored to IGNORE should another 288 * debug event fire before the instruction is completed. */ 289 DBGFEVENTSTATE_RESTORABLE, 290 /** End of valid events. */ 291 DBGFEVENTSTATE_END, 292 /** Make sure we've got a 32-bit type. */ 293 DBGFEVENTSTATE_32BIT_HACK = 0x7fffffff 294 } DBGFEVENTSTATE; 243 295 244 296 … … 259 311 * encounters a breakpoint and returns VINF_EM_DBG_BREAKPOINT. This is 260 312 * currently not used for REM breakpoints because of the lazy coupling 261 * between VBox and REM. */ 313 * between VBox and REM. 314 * 315 * @todo drop this in favor of aEvents! */ 262 316 uint32_t iActiveBp; 263 317 /** Set if we're singlestepping in raw mode. … … 265 319 bool fSingleSteppingRaw; 266 320 267 /** Padding the structure to 16 bytes. */ 268 bool afReserved[7]; 321 /** Alignment padding. */ 322 bool afPadding[3]; 323 324 /** The number of events on the stack (aEvents). 325 * The pending event is the last one (aEvents[cEvents - 1]), but only when 326 * enmState is DBGFEVENTSTATE_CURRENT. */ 327 uint32_t cEvents; 328 /** Events - current, ignoring and ignored. 329 * 330 * We maintain a stack of events in order to try avoid ending up in an infinit 331 * loop when resuming after an event fired. There are cases where we may end 332 * generating additional events before the instruction can be executed 333 * successfully. Like for instance an XCHG on MMIO with separate read and write 334 * breakpoints, or a MOVSB instruction working on breakpointed MMIO as both 335 * source and destination. 336 * 337 * So, when resuming after dropping into the debugger for an event, we convert 338 * the DBGFEVENTSTATE_CURRENT event into a DBGFEVENTSTATE_IGNORE event, leaving 339 * cEvents unchanged. If the event is reported again, we will ignore it and 340 * tell the reporter to continue executing. The event change to the 341 * DBGFEVENTSTATE_RESTORABLE state. 342 * 343 * Currently, the event reporter has to figure out that it is a nested event and 344 * tell DBGF to restore DBGFEVENTSTATE_RESTORABLE events (and keep 345 * DBGFEVENTSTATE_IGNORE, should they happen out of order for some weird 346 * reason). 347 */ 348 struct 349 { 350 /** The event details. */ 351 DBGFEVENT Event; 352 /** The RIP at which this happend (for validating ignoring). */ 353 uint64_t rip; 354 /** The event state. */ 355 DBGFEVENTSTATE enmState; 356 /** Alignment padding. */ 357 uint32_t u32Alignment; 358 } aEvents[3]; 269 359 } DBGFCPU; 360 AssertCompileMemberAlignment(DBGFCPU, aEvents, 8); 361 AssertCompileMemberSizeAlignment(DBGFCPU, aEvents[0], 8); 270 362 /** Pointer to DBGFCPU data. */ 271 363 typedef DBGFCPU *PDBGFCPU; -
trunk/src/VBox/VMM/testcase/tstVMStruct.h
r58781 r58909 209 209 210 210 GEN_CHECK_SIZE(DBGF); 211 GEN_CHECK_OFF(DBGF, offVM); 211 GEN_CHECK_OFF(DBGF, bmHardIntBreakpoints); 212 GEN_CHECK_OFF(DBGF, bmSoftIntBreakpoints); 213 GEN_CHECK_OFF(DBGF, bmSelectedEvents); 214 GEN_CHECK_OFF(DBGF, cHardIntBreakpoints); 215 GEN_CHECK_OFF(DBGF, cSoftIntBreakpoints); 216 GEN_CHECK_OFF(DBGF, cSelectedEvents); 212 217 GEN_CHECK_OFF(DBGF, fAttached); 213 218 GEN_CHECK_OFF(DBGF, fStoppedInHyper); … … 218 223 //GEN_CHECK_OFF(DBGF, pInfoFirst); 219 224 //GEN_CHECK_OFF(DBGF, InfoCritSect); 220 GEN_CHECK_OFF(DBGF, c HwBreakpoints);221 GEN_CHECK_OFF(DBGF, c Breakpoints);225 GEN_CHECK_OFF(DBGF, cEnabledHwBreakpoints); 226 GEN_CHECK_OFF(DBGF, cEnabledHwIoBreakpoints); 222 227 GEN_CHECK_OFF(DBGF, aHwBreakpoints); 223 228 GEN_CHECK_OFF(DBGF, aBreakpoints); 229 GEN_CHECK_OFF(DBGF, Mmio); 230 GEN_CHECK_OFF(DBGF, PortIo); 231 GEN_CHECK_OFF(DBGF, Int3); 224 232 //GEN_CHECK_OFF(DBGF, hAsDbLock); 225 233 //GEN_CHECK_OFF(DBGF, hRegDbLock); … … 231 239 GEN_CHECK_OFF(DBGFCPU, iActiveBp); 232 240 GEN_CHECK_OFF(DBGFCPU, fSingleSteppingRaw); 241 GEN_CHECK_OFF(DBGFCPU, cEvents); 242 GEN_CHECK_OFF(DBGFCPU, aEvents); 243 GEN_CHECK_OFF(DBGFCPU, aEvents[1]); 244 GEN_CHECK_OFF(DBGFCPU, aEvents[1].Event); 245 GEN_CHECK_OFF(DBGFCPU, aEvents[1].Event.enmCtx); 246 GEN_CHECK_OFF(DBGFCPU, aEvents[1].Event.enmType); 247 GEN_CHECK_OFF(DBGFCPU, aEvents[1].Event.u.Bp.iBp); 248 GEN_CHECK_OFF(DBGFCPU, aEvents[1].rip); 249 GEN_CHECK_OFF(DBGFCPU, aEvents[1].enmState); 233 250 //GEN_CHECK_OFF(DBGFCPU, pGuestRegSet); 234 251 //GEN_CHECK_OFF(DBGFCPU, pHyperRegSet);
Note:
See TracChangeset
for help on using the changeset viewer.