VirtualBox

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


Ignore:
Timestamp:
Jun 28, 2021 8:16:29 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
145382
Message:

VMM/DBGFBp: Continue work on I/O breakpoints, bugref:9837

  • Breakpoint owners now have a dedicated callback for I/O breakpoints which can convey information about the access like direction, size, address/port and value so the callback doesn't has to disassemble the instruction to get at those values.
  • Port I/O breakpoints are now mostly complete on the DBGF side and need to be hooked up to IOM next.
File:
1 edited

Legend:

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

    r87776 r89924  
    169169    if (pBpOwnerR0)
    170170    {
     171        AssertReturn(pBpOwnerR0->pfnBpIoHitR0, VERR_DBGF_BP_IPE_1);
     172
    171173        VBOXSTRICTRC rcStrict = VINF_SUCCESS;
    172174
     
    234236
    235237/**
     238 * Executes the actions associated with the given port I/O breakpoint.
     239 *
     240 * @returns VBox status code.
     241 * @param   pVM         The cross context VM structure.
     242 * @param   pVCpu       The cross context virtual CPU structure.
     243 * @param   fBefore     Flag whether the check is done before the access is carried out,
     244 *                      false if it is done after the access.
     245 * @param   fAccess     Access flags, see DBGFBPIOACCESS_XXX.
     246 * @param   uAddr       The address of the access, for port I/O this will hold the port number.
     247 * @param   uValue      The value read or written (the value for reads is only valid when DBGF_BP_F_HIT_EXEC_AFTER is set).
     248 * @param   hBp         The breakpoint handle which hit.
     249 * @param   pBp         The shared breakpoint state.
     250 * @param   pBpR0       The ring-0 only breakpoint state.
     251 */
     252#ifdef IN_RING0
     253DECLINLINE(VBOXSTRICTRC) dbgfBpPortIoHit(PVMCC pVM, PVMCPU pVCpu, bool fBefore, uint32_t fAccess, uint64_t uAddr, uint64_t uValue,
     254                                         DBGFBP hBp, PDBGFBPINT pBp, PDBGFBPINTR0 pBpR0)
     255#else
     256DECLINLINE(VBOXSTRICTRC) dbgfBpPortIoHit(PVMCC pVM, PVMCPU pVCpu, bool fBefore, uint32_t fAccess, uint64_t uAddr, uint64_t uValue,
     257                                         DBGFBP hBp, PDBGFBPINT pBp)
     258#endif
     259{
     260    ASMAtomicIncU64(&pBp->Pub.cHits);
     261
     262    VBOXSTRICTRC rcStrict = VINF_EM_DBG_BREAKPOINT;
     263#ifdef IN_RING0
     264    PCDBGFBPOWNERINTR0 pBpOwnerR0 = dbgfR0BpOwnerGetByHnd(pVM,
     265                                                            pBpR0->fInUse
     266                                                          ? pBpR0->hOwner
     267                                                          : NIL_DBGFBPOWNER);
     268    if (pBpOwnerR0)
     269    {
     270        AssertReturn(pBpOwnerR0->pfnBpIoHitR0, VERR_DBGF_BP_IPE_1);
     271        rcStrict = pBpOwnerR0->pfnBpIoHitR0(pVM, pVCpu->idCpuUnsafe, pBpR0->pvUserR0, hBp, &pBp->Pub,
     272                                              fBefore
     273                                            ? DBGF_BP_F_HIT_EXEC_BEFORE
     274                                            : DBGF_BP_F_HIT_EXEC_AFTER,
     275                                            fAccess, uAddr, uValue);
     276    }
     277    else
     278    {
     279        pVCpu->dbgf.s.fBpInvokeOwnerCallback = true; /* Need to check this for ring-3 only owners. */
     280        pVCpu->dbgf.s.hBpActive              = hBp;
     281        pVCpu->dbgf.s.fBpIoActive            = true;
     282        pVCpu->dbgf.s.fBpIoBefore            = fBefore;
     283        pVCpu->dbgf.s.uBpIoAddress           = uAddr;
     284        pVCpu->dbgf.s.fBpIoAccess            = fAccess;
     285        pVCpu->dbgf.s.uBpIoValue             = uValue;
     286    }
     287#else
     288    /* Resolve owner (can be NIL_DBGFBPOWNER) and invoke callback if there is one. */
     289    if (pBp->Pub.hOwner != NIL_DBGFBPOWNER)
     290    {
     291        PCDBGFBPOWNERINT pBpOwner = dbgfR3BpOwnerGetByHnd(pVM->pUVM, pBp->Pub.hOwner);
     292        if (pBpOwner)
     293        {
     294            AssertReturn(pBpOwner->pfnBpIoHitR3, VERR_DBGF_BP_IPE_1);
     295            rcStrict = pBpOwner->pfnBpIoHitR3(pVM, pVCpu->idCpu, pBp->pvUserR3, hBp, &pBp->Pub,
     296                                                fBefore
     297                                              ? DBGF_BP_F_HIT_EXEC_BEFORE
     298                                              : DBGF_BP_F_HIT_EXEC_AFTER,
     299                                              fAccess, uAddr, uValue);
     300        }
     301    }
     302#endif
     303    if (   rcStrict == VINF_DBGF_BP_HALT
     304        || rcStrict == VINF_DBGF_R3_BP_OWNER_DEFER)
     305    {
     306        pVCpu->dbgf.s.hBpActive = hBp;
     307        if (rcStrict == VINF_DBGF_R3_BP_OWNER_DEFER)
     308            pVCpu->dbgf.s.fBpInvokeOwnerCallback = true;
     309        else
     310            pVCpu->dbgf.s.fBpInvokeOwnerCallback = false;
     311        rcStrict = VINF_EM_DBG_BREAKPOINT;
     312    }
     313    else if (   rcStrict != VINF_SUCCESS
     314             && rcStrict != VINF_EM_DBG_BREAKPOINT)
     315        rcStrict = VERR_DBGF_BP_OWNER_CALLBACK_WRONG_STATUS; /* Guru meditation. */
     316
     317    return rcStrict;
     318}
     319
     320
     321/**
    236322 * Walks the L2 table starting at the given root index searching for the given key.
    237323 *
     
    294380
    295381    return VERR_DBGF_BP_L2_LOOKUP_FAILED;
     382}
     383
     384
     385/**
     386 * Checks whether there is a port I/O breakpoint for the given range and access size.
     387 *
     388 * @returns VBox status code.
     389 * @retval  VINF_EM_DBG_BREAKPOINT means there is a breakpoint pending.
     390 * @retval  VINF_SUCCESS means everything is fine to continue.
     391 * @retval  anything else means a fatal error causing a guru meditation.
     392 *
     393 * @param   pVM             The current context VM structure.
     394 * @param   pVCpu           The cross context virtual CPU structure.
     395 * @param   uIoPort         The I/O port being accessed.
     396 * @param   fAccess         Appropriate DBGFBPIOACCESS_XXX.
     397 * @param   uValue          The value being written to or read from the device
     398 *                          (The value is only valid for a read when the
     399 *                          call is made after the access, writes are always valid).
     400 * @param   fBefore         Flag whether the check is done before the access is carried out,
     401 *                          false if it is done after the access.
     402 */
     403VMM_INT_DECL(VBOXSTRICTRC) DBGFBpCheckPortIo(PVMCC pVM, PVMCPU pVCpu, RTIOPORT uIoPort,
     404                                             uint32_t fAccess, uint32_t uValue, bool fBefore)
     405{
     406    RT_NOREF(uValue); /** @todo Trigger only on specific values. */
     407
     408    /* Don't trigger in single stepping mode. */
     409    if (pVCpu->dbgf.s.fSingleSteppingRaw)
     410        return VINF_SUCCESS;
     411
     412#if defined(IN_RING0)
     413    uint32_t volatile *paBpLocPortIo = pVM->dbgfr0.s.CTX_SUFF(paBpLocPortIo);
     414#elif defined(IN_RING3)
     415    PUVM pUVM = pVM->pUVM;
     416    uint32_t volatile *paBpLocPortIo = pUVM->dbgf.s.CTX_SUFF(paBpLocPortIo);
     417#else
     418# error "Unsupported host context"
     419#endif
     420    if (paBpLocPortIo)
     421    {
     422        const uint32_t u32Entry = ASMAtomicReadU32(&paBpLocPortIo[uIoPort]);
     423        if (u32Entry != DBGF_BP_INT3_L1_ENTRY_TYPE_NULL)
     424        {
     425            uint8_t u8Type = DBGF_BP_INT3_L1_ENTRY_GET_TYPE(u32Entry);
     426            if (RT_LIKELY(u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_BP_HND))
     427            {
     428                DBGFBP hBp = DBGF_BP_INT3_L1_ENTRY_GET_BP_HND(u32Entry);
     429
     430                /* Query the internal breakpoint state from the handle. */
     431#ifdef IN_RING3
     432                PDBGFBPINT   pBp = dbgfBpGetByHnd(pVM, hBp);
     433#else
     434                PDBGFBPINTR0 pBpR0 = NULL;
     435                PDBGFBPINT   pBp = dbgfBpGetByHnd(pVM, hBp, &pBpR0);
     436#endif
     437                if (   pBp
     438                    && DBGF_BP_PUB_GET_TYPE(&pBp->Pub) == DBGFBPTYPE_PORT_IO)
     439                {
     440                    if (   uIoPort >= pBp->Pub.u.PortIo.uPort
     441                        && uIoPort < pBp->Pub.u.PortIo.uPort + pBp->Pub.u.PortIo.cPorts
     442                        && pBp->Pub.u.PortIo.fAccess & fAccess
     443                        && (   (   fBefore
     444                                && DBGF_BP_PUB_IS_EXEC_BEFORE(&pBp->Pub))
     445                            || (   !fBefore
     446                                && DBGF_BP_PUB_IS_EXEC_AFTER(&pBp->Pub))))
     447#ifdef IN_RING3
     448                        return dbgfBpPortIoHit(pVM, pVCpu, fBefore, fAccess, uIoPort, uValue, hBp, pBp);
     449#else
     450                        return dbgfBpPortIoHit(pVM, pVCpu, fBefore, fAccess, uIoPort, uValue, hBp, pBp, pBpR0);
     451#endif
     452                    /* else: No matching port I/O breakpoint. */
     453                }
     454                else /* Invalid breakpoint handle or not an port I/O breakpoint. */
     455                    return VERR_DBGF_BP_L1_LOOKUP_FAILED;
     456            }
     457            else /* Some invalid type. */
     458                return VERR_DBGF_BP_L1_LOOKUP_FAILED;
     459        }
     460    }
     461
     462    return VINF_SUCCESS;
    296463}
    297464
Note: See TracChangeset for help on using the changeset viewer.

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