Changeset 97705 in vbox for trunk/src/VBox/VMM/VMMAll
- Timestamp:
- Nov 29, 2022 2:11:49 PM (2 years ago)
- Location:
- trunk/src/VBox/VMM/VMMAll
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/DBGFAll.cpp
r97699 r97705 229 229 uint32_t fMatched = 0; 230 230 uint32_t fEnabled = 0; 231 for (unsigned iBp = 0, iBpMask = 1; iBp < 4; iBp++, iBpMask <<= 1)231 for (unsigned iBp = 0, uBpMask = 1; iBp < 4; iBp++, uBpMask <<= 1) 232 232 if (X86_DR7_IS_EO_CFG(fDr7, iBp)) 233 233 { 234 234 if (fDr7 & X86_DR7_L_G(iBp)) 235 fEnabled |= iBpMask;235 fEnabled |= uBpMask; 236 236 if (pVCpu->cpum.GstCtx.dr[iBp] == GCPtrPC) 237 fMatched |= iBpMask;237 fMatched |= uBpMask; 238 238 } 239 239 if (!(fEnabled & fMatched)) … … 361 361 362 362 /** 363 * Checks I/O access for guest or hypervisor hardware breakpoints. 364 * 365 * Caller must make sure DR0-3 and DR7 are present in the CPU context before 366 * calling this function. 367 * 368 * @returns CPUMCTX_DBG_DBGF_BP, CPUMCTX_DBG_HIT_DRX_MASK, or 0 (no match). 369 * 370 * @param pVM The cross context VM structure. 371 * @param pVCpu The cross context virtual CPU structure of the calling EMT. 372 * @param uIoPort The I/O port being accessed. 373 * @param cbValue The size/width of the access, in bytes. 374 */ 375 VMM_INT_DECL(uint32_t) DBGFBpCheckIo2(PVMCC pVM, PVMCPUCC pVCpu, RTIOPORT uIoPort, uint8_t cbValue) 376 { 377 uint32_t const uIoPortFirst = uIoPort; 378 uint32_t const uIoPortLast = uIoPortFirst + cbValue - 1; 379 380 /* 381 * Check hyper breakpoints first as the VMM debugger has priority over 382 * the guest. 383 */ 384 if (pVM->dbgf.s.cEnabledHwIoBreakpoints > 0) 385 for (unsigned iBp = 0; iBp < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints); iBp++) 386 { 387 if ( pVM->dbgf.s.aHwBreakpoints[iBp].fType == X86_DR7_RW_IO 388 && pVM->dbgf.s.aHwBreakpoints[iBp].fEnabled 389 && pVM->dbgf.s.aHwBreakpoints[iBp].hBp != NIL_DBGFBP) 390 { 391 uint8_t cbReg = pVM->dbgf.s.aHwBreakpoints[iBp].cb; Assert(RT_IS_POWER_OF_TWO(cbReg)); 392 uint64_t uDrXFirst = pVM->dbgf.s.aHwBreakpoints[iBp].GCPtr & ~(uint64_t)(cbReg - 1); 393 uint64_t uDrXLast = uDrXFirst + cbReg - 1; 394 if (uDrXFirst <= uIoPortLast && uDrXLast >= uIoPortFirst) 395 { 396 /* (See also DBGFRZTrap01Handler.) */ 397 pVCpu->dbgf.s.hBpActive = pVM->dbgf.s.aHwBreakpoints[iBp].hBp; 398 pVCpu->dbgf.s.fSingleSteppingRaw = false; 399 400 LogFlow(("DBGFBpCheckIo2: hit hw breakpoint %d at %04x:%RGv (iop %#x L %u)\n", 401 iBp, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, uIoPort, cbValue)); 402 return CPUMCTX_DBG_DBGF_BP; 403 } 404 } 405 } 406 407 /* 408 * Check the guest. 409 */ 410 uint32_t const fDr7 = pVCpu->cpum.GstCtx.dr[7]; 411 if ( (fDr7 & X86_DR7_ENABLED_MASK) 412 && X86_DR7_ANY_RW_IO(fDr7) 413 && (pVCpu->cpum.GstCtx.cr4 & X86_CR4_DE) ) 414 { 415 uint32_t fEnabled = 0; 416 uint32_t fMatched = 0; 417 for (unsigned iBp = 0, uBpMask = 1; iBp < 4; iBp++, uBpMask <<= 1) 418 { 419 if (fDr7 & X86_DR7_L_G(iBp)) 420 fEnabled |= uBpMask; 421 if (X86_DR7_GET_RW(fDr7, iBp) == X86_DR7_RW_IO) 422 { 423 /* ASSUME the breakpoint and the I/O width qualifier uses the same encoding (1 2 x 4). */ 424 static uint8_t const s_abInvAlign[4] = { 0, 1, 7, 3 }; 425 uint8_t const cbInvAlign = s_abInvAlign[X86_DR7_GET_LEN(fDr7, iBp)]; 426 uint64_t const uDrXFirst = pVCpu->cpum.GstCtx.dr[iBp] & ~(uint64_t)cbInvAlign; 427 uint64_t const uDrXLast = uDrXFirst + cbInvAlign; 428 if (uDrXFirst <= uIoPortLast && uDrXLast >= uIoPortFirst) 429 fMatched |= uBpMask; 430 } 431 } 432 if (fEnabled & fMatched) 433 { 434 LogFlow(("DBGFBpCheckIo2: hit hw breakpoint %#x at %04x:%RGv (iop %#x L %u)\n", 435 fMatched, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, uIoPort, cbValue)); 436 return fMatched << CPUMCTX_DBG_HIT_DRX_SHIFT; 437 } 438 } 439 440 return 0; 441 } 442 443 444 /** 363 445 * Returns the single stepping state for a virtual CPU. 364 446 * -
trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp
r97694 r97705 7346 7346 if (rcStrict != VINF_SUCCESS) 7347 7347 iemSetPassUpStatus(pVCpu, rcStrict); 7348 7349 /* 7350 * Check for I/O breakpoints before we complete the instruction. 7351 */ 7352 uint32_t const fDr7 = pVCpu->cpum.GstCtx.dr[7]; 7353 if (RT_UNLIKELY( ( ( (fDr7 & X86_DR7_ENABLED_MASK) 7354 && X86_DR7_ANY_RW_IO(fDr7) 7355 && (pVCpu->cpum.GstCtx.cr4 & X86_CR4_DE)) 7356 || pVM->dbgf.ro.cEnabledHwIoBreakpoints > 0) 7357 && rcStrict == VINF_SUCCESS)) 7358 { 7359 IEM_CTX_IMPORT_RET(pVCpu, CPUMCTX_EXTRN_DR0_DR3 | CPUMCTX_EXTRN_DR6); 7360 pVCpu->cpum.GstCtx.eflags.uBoth |= DBGFBpCheckIo2(pVM, pVCpu, u16Port, cbReg); 7361 } 7362 7348 7363 rcStrict = iemRegAddToRipAndFinishingClearingRF(pVCpu, cbInstr); 7349 7350 /*7351 * Check for I/O breakpoints.7352 */7353 /** @todo this should set a internal flag and be raised by7354 * iemRegAddToRipAndFinishingClearingRF! */7355 uint32_t const uDr7 = pVCpu->cpum.GstCtx.dr[7];7356 if (RT_UNLIKELY( ( ( (uDr7 & X86_DR7_ENABLED_MASK)7357 && X86_DR7_ANY_RW_IO(uDr7)7358 && (pVCpu->cpum.GstCtx.cr4 & X86_CR4_DE))7359 || DBGFBpIsHwIoArmed(pVM))7360 && rcStrict == VINF_SUCCESS))7361 {7362 IEM_CTX_IMPORT_RET(pVCpu, CPUMCTX_EXTRN_DR0_DR3 | CPUMCTX_EXTRN_DR6);7363 rcStrict = DBGFBpCheckIo(pVM, pVCpu, IEM_GET_CTX(pVCpu), u16Port, cbReg);7364 if (rcStrict == VINF_EM_RAW_GUEST_TRAP)7365 rcStrict = iemRaiseDebugException(pVCpu);7366 }7367 7364 } 7368 7365 … … 7458 7455 if (rcStrict != VINF_SUCCESS) 7459 7456 iemSetPassUpStatus(pVCpu, rcStrict); 7457 7458 /* 7459 * Check for I/O breakpoints before we complete the instruction. 7460 */ 7461 uint32_t const fDr7 = pVCpu->cpum.GstCtx.dr[7]; 7462 if (RT_UNLIKELY( ( ( (fDr7 & X86_DR7_ENABLED_MASK) 7463 && X86_DR7_ANY_RW_IO(fDr7) 7464 && (pVCpu->cpum.GstCtx.cr4 & X86_CR4_DE)) 7465 || pVM->dbgf.ro.cEnabledHwIoBreakpoints > 0) 7466 && rcStrict == VINF_SUCCESS)) 7467 { 7468 IEM_CTX_IMPORT_RET(pVCpu, CPUMCTX_EXTRN_DR0_DR3 | CPUMCTX_EXTRN_DR6); 7469 pVCpu->cpum.GstCtx.eflags.uBoth |= DBGFBpCheckIo2(pVM, pVCpu, u16Port, cbReg); 7470 } 7471 7460 7472 rcStrict = iemRegAddToRipAndFinishingClearingRF(pVCpu, cbInstr); 7461 7462 /*7463 * Check for I/O breakpoints.7464 */7465 /** @todo this should set a internal flag and be raised by7466 * iemRegAddToRipAndFinishingClearingRF! */7467 uint32_t const uDr7 = pVCpu->cpum.GstCtx.dr[7];7468 if (RT_UNLIKELY( ( ( (uDr7 & X86_DR7_ENABLED_MASK)7469 && X86_DR7_ANY_RW_IO(uDr7)7470 && (pVCpu->cpum.GstCtx.cr4 & X86_CR4_DE))7471 || DBGFBpIsHwIoArmed(pVM))7472 && rcStrict == VINF_SUCCESS))7473 {7474 IEM_CTX_IMPORT_RET(pVCpu, CPUMCTX_EXTRN_DR0_DR3 | CPUMCTX_EXTRN_DR6);7475 rcStrict = DBGFBpCheckIo(pVM, pVCpu, IEM_GET_CTX(pVCpu), u16Port, cbReg);7476 if (rcStrict == VINF_EM_RAW_GUEST_TRAP)7477 rcStrict = iemRaiseDebugException(pVCpu);7478 }7479 7473 } 7480 7474 return rcStrict;
Note:
See TracChangeset
for help on using the changeset viewer.