VirtualBox

Changeset 84552 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
May 27, 2020 7:34:40 AM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
138282
Message:

VMM/DBGFTracer: Support string I/O port accesses, bugref:9210

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/DBGFR3Tracer.cpp

    r84494 r84552  
    185185static const RTTRACELOGEVTITEMDESC g_DevIoPortRwEvtItems[] =
    186186{
    187     {"hIoPorts",       "The MMIO region handle being unmapped",                 RTTRACELOGTYPE_UINT64,  0},
     187    {"hIoPorts",       "The I/O region handle being accessed",                  RTTRACELOGTYPE_UINT64,  0},
    188188    {"offPort",        "The offset in the I/O port region being accessed",      RTTRACELOGTYPE_UINT16,  0},
    189189    {"cbXfer",         "Number of bytes being transfered",                      RTTRACELOGTYPE_UINT64,  0},
     
    210210
    211211
     212static const RTTRACELOGEVTITEMDESC g_DevIoPortRwStrEvtItems[] =
     213{
     214    {"hIoPorts",       "The I/O region handle being accesses",                  RTTRACELOGTYPE_UINT64,  0},
     215    {"offPort",        "The offset in the I/O port region being accessed",      RTTRACELOGTYPE_UINT16,  0},
     216    {"cbItem",         "Item size for the access",                              RTTRACELOGTYPE_UINT32,  0},
     217    {"cTransfersReq",  "Number of transfers requested by the guest",            RTTRACELOGTYPE_UINT32,  0},
     218    {"cTransfersRet",  "Number of transfers executed by the device",            RTTRACELOGTYPE_UINT32,  0}
     219};
     220
     221static const RTTRACELOGEVTDESC g_DevIoPortReadStrEvtDesc =
     222{
     223    "Dev.IoPortReadStr",
     224    "I/O port region of a device is being read using REP INS",
     225    RTTRACELOGEVTSEVERITY_DEBUG,
     226    RT_ELEMENTS(g_DevIoPortRwStrEvtItems),
     227    &g_DevIoPortRwStrEvtItems[0]
     228};
     229
     230static const RTTRACELOGEVTDESC g_DevIoPortWriteStrEvtDesc =
     231{
     232    "Dev.IoPortWriteStr",
     233    "I/O port region of a device is being written using REP OUTS",
     234    RTTRACELOGEVTSEVERITY_DEBUG,
     235    RT_ELEMENTS(g_DevIoPortRwStrEvtItems),
     236    &g_DevIoPortRwStrEvtItems[0]
     237};
     238
     239
    212240static const RTTRACELOGEVTITEMDESC g_DevIrqEvtItems[] =
    213241{
     
    269297
    270298
    271 static const RTTRACELOGEVTITEMDESC g_DevGCPhysRwDataEvtItems[] =
     299static const RTTRACELOGEVTITEMDESC g_DevRwDataEvtItems[] =
    272300{
    273301    {"abData",        "The data being read/written",                            RTTRACELOGTYPE_RAWDATA,  0}
    274302};
    275303
    276 static const RTTRACELOGEVTDESC g_DevGCPhysRwDataEvtDesc =
    277 {
    278     "Dev.GCPhysRwData",
     304static const RTTRACELOGEVTDESC g_DevRwDataEvtDesc =
     305{
     306    "Dev.RwData",
    279307    "The data being read or written",
    280308    RTTRACELOGEVTSEVERITY_DEBUG,
    281     RT_ELEMENTS(g_DevGCPhysRwDataEvtItems),
    282     &g_DevGCPhysRwDataEvtItems[0]
     309    RT_ELEMENTS(g_DevRwDataEvtItems),
     310    &g_DevRwDataEvtItems[0]
    283311};
    284312
     
    295323 * @param   pThis                   The DBGF tracer instance.
    296324 */
    297 static PDBGFTRACERGCPHYSRWAGG dbgfTracerR3EvtGCPhysRwAggNew(PDBGFTRACERINSR3 pThis)
     325static PDBGFTRACERGCPHYSRWAGG dbgfTracerR3EvtRwAggNew(PDBGFTRACERINSR3 pThis)
    298326{
    299327    for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aGstMemRwData); i++)
     
    314342 * @param   idEvtPrev               The event ID to look for.
    315343 */
    316 static PDBGFTRACERGCPHYSRWAGG dbgfTracerR3EvtGCPhysRwAggFind(PDBGFTRACERINSR3 pThis, uint64_t idEvtPrev)
     344static PDBGFTRACERGCPHYSRWAGG dbgfTracerR3EvtRwAggFind(PDBGFTRACERINSR3 pThis, uint64_t idEvtPrev)
    317345{
    318346    for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aGstMemRwData); i++)
     
    324352
    325353    return NULL;
     354}
     355
     356
     357/**
     358 * Common code for the guest memory and string I/O port read/write events.
     359 *
     360 * @returns VBox status code.
     361 * @param   pThis                   The DBGF tracer instance.
     362 * @param   pEvtHdr                 The event header.
     363 * @param   cbXfer                  Overall number of bytes of data for this event.
     364 * @param   pvData                  Initial data supplied in the event starting the aggregation.
     365 * @param   cbData                  Number of initial bytes of data.
     366 */
     367static int dbgfTracerR3EvtRwStartCommon(PDBGFTRACERINSR3 pThis, PCDBGFTRACEREVTHDR pEvtHdr, size_t cbXfer, const void *pvData, size_t cbData)
     368{
     369    /* Slow path, find an empty aggregation structure. */
     370    int rc = VINF_SUCCESS;
     371    PDBGFTRACERGCPHYSRWAGG pDataAgg = dbgfTracerR3EvtRwAggNew(pThis);
     372    if (RT_LIKELY(pDataAgg))
     373    {
     374        /* Initialize it. */
     375        pDataAgg->idEvtStart = pEvtHdr->idEvt;
     376        pDataAgg->idEvtPrev  = pEvtHdr->idEvt;
     377        pDataAgg->cbXfer     = cbXfer;
     378        pDataAgg->cbLeft     = pDataAgg->cbXfer;
     379        pDataAgg->offBuf     = 0;
     380
     381        /* Need to reallocate the buffer to hold the complete data? */
     382        if (RT_UNLIKELY(pDataAgg->cbBufMax < pDataAgg->cbXfer))
     383        {
     384            uint8_t *pbBufNew = (uint8_t *)RTMemRealloc(pDataAgg->pbBuf, pDataAgg->cbXfer);
     385            if (RT_LIKELY(pbBufNew))
     386            {
     387                pDataAgg->pbBuf    = pbBufNew;
     388                pDataAgg->cbBufMax = pDataAgg->cbXfer;
     389            }
     390            else
     391                rc = VERR_NO_MEMORY;
     392        }
     393
     394        if (RT_SUCCESS(rc))
     395        {
     396            memcpy(pDataAgg->pbBuf, pvData, cbData);
     397            pDataAgg->offBuf += cbData;
     398            pDataAgg->cbLeft -= cbData;
     399        }
     400    }
     401    else
     402        rc = VERR_NO_MEMORY;
     403
     404    if (RT_FAILURE(rc))
     405    {
     406        LogRelMax(10, ("DBGF: Creating new data aggregation structure for memory read/write failed with %Rrc, trace log will not contain data for this event!\n", rc));
     407
     408        /* Write out the finish event without any data. */
     409        size_t cbEvtData = 0;
     410        rc = RTTraceLogWrEvtAdd(pThis->hTraceLog, &g_DevRwDataEvtDesc, RTTRACELOG_WR_ADD_EVT_F_GRP_FINISH,
     411                                pEvtHdr->idEvt, pEvtHdr->hEvtSrc, NULL, &cbEvtData);
     412        if (pDataAgg) /* Reset the aggregation event. */
     413            pDataAgg->idEvtStart = DBGF_TRACER_EVT_HDR_ID_INVALID;
     414    }
     415
     416    return rc;
    326417}
    327418
     
    352443            size_t cbEvtData = pEvtGCPhysRw->cbXfer;
    353444
    354             rc = RTTraceLogWrEvtAdd(pThis->hTraceLog, &g_DevGCPhysRwDataEvtDesc, RTTRACELOG_WR_ADD_EVT_F_GRP_FINISH,
     445            rc = RTTraceLogWrEvtAdd(pThis->hTraceLog, &g_DevRwDataEvtDesc, RTTRACELOG_WR_ADD_EVT_F_GRP_FINISH,
    355446                                    pEvtHdr->idEvt, pEvtHdr->hEvtSrc, &pEvtGCPhysRw->abData[0], &cbEvtData);
    356447        }
    357448        else
    358         {
    359             /* Slow path, find an empty aggregation structure. */
    360             PDBGFTRACERGCPHYSRWAGG pDataAgg = dbgfTracerR3EvtGCPhysRwAggNew(pThis);
    361             if (RT_LIKELY(pDataAgg))
    362             {
    363                 /* Initialize it. */
    364                 pDataAgg->idEvtStart = pEvtHdr->idEvt;
    365                 pDataAgg->idEvtPrev  = pEvtHdr->idEvt;
    366                 pDataAgg->cbXfer     = pEvtGCPhysRw->cbXfer;
    367                 pDataAgg->cbLeft     = pDataAgg->cbXfer;
    368                 pDataAgg->offBuf     = 0;
    369 
    370                 /* Need to reallocate the buffer to hold the complete data? */
    371                 if (RT_UNLIKELY(pDataAgg->cbBufMax < pDataAgg->cbXfer))
    372                 {
    373                     uint8_t *pbBufNew = (uint8_t *)RTMemRealloc(pDataAgg->pbBuf, pDataAgg->cbXfer);
    374                     if (RT_LIKELY(pbBufNew))
    375                     {
    376                         pDataAgg->pbBuf    = pbBufNew;
    377                         pDataAgg->cbBufMax = pDataAgg->cbXfer;
    378                     }
    379                     else
    380                         rc = VERR_NO_MEMORY;
    381                 }
    382 
    383                 if (RT_SUCCESS(rc))
    384                 {
    385                     memcpy(pDataAgg->pbBuf, &pEvtGCPhysRw->abData[0], sizeof(pEvtGCPhysRw->abData));
    386                     pDataAgg->offBuf += sizeof(pEvtGCPhysRw->abData);
    387                     pDataAgg->cbLeft -= sizeof(pEvtGCPhysRw->abData);
    388                 }
    389             }
    390             else
    391                 rc = VERR_NO_MEMORY;
    392 
    393             if (RT_FAILURE(rc))
    394             {
    395                 LogRelMax(10, ("DBGF: Creating new data aggregation structure for guest memory read/write failed with %Rrc, trace log will not contain data for this event!\n", rc));
    396 
    397                 /* Write out the finish event without any data. */
    398                 size_t cbEvtData = 0;
    399                 rc = RTTraceLogWrEvtAdd(pThis->hTraceLog, &g_DevGCPhysRwDataEvtDesc, RTTRACELOG_WR_ADD_EVT_F_GRP_FINISH,
    400                                         pEvtHdr->idEvt, pEvtHdr->hEvtSrc, NULL, &cbEvtData);
    401                 if (pDataAgg) /* Reset the aggregation event. */
    402                     pDataAgg->idEvtStart = DBGF_TRACER_EVT_HDR_ID_INVALID;
    403             }
    404         }
     449            rc = dbgfTracerR3EvtRwStartCommon(pThis, pEvtHdr, pEvtGCPhysRw->cbXfer, &pEvtGCPhysRw->abData[0], sizeof(pEvtGCPhysRw->abData));
    405450    }
    406451
     
    410455
    411456/**
    412  * Continues a previously started guest memory read/write event.
     457 * Starts a new I/O port string read/write event.
     458 *
     459 * @returns VBox status code.
     460 * @param   pThis                   The DBGF tracer instance.
     461 * @param   pEvtHdr                 The event header.
     462 * @param   pEvtIoPortStrRw         The I/O port string read/write event descriptor.
     463 * @param   cbXfer                  Number of bytes of valid data for this event.
     464 * @param   pEvtDesc                The event descriptor written to the trace log.
     465 */
     466static int dbgfTracerR3EvtIoPortStrRwStart(PDBGFTRACERINSR3 pThis, PCDBGFTRACEREVTHDR pEvtHdr,
     467                                           PCDBGFTRACEREVTIOPORTSTR pEvtIoPortStrRw, size_t cbXfer,
     468                                           PCRTTRACELOGEVTDESC pEvtDesc)
     469{
     470    /* Write out the event header first in any case. */
     471    int rc = RTTraceLogWrEvtAddL(pThis->hTraceLog, pEvtDesc, RTTRACELOG_WR_ADD_EVT_F_GRP_START,
     472                                 pEvtHdr->idEvt, pEvtHdr->hEvtSrc, pEvtIoPortStrRw->hIoPorts, pEvtIoPortStrRw->offPort,
     473                                 pEvtIoPortStrRw->cbItem, pEvtIoPortStrRw->cTransfersReq, pEvtIoPortStrRw->cTransfersRet);
     474    if (RT_SUCCESS(rc))
     475    {
     476        /*
     477         * If the amount of data is small enough to fit into the single event descriptor we can skip allocating
     478         * an aggregation tracking structure and write the event containing the complete data out immediately.
     479         */
     480        if (cbXfer <= sizeof(pEvtIoPortStrRw->abData))
     481        {
     482            size_t cbEvtData = cbXfer;
     483
     484            rc = RTTraceLogWrEvtAdd(pThis->hTraceLog, &g_DevRwDataEvtDesc, RTTRACELOG_WR_ADD_EVT_F_GRP_FINISH,
     485                                    pEvtHdr->idEvt, pEvtHdr->hEvtSrc, &pEvtIoPortStrRw->abData[0], &cbEvtData);
     486        }
     487        else
     488            rc = dbgfTracerR3EvtRwStartCommon(pThis, pEvtHdr, cbXfer, &pEvtIoPortStrRw->abData[0], sizeof(pEvtIoPortStrRw->abData));
     489    }
     490
     491    return rc;
     492}
     493
     494
     495/**
     496 * Continues a previously started guest memory or string I/O port read/write event.
    413497 *
    414498 * @returns VBox status code.
     
    417501 * @param   pvData                  The data to log.
    418502 */
    419 static int dbgfTracerR3EvtGCPhysRwContinue(PDBGFTRACERINSR3 pThis, PCDBGFTRACEREVTHDR pEvtHdr, void *pvData)
     503static int dbgfTracerR3EvtRwContinue(PDBGFTRACERINSR3 pThis, PCDBGFTRACEREVTHDR pEvtHdr, void *pvData)
    420504{
    421505    int rc = VINF_SUCCESS;
    422     PDBGFTRACERGCPHYSRWAGG pDataAgg = dbgfTracerR3EvtGCPhysRwAggFind(pThis, pEvtHdr->idEvtPrev);
     506    PDBGFTRACERGCPHYSRWAGG pDataAgg = dbgfTracerR3EvtRwAggFind(pThis, pEvtHdr->idEvtPrev);
    423507
    424508    if (RT_LIKELY(pDataAgg))
     
    433517        {
    434518            /* All data aggregated, write it out and reset the structure. */
    435             rc = RTTraceLogWrEvtAdd(pThis->hTraceLog, &g_DevGCPhysRwDataEvtDesc, RTTRACELOG_WR_ADD_EVT_F_GRP_FINISH,
     519            rc = RTTraceLogWrEvtAdd(pThis->hTraceLog, &g_DevRwDataEvtDesc, RTTRACELOG_WR_ADD_EVT_F_GRP_FINISH,
    436520                                    pDataAgg->idEvtStart, pEvtHdr->hEvtSrc, pDataAgg->pbBuf, &pDataAgg->cbXfer);
    437521            pDataAgg->offBuf     = 0;
     
    543627                                     pEvtHdr->idEvt, pEvtHdr->hEvtSrc, pEvtIoPortRw->hIoPorts, pEvtIoPortRw->offPort,
    544628                                     pEvtIoPortRw->cbXfer, pEvtIoPortRw->u32Val);
     629            break;
     630        }
     631        case DBGFTRACEREVT_IOPORT_READ_STR:
     632        case DBGFTRACEREVT_IOPORT_WRITE_STR:
     633        {
     634            PCRTTRACELOGEVTDESC pEvtDesc =   pEvtHdr->enmEvt == DBGFTRACEREVT_IOPORT_WRITE_STR
     635                                           ? &g_DevIoPortWriteStrEvtDesc
     636                                           : &g_DevIoPortReadStrEvtDesc;
     637
     638            /* If the previous event ID is invalid this starts a new read/write we have to aggregate all the data for. */
     639            if (pEvtHdr->idEvtPrev == DBGF_TRACER_EVT_HDR_ID_INVALID)
     640            {
     641                PCDBGFTRACEREVTIOPORTSTR pEvtIoPortStrRw = (PCDBGFTRACEREVTIOPORTSTR)(pEvtHdr + 1);
     642                size_t cbXfer =   pEvtHdr->enmEvt == DBGFTRACEREVT_IOPORT_WRITE_STR
     643                                ? pEvtIoPortStrRw->cTransfersReq * pEvtIoPortStrRw->cbItem
     644                                : pEvtIoPortStrRw->cTransfersRet * pEvtIoPortStrRw->cbItem;
     645
     646                rc = dbgfTracerR3EvtIoPortStrRwStart(pThis, pEvtHdr, pEvtIoPortStrRw, cbXfer, pEvtDesc);
     647            }
     648            else
     649            {
     650                /* Continuation of a started read or write, look up the right tracking structure and process the new data. */
     651                void *pvData = pEvtHdr + 1;
     652                rc = dbgfTracerR3EvtRwContinue(pThis, pEvtHdr, pvData);
     653            }
    545654            break;
    546655        }
     
    578687                /* Continuation of a started read or write, look up the right tracking structure and process the new data. */
    579688                void *pvData = pEvtHdr + 1;
    580                 rc = dbgfTracerR3EvtGCPhysRwContinue(pThis, pEvtHdr, pvData);
     689                rc = dbgfTracerR3EvtRwContinue(pThis, pEvtHdr, pvData);
    581690            }
    582691            break;
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