VirtualBox

儲存庫 vbox 的更動 89924


忽略:
時間撮記:
2021-6-28 上午08:16:29 (4 年 以前)
作者:
vboxsync
svn:sync-xref-src-repo-rev:
145382
訊息:

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.
位置:
trunk
檔案:
修改 7 筆資料

圖例:

未更動
新增
刪除
  • trunk/include/VBox/vmm/dbgf.h

    r89912 r89924  
    854854/** All kind of access (read, write, all sizes). */
    855855#define DBGFBPIOACCESS_ALL                  UINT32_C(0x00001f1f)
     856/** All kind of access for MMIO (read, write, all sizes). */
     857#define DBGFBPIOACCESS_ALL_MMIO             DBGFBPIOACCESS_ALL
     858/** All kind of access (read, write, all sizes). */
     859#define DBGFBPIOACCESS_ALL_PORT_IO          UINT32_C(0x00000303)
    856860
    857861/** The acceptable mask for I/O ports.   */
     
    970974 * after the instruction causing the breakpoint to hit was executed. */
    971975#define DBGF_BP_F_HIT_EXEC_AFTER            RT_BIT(2)
     976/** The acceptable flags mask.   */
     977#define DBGF_BP_F_VALID_MASK                UINT32_C(0x00000007)
    972978/** @} */
    973979
     
    9981004
    9991005
     1006/**
     1007 * I/O breakpoint hit handler.
     1008 *
     1009 * @returns Strict VBox status code.
     1010 * @retval  VINF_SUCCESS if the breakpoint was handled and guest execution can resume.
     1011 * @retval  VINF_DBGF_BP_HALT if guest execution should be stopped and the debugger should be invoked.
     1012 * @retval  VINF_DBGF_R3_BP_OWNER_DEFER return to ring-3 and invoke the owner callback there again.
     1013 *
     1014 * @param   pVM         The cross-context VM structure pointer.
     1015 * @param   idCpu       ID of the vCPU triggering the breakpoint.
     1016 * @param   pvUserBp    User argument of the set breakpoint.
     1017 * @param   hBp         The breakpoint handle.
     1018 * @param   pBpPub      Pointer to the readonly public state of the breakpoint.
     1019 * @param   fFlags      Flags indicating when the handler was called (DBGF_BP_F_HIT_EXEC_BEFORE vs DBGF_BP_F_HIT_EXEC_AFTER).
     1020 * @param   fAccess     Access flags, see DBGFBPIOACCESS_XXX.
     1021 * @param   uAddr       The address of the access, for port I/O this will hold the port number.
     1022 * @param   uValue      The value read or written (the value for reads is only valid when DBGF_BP_F_HIT_EXEC_AFTER is set).
     1023 *
     1024 * @remarks The handler is called on the EMT of vCPU triggering the breakpoint and no locks are held.
     1025 * @remarks Any status code returned other than the ones mentioned will send the VM straight into a
     1026 *          guru meditation.
     1027 */
     1028typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNDBGFBPIOHIT,(PVM pVM, VMCPUID idCpu, void *pvUserBp, DBGFBP hBp, PCDBGFBPPUB pBpPub,
     1029                                                      uint16_t fFlags, uint32_t fAccess, uint64_t uAddr, uint64_t uValue));
     1030/** Pointer to a FNDBGFBPIOHIT(). */
     1031typedef FNDBGFBPIOHIT *PFNDBGFBPIOHIT;
     1032
     1033
    10001034#ifdef IN_RING3
    10011035/** @defgroup grp_dbgf_bp_r3    The DBGF Breakpoint Host Context Ring-3 API
    10021036 * @{ */
    1003 VMMR3DECL(int) DBGFR3BpOwnerCreate(PUVM pUVM, PFNDBGFBPHIT pfnBpHit, PDBGFBPOWNER phBpOwner);
     1037VMMR3DECL(int) DBGFR3BpOwnerCreate(PUVM pUVM, PFNDBGFBPHIT pfnBpHit, PFNDBGFBPIOHIT pfnBpIoHit, PDBGFBPOWNER phBpOwner);
    10041038VMMR3DECL(int) DBGFR3BpOwnerDestroy(PUVM pUVM, DBGFBPOWNER hBpOwner);
    10051039
     
    10261060VMMR3DECL(int) DBGFR3BpSetMmioEx(PUVM pUVM, DBGFBPOWNER hOwner, void *pvUser,
    10271061                                 RTGCPHYS GCPhys, uint32_t cb, uint32_t fAccess,
    1028                                  uint64_t iHitTrigger, uint64_t iHitDisable, PDBGFBP phBp);
     1062                                 uint32_t fFlags, uint64_t iHitTrigger, uint64_t iHitDisable, PDBGFBP phBp);
    10291063VMMR3DECL(int) DBGFR3BpClear(PUVM pUVM, DBGFBP hBp);
    10301064VMMR3DECL(int) DBGFR3BpEnable(PUVM pUVM, DBGFBP hBp);
     
    10581092VMMR0_INT_DECL(void) DBGFR0CleanupVM(PGVM pGVM);
    10591093
    1060 VMMR0_INT_DECL(int)  DBGFR0BpOwnerSetUpContext(PGVM pGVM, DBGFBPOWNER hBpOwner, PFNDBGFBPHIT pfnBpHit);
     1094VMMR0_INT_DECL(int)  DBGFR0BpOwnerSetUpContext(PGVM pGVM, DBGFBPOWNER hBpOwner, PFNDBGFBPHIT pfnBpHit, PFNDBGFBPIOHIT pfnBpIoHit);
    10611095VMMR0_INT_DECL(int)  DBGFR0BpOwnerDestroyContext(PGVM pGVM, DBGFBPOWNER hBpOwner);
    10621096
     
    10761110VMM_INT_DECL(bool)          DBGFIsStepping(PVMCPU pVCpu);
    10771111VMM_INT_DECL(VBOXSTRICTRC)  DBGFBpCheckIo(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, RTIOPORT uIoPort, uint8_t cbValue);
     1112VMM_INT_DECL(VBOXSTRICTRC)  DBGFBpCheckPortIo(PVMCC pVM, PVMCPU pVCpu, RTIOPORT uIoPort,
     1113                                              uint32_t fAccess, uint32_t uValue, bool fBefore);
    10781114VMM_INT_DECL(VBOXSTRICTRC)  DBGFEventGenericWithArgs(PVM pVM, PVMCPU pVCpu, DBGFEVENTTYPE enmEvent, DBGFEVENTCTX enmCtx,
    10791115                                                     unsigned cArgs, ...);
  • 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
  • trunk/src/VBox/VMM/VMMR0/DBGFR0Bp.cpp

    r89912 r89924  
    496496    AssertRCReturn(rc, rc);
    497497
    498     AssertReturn(!pGVM->dbgfr0.s.fInit, VERR_WRONG_ORDER);
     498    AssertReturn(pGVM->dbgfr0.s.fInit, VERR_WRONG_ORDER);
    499499    AssertReturn(!pGVM->dbgfr0.s.paBpLocPortIoR0, VERR_WRONG_ORDER);
    500500
  • trunk/src/VBox/VMM/VMMR3/DBGFR3Bp.cpp

    r89913 r89924  
    9191 * |     .      |            |     .     |
    9292 * +------------+            +-----------+
    93  *                            L2 idx AVL
     93 *                            L2 idx BST
    9494 * @endverbatim
    9595 *
     
    107107 *              matching the lowest 16bits and the search must continue in the L2 table with the
    108108 *              remaining 28bits acting as an index into the L2 table indicating the search root.
    109  *     -# The L2 table consists of multiple index based AVL trees, there is one for each reference
     109 *     -# The L2 table consists of multiple index based binary search trees, there is one for each reference
    110110 *        from the L1 table. The key for the table are the upper 6 bytes of the breakpoint address
    111111 *        used for searching. This tree is traversed until either a matching address is found and
     
    133133 *   are always mapped into ring-0 and ring-3 with different base addresses.
    134134 * - Efficent breakpoint allocation is done by having a global bitmap indicating free
    135  *   and occupied breakpoint entries. Same applies for the L2 AVL table.
     135 *   and occupied breakpoint entries. Same applies for the L2 BST table.
    136136 * - Special care must be taken when modifying the L1 and L2 tables as other EMTs
    137137 *   might still access it (want to try a lockless approach first using
     
    139139 * - Each BP entry is supposed to be 64 byte big and each chunk should contain 65536
    140140 *   breakpoints which results in 4MiB for each chunk plus the allocation bitmap.
    141  * - ring-0 has to take special care when traversing the L2 AVL tree to not run into cycles
     141 * - ring-0 has to take special care when traversing the L2 BST to not run into cycles
    142142 *   and do strict bounds checking before accessing anything. The L1 and L2 table
    143143 *   are written to from ring-3 only. Same goes for the breakpoint table with the
     
    463463
    464464/**
    465  * Returns the internal breakpoint owner state for the given handle.
    466  *
    467  * @returns Pointer to the internal breakpoint owner state or NULL if the handle is invalid.
    468  * @param   pUVM                The user mode VM handle.
    469  * @param   hBpOwner            The breakpoint owner handle to resolve.
    470  */
    471 DECLINLINE(PDBGFBPOWNERINT) dbgfR3BpOwnerGetByHnd(PUVM pUVM, DBGFBPOWNER hBpOwner)
    472 {
    473     AssertReturn(hBpOwner < DBGF_BP_OWNER_COUNT_MAX, NULL);
    474     AssertPtrReturn(pUVM->dbgf.s.pbmBpOwnersAllocR3, NULL);
    475 
    476     AssertReturn(ASMBitTest(pUVM->dbgf.s.pbmBpOwnersAllocR3, hBpOwner), NULL);
    477     return &pUVM->dbgf.s.paBpOwnersR3[hBpOwner];
    478 }
    479 
    480 
    481 /**
    482465 * Retains the given breakpoint owner handle for use.
    483466 *
     
    486469 * @param   pUVM                The user mode VM handle.
    487470 * @param   hBpOwner            The breakpoint owner handle to retain, NIL_DBGFOWNER is accepted without doing anything.
    488  */
    489 DECLINLINE(int) dbgfR3BpOwnerRetain(PUVM pUVM, DBGFBPOWNER hBpOwner)
     471 * @param   fIo                 Flag whether the owner must have the I/O handler set because it used by an I/O breakpoint.
     472 */
     473DECLINLINE(int) dbgfR3BpOwnerRetain(PUVM pUVM, DBGFBPOWNER hBpOwner, bool fIo)
    490474{
    491475    if (hBpOwner == NIL_DBGFBPOWNER)
     
    495479    if (pBpOwner)
    496480    {
     481        AssertReturn (   (   fIo
     482                          && pBpOwner->pfnBpIoHitR3)
     483                      ||  (   !fIo
     484                           && pBpOwner->pfnBpHitR3),
     485                      VERR_INVALID_HANDLE);
    497486        ASMAtomicIncU32(&pBpOwner->cRefs);
    498487        return VINF_SUCCESS;
     
    650639                         PDBGFBPINT *ppBp)
    651640{
    652     int rc = dbgfR3BpOwnerRetain(pUVM, hOwner);
     641    bool fIo =    enmType == DBGFBPTYPE_PORT_IO
     642               || enmType == DBGFBPTYPE_MMIO;
     643    int rc = dbgfR3BpOwnerRetain(pUVM, hOwner, fIo);
    653644    if (RT_FAILURE(rc))
    654645        return rc;
     
    16821673            AssertReturn(u8Type == DBGF_BP_INT3_L1_ENTRY_TYPE_BP_HND, VERR_DBGF_BP_IPE_7);
    16831674
    1684             bool fXchg = ASMAtomicCmpXchgU32(&pUVM->dbgf.s.paBpLocL1R3[idxPort], DBGF_BP_INT3_L1_ENTRY_TYPE_NULL, u32Entry);
     1675            bool fXchg = ASMAtomicCmpXchgU32(&pUVM->dbgf.s.paBpLocPortIoR3[idxPort], DBGF_BP_INT3_L1_ENTRY_TYPE_NULL, u32Entry);
    16851676            Assert(fXchg); RT_NOREF(fXchg);
    16861677        }
     
    17521743static int dbgfR3BpArm(PUVM pUVM, DBGFBP hBp, PDBGFBPINT pBp)
    17531744{
    1754     int rc;
     1745    int rc = VINF_SUCCESS;
    17551746    PVM pVM = pUVM->pVM;
    17561747
     
    18021793        }
    18031794        case DBGFBPTYPE_PORT_IO:
     1795        {
     1796            dbgfR3BpSetEnabled(pBp, true /*fEnabled*/);
     1797            ASMAtomicIncU32(&pUVM->dbgf.s.cPortIoBps);
     1798            IOMR3NotifyBreakpointCountChange(pVM, true /*fPortIo*/, false /*fMmio*/);
     1799            break;
     1800        }
    18041801        case DBGFBPTYPE_MMIO:
    18051802            rc = VERR_NOT_IMPLEMENTED;
     
    18261823static int dbgfR3BpDisarm(PUVM pUVM, DBGFBP hBp, PDBGFBPINT pBp)
    18271824{
    1828     int rc;
     1825    int rc = VINF_SUCCESS;
    18291826    PVM pVM = pUVM->pVM;
    18301827
     
    18701867        }
    18711868        case DBGFBPTYPE_PORT_IO:
     1869        {
     1870            dbgfR3BpSetEnabled(pBp, false /*fEnabled*/);
     1871            uint32_t cPortIoBps = ASMAtomicDecU32(&pUVM->dbgf.s.cPortIoBps);
     1872            if (!cPortIoBps) /** @todo Need to gather all EMTs to not have a stray EMT accessing BP data when it might go away. */
     1873                IOMR3NotifyBreakpointCountChange(pVM, false /*fPortIo*/, false /*fMmio*/);
     1874            break;
     1875        }
    18721876        case DBGFBPTYPE_MMIO:
    18731877            rc = VERR_NOT_IMPLEMENTED;
     
    18831887
    18841888/**
     1889 * Worker for DBGFR3BpHit() differnetiating on the breakpoint type.
     1890 *
     1891 * @returns Strict VBox status code.
     1892 * @param   pVM         The cross context VM structure.
     1893 * @param   pVCpu       The vCPU the breakpoint event happened on.
     1894 * @param   hBp         The breakpoint handle.
     1895 * @param   pBp         The breakpoint data.
     1896 * @param   pBpOwner    The breakpoint owner data.
     1897 *
     1898 * @thread EMT
     1899 */
     1900static VBOXSTRICTRC dbgfR3BpHit(PVM pVM, PVMCPU pVCpu, DBGFBP hBp, PDBGFBPINT pBp, PCDBGFBPOWNERINT pBpOwner)
     1901{
     1902    VBOXSTRICTRC rcStrict;
     1903
     1904    switch (DBGF_BP_PUB_GET_TYPE(&pBp->Pub))
     1905    {
     1906        case DBGFBPTYPE_REG:
     1907        case DBGFBPTYPE_INT3:
     1908        {
     1909            if (DBGF_BP_PUB_IS_EXEC_BEFORE(&pBp->Pub))
     1910                rcStrict = pBpOwner->pfnBpHitR3(pVM, pVCpu->idCpu, pBp->pvUserR3, hBp, &pBp->Pub, DBGF_BP_F_HIT_EXEC_BEFORE);
     1911            if (rcStrict == VINF_SUCCESS)
     1912            {
     1913                uint8_t abInstr[DBGF_BP_INSN_MAX];
     1914                RTGCPTR const GCPtrInstr = pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base;
     1915                int rc = PGMPhysSimpleReadGCPtr(pVCpu, &abInstr[0], GCPtrInstr, sizeof(abInstr));
     1916                AssertRC(rc);
     1917                if (RT_SUCCESS(rc))
     1918                {
     1919                    /* Replace the int3 with the original instruction byte. */
     1920                    abInstr[0] = pBp->Pub.u.Int3.bOrg;
     1921                    rcStrict = IEMExecOneWithPrefetchedByPC(pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx), GCPtrInstr, &abInstr[0], sizeof(abInstr));
     1922                    if (   rcStrict == VINF_SUCCESS
     1923                        && DBGF_BP_PUB_IS_EXEC_AFTER(&pBp->Pub))
     1924                    {
     1925                        VBOXSTRICTRC rcStrict2 = pBpOwner->pfnBpHitR3(pVM, pVCpu->idCpu, pBp->pvUserR3, hBp, &pBp->Pub, DBGF_BP_F_HIT_EXEC_AFTER);
     1926                        if (rcStrict2 == VINF_SUCCESS)
     1927                            return VBOXSTRICTRC_VAL(rcStrict);
     1928                        else if (rcStrict2 != VINF_DBGF_BP_HALT)
     1929                            return VERR_DBGF_BP_OWNER_CALLBACK_WRONG_STATUS;
     1930                    }
     1931                    else
     1932                        return VBOXSTRICTRC_VAL(rcStrict);
     1933                }
     1934            }
     1935            break;
     1936        }
     1937        case DBGFBPTYPE_PORT_IO:
     1938        case DBGFBPTYPE_MMIO:
     1939        {
     1940            pVCpu->dbgf.s.fBpIoActive = false;
     1941            rcStrict = pBpOwner->pfnBpIoHitR3(pVM, pVCpu->idCpu, pBp->pvUserR3, hBp, &pBp->Pub,
     1942                                                pVCpu->dbgf.s.fBpIoBefore
     1943                                              ? DBGF_BP_F_HIT_EXEC_BEFORE
     1944                                              : DBGF_BP_F_HIT_EXEC_AFTER,
     1945                                              pVCpu->dbgf.s.fBpIoAccess, pVCpu->dbgf.s.uBpIoAddress,
     1946                                              pVCpu->dbgf.s.uBpIoValue);
     1947
     1948            break;
     1949        }
     1950        default:
     1951            AssertMsgFailedReturn(("Invalid breakpoint type %d\n", DBGF_BP_PUB_GET_TYPE(&pBp->Pub)),
     1952                                  VERR_IPE_NOT_REACHED_DEFAULT_CASE);
     1953    }
     1954
     1955    return rcStrict;
     1956}
     1957
     1958
     1959/**
    18851960 * Creates a new breakpoint owner returning a handle which can be used when setting breakpoints.
    18861961 *
     
    18891964 * @param   pUVM                The user mode VM handle.
    18901965 * @param   pfnBpHit            The R3 callback which is called when a breakpoint with the owner handle is hit.
     1966 * @param   pfnBpIoHit          The R3 callback which is called when a I/O breakpoint with the owner handle is hit.
    18911967 * @param   phBpOwner           Where to store the owner handle on success.
    18921968 *
    18931969 * @thread Any thread but might defer work to EMT on the first call.
    18941970 */
    1895 VMMR3DECL(int) DBGFR3BpOwnerCreate(PUVM pUVM, PFNDBGFBPHIT pfnBpHit, PDBGFBPOWNER phBpOwner)
     1971VMMR3DECL(int) DBGFR3BpOwnerCreate(PUVM pUVM, PFNDBGFBPHIT pfnBpHit, PFNDBGFBPIOHIT pfnBpIoHit, PDBGFBPOWNER phBpOwner)
    18961972{
    18971973    /*
     
    18991975     */
    19001976    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
    1901     AssertPtrReturn(pfnBpHit, VERR_INVALID_PARAMETER);
     1977    AssertReturn(pfnBpHit || pfnBpIoHit, VERR_INVALID_PARAMETER);
    19021978    AssertPtrReturn(phBpOwner, VERR_INVALID_POINTER);
    19031979
     
    19191995            {
    19201996                PDBGFBPOWNERINT pBpOwner = &pUVM->dbgf.s.paBpOwnersR3[iClr];
    1921                 pBpOwner->cRefs      = 1;
    1922                 pBpOwner->pfnBpHitR3 = pfnBpHit;
     1997                pBpOwner->cRefs        = 1;
     1998                pBpOwner->pfnBpHitR3   = pfnBpHit;
     1999                pBpOwner->pfnBpIoHitR3 = pfnBpIoHit;
    19232000
    19242001                *phBpOwner = (DBGFBPOWNER)iClr;
     
    22532330                                 uint64_t iHitTrigger, uint64_t iHitDisable, PDBGFBP phBp)
    22542331{
    2255     return DBGFR3BpSetPortIoEx(pUVM, NIL_DBGFBPOWNER, NULL /*pvUser*/, uPort, cPorts,
    2256                                DBGF_BP_F_DEFAULT, fAccess, iHitTrigger, iHitDisable, phBp);
     2332    return DBGFR3BpSetPortIoEx(pUVM, NIL_DBGFBPOWNER, NULL /*pvUser*/, uPort, cPorts, fAccess,
     2333                               DBGF_BP_F_DEFAULT, iHitTrigger, iHitDisable, phBp);
    22572334}
    22582335
     
    22862363    AssertReturn(!(fAccess & ~DBGFBPIOACCESS_VALID_MASK_PORT_IO), VERR_INVALID_FLAGS);
    22872364    AssertReturn(fAccess, VERR_INVALID_FLAGS);
     2365    AssertReturn(!(fFlags & ~DBGF_BP_F_VALID_MASK), VERR_INVALID_FLAGS);
     2366    AssertReturn(fFlags, VERR_INVALID_FLAGS);
    22882367    AssertReturn(iHitTrigger <= iHitDisable, VERR_INVALID_PARAMETER);
    22892368    AssertPtrReturn(phBp, VERR_INVALID_POINTER);
    22902369    AssertReturn(cPorts > 0, VERR_OUT_OF_RANGE);
    2291     AssertReturn((RTIOPORT)(uPort + cPorts) < uPort, VERR_OUT_OF_RANGE);
     2370    AssertReturn((RTIOPORT)(uPort + (cPorts - 1)) >= uPort, VERR_OUT_OF_RANGE);
    22922371
    22932372    int rc = dbgfR3BpPortIoEnsureInit(pUVM);
     
    23642443{
    23652444    return DBGFR3BpSetMmioEx(pUVM, NIL_DBGFBPOWNER, NULL /*pvUser*/, GCPhys, cb, fAccess,
    2366                              iHitTrigger, iHitDisable, phBp);
     2445                             DBGF_BP_F_DEFAULT, iHitTrigger, iHitDisable, phBp);
    23672446}
    23682447
     
    23782457 * @param   cb              The size of the MMIO range to break on.
    23792458 * @param   fAccess         The access we want to break on.
     2459 * @param   fFlags          Combination of DBGF_BP_F_XXX.
    23802460 * @param   iHitTrigger     The hit count at which the breakpoint start
    23812461 *                          triggering. Use 0 (or 1) if it's gonna trigger at
     
    23892469VMMR3DECL(int) DBGFR3BpSetMmioEx(PUVM pUVM, DBGFBPOWNER hOwner, void *pvUser,
    23902470                                 RTGCPHYS GCPhys, uint32_t cb, uint32_t fAccess,
    2391                                  uint64_t iHitTrigger, uint64_t iHitDisable, PDBGFBP phBp)
     2471                                 uint32_t fFlags, uint64_t iHitTrigger, uint64_t iHitDisable, PDBGFBP phBp)
    23922472{
    23932473    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
     
    23952475    AssertReturn(!(fAccess & ~DBGFBPIOACCESS_VALID_MASK_MMIO), VERR_INVALID_FLAGS);
    23962476    AssertReturn(fAccess, VERR_INVALID_FLAGS);
     2477    AssertReturn(!(fFlags & ~DBGF_BP_F_VALID_MASK), VERR_INVALID_FLAGS);
     2478    AssertReturn(fFlags, VERR_INVALID_FLAGS);
    23972479    AssertReturn(iHitTrigger <= iHitDisable, VERR_INVALID_PARAMETER);
    23982480    AssertPtrReturn(phBp, VERR_INVALID_POINTER);
     
    25952677    {
    25962678        DBGFBP hBp = pVCpu->dbgf.s.hBpActive;
    2597         PDBGFBPINT pBp = dbgfR3BpGetByHnd(pVM->pUVM, pVCpu->dbgf.s.hBpActive);
     2679        pVCpu->dbgf.s.hBpActive              = NIL_DBGFBP;
     2680        pVCpu->dbgf.s.fBpInvokeOwnerCallback = false;
     2681
     2682        PDBGFBPINT pBp = dbgfR3BpGetByHnd(pVM->pUVM, hBp);
    25982683        AssertReturn(pBp, VERR_DBGF_BP_IPE_9);
    25992684
     
    26042689            if (pBpOwner)
    26052690            {
    2606                 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
    2607 
    2608                 if (DBGF_BP_PUB_IS_EXEC_BEFORE(&pBp->Pub))
    2609                     rcStrict = pBpOwner->pfnBpHitR3(pVM, pVCpu->idCpu, pBp->pvUserR3, hBp, &pBp->Pub, DBGF_BP_F_HIT_EXEC_BEFORE);
    2610                 if (rcStrict == VINF_SUCCESS)
    2611                 {
    2612                     uint8_t abInstr[DBGF_BP_INSN_MAX];
    2613                     RTGCPTR const GCPtrInstr = pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base;
    2614                     int rc = PGMPhysSimpleReadGCPtr(pVCpu, &abInstr[0], GCPtrInstr, sizeof(abInstr));
    2615                     AssertRC(rc);
    2616                     if (RT_SUCCESS(rc))
    2617                     {
    2618                         /* Replace the int3 with the original instruction byte. */
    2619                         abInstr[0] = pBp->Pub.u.Int3.bOrg;
    2620                         rcStrict = IEMExecOneWithPrefetchedByPC(pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx), GCPtrInstr, &abInstr[0], sizeof(abInstr));
    2621                         if (   rcStrict == VINF_SUCCESS
    2622                             && DBGF_BP_PUB_IS_EXEC_AFTER(&pBp->Pub))
    2623                         {
    2624                             VBOXSTRICTRC rcStrict2 = pBpOwner->pfnBpHitR3(pVM, pVCpu->idCpu, pBp->pvUserR3, hBp, &pBp->Pub, DBGF_BP_F_HIT_EXEC_AFTER);
    2625                             if (rcStrict2 == VINF_SUCCESS)
    2626                                 return VBOXSTRICTRC_VAL(rcStrict);
    2627                             else if (rcStrict2 != VINF_DBGF_BP_HALT)
    2628                                 return VERR_DBGF_BP_OWNER_CALLBACK_WRONG_STATUS;
    2629                         }
    2630                         else
    2631                             return VBOXSTRICTRC_VAL(rcStrict);
    2632                     }
    2633                 }
    2634                 else if (rcStrict != VINF_DBGF_BP_HALT) /* Guru meditation. */
     2691                VBOXSTRICTRC rcStrict = dbgfR3BpHit(pVM, pVCpu, hBp, pBp, pBpOwner);
     2692                if (VBOXSTRICTRC_VAL(rcStrict) == VINF_SUCCESS)
     2693                    return VINF_SUCCESS;
     2694                else if (VBOXSTRICTRC_VAL(rcStrict) != VINF_DBGF_BP_HALT) /* Guru meditation. */
    26352695                    return VERR_DBGF_BP_OWNER_CALLBACK_WRONG_STATUS;
    26362696                /* else: Halt in the debugger. */
  • trunk/src/VBox/VMM/VMMR3/DBGFR3FlowTrace.cpp

    r87787 r89924  
    12091209        if (RT_SUCCESS(rc))
    12101210        {
    1211             rc = DBGFR3BpOwnerCreate(pUVM, dbgfR3FlowTraceModProbeFiredWorker, &pThis->hBpOwner);
     1211            rc = DBGFR3BpOwnerCreate(pUVM, dbgfR3FlowTraceModProbeFiredWorker, NULL /*pfnBpIoHit*/, &pThis->hBpOwner);
    12121212            if (RT_SUCCESS(rc))
    12131213            {
  • trunk/src/VBox/VMM/include/DBGFInline.h

    r86728 r89924  
    109109}
    110110
     111#ifdef IN_RING3
     112/**
     113 * Returns the internal breakpoint owner state for the given handle.
     114 *
     115 * @returns Pointer to the internal breakpoint owner state or NULL if the handle is invalid.
     116 * @param   pUVM                The user mode VM handle.
     117 * @param   hBpOwner            The breakpoint owner handle to resolve.
     118 */
     119DECLINLINE(PDBGFBPOWNERINT) dbgfR3BpOwnerGetByHnd(PUVM pUVM, DBGFBPOWNER hBpOwner)
     120{
     121    AssertReturn(hBpOwner < DBGF_BP_OWNER_COUNT_MAX, NULL);
     122    AssertPtrReturn(pUVM->dbgf.s.pbmBpOwnersAllocR3, NULL);
     123
     124    AssertReturn(ASMBitTest(pUVM->dbgf.s.pbmBpOwnersAllocR3, hBpOwner), NULL);
     125    return &pUVM->dbgf.s.paBpOwnersR3[hBpOwner];
     126}
     127#endif
     128
    111129#endif /* !VMM_INCLUDED_SRC_include_DBGFInline_h */
  • trunk/src/VBox/VMM/include/DBGFInternal.h

    r89912 r89924  
    824824    /** Callback to call when a breakpoint has hit, Ring-3 Ptr. */
    825825    R3PTRTYPE(PFNDBGFBPHIT)     pfnBpHitR3;
     826    /** Callback to call when a I/O breakpoint has hit, Ring-3 Ptr. */
     827    R3PTRTYPE(PFNDBGFBPIOHIT)   pfnBpIoHitR3;
     828    /** Padding. */
     829    uint64_t                    u64Pad1;
    826830} DBGFBPOWNERINT;
    827 AssertCompileSize(DBGFBPOWNERINT, 16);
     831AssertCompileSize(DBGFBPOWNERINT, 32);
    828832/** Pointer to an internal breakpoint owner state, shared part. */
    829833typedef DBGFBPOWNERINT *PDBGFBPOWNERINT;
     
    843847    /** Callback to call when a breakpoint has hit, Ring-0 Ptr. */
    844848    R0PTRTYPE(PFNDBGFBPHIT)     pfnBpHitR0;
     849    /** Callback to call when a I/O breakpoint has hit, Ring-0 Ptr. */
     850    R0PTRTYPE(PFNDBGFBPIOHIT)   pfnBpIoHitR0;
     851    /** Padding. */
     852    uint64_t                    u64Pad1;
    845853} DBGFBPOWNERINTR0;
    846 AssertCompileSize(DBGFBPOWNERINTR0, 16);
     854AssertCompileSize(DBGFBPOWNERINTR0, 32);
    847855/** Pointer to an internal breakpoint owner state, shared part. */
    848856typedef DBGFBPOWNERINTR0 *PDBGFBPOWNERINTR0;
     
    12111219     * This is checked and cleared in the \#DB handler. */
    12121220    bool                    fSingleSteppingRaw;
    1213     /** Alignment padding. */
    1214     bool                    afPadding[2];
     1221    /** Flag whether an I/O breakpoint is pending. */
     1222    bool                    fBpIoActive;
     1223    /** Flagh whether the I/O breakpoint hit before the access or after. */
     1224    bool                    fBpIoBefore;
    12151225    /** Current active breakpoint handle.
    12161226     * This is NIL_DBGFBP if not active. It is set when a execution engine
     
    12191229     * @todo drop this in favor of aEvents!  */
    12201230    DBGFBP                  hBpActive;
     1231    /** The access mask for a pending I/O breakpoint. */
     1232    uint32_t                fBpIoAccess;
     1233    /** The address of the access. */
     1234    uint64_t                uBpIoAddress;
     1235    /** The value of the access. */
     1236    uint64_t                uBpIoValue;
    12211237
    12221238    /** The number of events on the stack (aEvents).
     
    13911407     * can still do read accesses without holding it while traversing the trees). */
    13921408    RTSEMFASTMUTEX                  hMtxBpL2Wr;
     1409    /** Number of armed port I/O breakpoints. */
     1410    volatile uint32_t               cPortIoBps;
    13931411    /** @} */
    13941412
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

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