VirtualBox

Changeset 97705 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Nov 29, 2022 2:11:49 PM (2 years ago)
Author:
vboxsync
Message:

VMM/IEM,DBGF,CPUM: Do debugger I/O breakpoints via the internal EFLAGS bits too. Seems we might need two bits, so had to shift the internal bits down from 24 to 22. bugref:9898

Location:
trunk/src/VBox/VMM/VMMAll
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/DBGFAll.cpp

    r97699 r97705  
    229229        uint32_t fMatched = 0;
    230230        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)
    232232            if (X86_DR7_IS_EO_CFG(fDr7, iBp))
    233233            {
    234234                if (fDr7 & X86_DR7_L_G(iBp))
    235                     fEnabled |= iBpMask;
     235                    fEnabled |= uBpMask;
    236236                if (pVCpu->cpum.GstCtx.dr[iBp] == GCPtrPC)
    237                     fMatched |= iBpMask;
     237                    fMatched |= uBpMask;
    238238            }
    239239        if (!(fEnabled & fMatched))
     
    361361
    362362/**
     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 */
     375VMM_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/**
    363445 * Returns the single stepping state for a virtual CPU.
    364446 *
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp

    r97694 r97705  
    73467346        if (rcStrict != VINF_SUCCESS)
    73477347            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
    73487363        rcStrict = iemRegAddToRipAndFinishingClearingRF(pVCpu, cbInstr);
    7349 
    7350         /*
    7351          * Check for I/O breakpoints.
    7352          */
    7353         /** @todo this should set a internal flag and be raised by
    7354          *        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         }
    73677364    }
    73687365
     
    74587455        if (rcStrict != VINF_SUCCESS)
    74597456            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
    74607472        rcStrict = iemRegAddToRipAndFinishingClearingRF(pVCpu, cbInstr);
    7461 
    7462         /*
    7463          * Check for I/O breakpoints.
    7464          */
    7465         /** @todo this should set a internal flag and be raised by
    7466          *        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         }
    74797473    }
    74807474    return rcStrict;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette