Index: /trunk/include/VBox/vmm/dbgf.h
===================================================================
--- /trunk/include/VBox/vmm/dbgf.h	(revision 84551)
+++ /trunk/include/VBox/vmm/dbgf.h	(revision 84552)
@@ -2834,5 +2834,9 @@
 VMM_INT_DECL(int)   DBGFTracerEvtIoPortUnmap(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hIoPorts);
 VMM_INT_DECL(int)   DBGFTracerEvtIoPortRead(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hIoPorts, RTIOPORT offPort, const void *pvVal, size_t cbVal);
+VMM_INT_DECL(int)   DBGFTracerEvtIoPortReadStr(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hIoPorts, RTIOPORT offPort, const void *pv, size_t cb,
+                                               uint32_t cTransfersReq, uint32_t cTransfersRet);
 VMM_INT_DECL(int)   DBGFTracerEvtIoPortWrite(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hIoPorts, RTIOPORT offPort, const void *pvVal, size_t cbVal);
+VMM_INT_DECL(int)   DBGFTracerEvtIoPortWriteStr(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hIoPorts, RTIOPORT offPort, const void *pv, size_t cb,
+                                                uint32_t cTransfersReq, uint32_t cTransfersRet);
 VMM_INT_DECL(int)   DBGFTracerEvtIrq(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, int32_t iIrq, int32_t fIrqLvl);
 VMM_INT_DECL(int)   DBGFTracerEvtIoApicMsi(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, RTGCPHYS GCPhys, uint32_t u32Val);
Index: /trunk/src/VBox/VMM/VMMAll/DBGFAllTracer.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/DBGFAllTracer.cpp	(revision 84551)
+++ /trunk/src/VBox/VMM/VMMAll/DBGFAllTracer.cpp	(revision 84552)
@@ -288,4 +288,64 @@
 
 /**
+ * Handles a I/O port string transfer event.
+ *
+ * @returns VBox status code.
+ * @param   pVM                     The current context VM instance data.
+ * @param   pThisCC                 The event tracer instance current context data.
+ * @param   enmTraceEvt             The trace event type posted.
+ * @param   hEvtSrc                 The event source for the posted event.
+ * @param   hIoPorts                The I/O port region handle for the transfer.
+ * @param   offPort                 The offset into the region where the transfer happened.
+ * @param   pv                      The data being transfered.
+ * @param   cb                      Number of bytes of valid data in the buffer.
+ * @param   cbItem                  Item size in bytes.
+ * @param   cTransfersReq           Number of transfers requested.
+ * @param   cTransfersRet           Number of transfers done.
+ */
+static int dbgfTracerEvtIoPortStr(PVMCC pVM, PDBGFTRACERINSCC pThisCC, DBGFTRACEREVT enmTraceEvt, DBGFTRACEREVTSRC hEvtSrc,
+                                  uint64_t hIoPorts, RTIOPORT offPort, const void *pv, size_t cb, size_t cbItem, uint32_t cTransfersReq,
+                                  uint32_t cTransfersRet)
+{
+    /* Fast path for really small transfers where everything fits into the descriptor. */
+    DBGFTRACEREVTIOPORTSTR EvtIoPortStr;
+    EvtIoPortStr.hIoPorts      = hIoPorts;
+    EvtIoPortStr.cbItem        = cbItem;
+    EvtIoPortStr.cTransfersReq = cTransfersReq;
+    EvtIoPortStr.cTransfersRet = cTransfersRet;
+    EvtIoPortStr.offPort       = offPort;
+    if (cb <= sizeof(EvtIoPortStr.abData))
+    {
+        memcpy(&EvtIoPortStr.abData[0], pv, cb);
+        return dbgfTracerEvtPostSingle(pVM, pThisCC, hEvtSrc, enmTraceEvt, &EvtIoPortStr, NULL /*pidEvt*/);
+    }
+
+    /*
+     * Slow path where we have to split the data into multiple entries.
+     * Each one is linked to the previous one by the previous event ID.
+     */
+    const uint8_t *pbBuf = (const uint8_t *)pv;
+    size_t cbLeft = cb;
+    uint64_t idEvtPrev = 0;
+    memcpy(&EvtIoPortStr.abData[0], pbBuf, sizeof(EvtIoPortStr.abData));
+    pbBuf  += sizeof(EvtIoPortStr.abData);
+    cbLeft -= sizeof(EvtIoPortStr.abData);
+
+    int rc = dbgfTracerEvtPostSingle(pVM, pThisCC, hEvtSrc, enmTraceEvt, &EvtIoPortStr, &idEvtPrev);
+    while (   RT_SUCCESS(rc)
+           && cbLeft)
+    {
+        size_t cbThisXfer = RT_MIN(cbLeft, DBGF_TRACER_EVT_PAYLOAD_SZ);
+        rc = dbgfTracerEvtPostEx(pVM, pThisCC, hEvtSrc, enmTraceEvt, idEvtPrev,
+                                 pbBuf, cbThisXfer, &idEvtPrev);
+
+        pbBuf  += cbThisXfer;
+        cbLeft -= cbThisXfer;
+    }
+
+    return rc;
+}
+
+
+/**
  * Registers an MMIO region mapping event for the given event source.
  *
@@ -490,4 +550,28 @@
 
 /**
+ * Registers an I/O region string read event for the given event source.
+ *
+ * @returns VBox status code.
+ * @param   pVM                     The current context VM instance data.
+ * @param   hEvtSrc                 The event source for the posted event.
+ * @param   hIoPorts                The I/O port region handle being read from.
+ * @param   offPort                 The offset into the region where the read happened.
+ * @param   pv                      The data being read.
+ * @param   cb                      Item size in bytes.
+ * @param   cTransfersReq           Number of transfers requested.
+ * @param   cTransfersRet           Number of transfers done.
+ */
+VMM_INT_DECL(int) DBGFTracerEvtIoPortReadStr(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hIoPorts, RTIOPORT offPort, const void *pv, size_t cb,
+                                             uint32_t cTransfersReq, uint32_t cTransfersRet)
+{
+    PDBGFTRACERINSCC pThisCC = dbgfTracerGetInstance(pVM);
+    AssertReturn(pThisCC, VERR_DBGF_TRACER_IPE_1);
+
+    return dbgfTracerEvtIoPortStr(pVM, pThisCC, DBGFTRACEREVT_IOPORT_READ_STR, hEvtSrc, hIoPorts, offPort, pv, cTransfersRet * cb,
+                                  cb, cTransfersReq, cTransfersRet);
+}
+
+
+/**
  * Registers an I/O region write event for the given event source.
  *
@@ -517,4 +601,28 @@
 
 /**
+ * Registers an I/O region string write event for the given event source.
+ *
+ * @returns VBox status code.
+ * @param   pVM                     The current context VM instance data.
+ * @param   hEvtSrc                 The event source for the posted event.
+ * @param   hIoPorts                The I/O port region handle being written to.
+ * @param   offPort                 The offset into the region where the write happened.
+ * @param   pv                      The data being written.
+ * @param   cb                      Item size in bytes.
+ * @param   cTransfersReq           Number of transfers requested.
+ * @param   cTransfersRet           Number of transfers done.
+ */
+VMM_INT_DECL(int) DBGFTracerEvtIoPortWriteStr(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hIoPorts, RTIOPORT offPort, const void *pv, size_t cb,
+                                              uint32_t cTransfersReq, uint32_t cTransfersRet)
+{
+    PDBGFTRACERINSCC pThisCC = dbgfTracerGetInstance(pVM);
+    AssertReturn(pThisCC, VERR_DBGF_TRACER_IPE_1);
+
+    return dbgfTracerEvtIoPortStr(pVM, pThisCC, DBGFTRACEREVT_IOPORT_WRITE_STR, hEvtSrc, hIoPorts, offPort, pv, cTransfersReq * cb,
+                                  cb, cTransfersReq, cTransfersRet);
+}
+
+
+/**
  * Registers an IRQ change event for the given event source.
  *
Index: /trunk/src/VBox/VMM/VMMR3/DBGFR3Tracer.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/DBGFR3Tracer.cpp	(revision 84551)
+++ /trunk/src/VBox/VMM/VMMR3/DBGFR3Tracer.cpp	(revision 84552)
@@ -185,5 +185,5 @@
 static const RTTRACELOGEVTITEMDESC g_DevIoPortRwEvtItems[] =
 {
-    {"hIoPorts",       "The MMIO region handle being unmapped",                 RTTRACELOGTYPE_UINT64,  0},
+    {"hIoPorts",       "The I/O region handle being accessed",                  RTTRACELOGTYPE_UINT64,  0},
     {"offPort",        "The offset in the I/O port region being accessed",      RTTRACELOGTYPE_UINT16,  0},
     {"cbXfer",         "Number of bytes being transfered",                      RTTRACELOGTYPE_UINT64,  0},
@@ -210,4 +210,32 @@
 
 
+static const RTTRACELOGEVTITEMDESC g_DevIoPortRwStrEvtItems[] =
+{
+    {"hIoPorts",       "The I/O region handle being accesses",                  RTTRACELOGTYPE_UINT64,  0},
+    {"offPort",        "The offset in the I/O port region being accessed",      RTTRACELOGTYPE_UINT16,  0},
+    {"cbItem",         "Item size for the access",                              RTTRACELOGTYPE_UINT32,  0},
+    {"cTransfersReq",  "Number of transfers requested by the guest",            RTTRACELOGTYPE_UINT32,  0},
+    {"cTransfersRet",  "Number of transfers executed by the device",            RTTRACELOGTYPE_UINT32,  0}
+};
+
+static const RTTRACELOGEVTDESC g_DevIoPortReadStrEvtDesc =
+{
+    "Dev.IoPortReadStr",
+    "I/O port region of a device is being read using REP INS",
+    RTTRACELOGEVTSEVERITY_DEBUG,
+    RT_ELEMENTS(g_DevIoPortRwStrEvtItems),
+    &g_DevIoPortRwStrEvtItems[0]
+};
+
+static const RTTRACELOGEVTDESC g_DevIoPortWriteStrEvtDesc =
+{
+    "Dev.IoPortWriteStr",
+    "I/O port region of a device is being written using REP OUTS",
+    RTTRACELOGEVTSEVERITY_DEBUG,
+    RT_ELEMENTS(g_DevIoPortRwStrEvtItems),
+    &g_DevIoPortRwStrEvtItems[0]
+};
+
+
 static const RTTRACELOGEVTITEMDESC g_DevIrqEvtItems[] =
 {
@@ -269,16 +297,16 @@
 
 
-static const RTTRACELOGEVTITEMDESC g_DevGCPhysRwDataEvtItems[] =
+static const RTTRACELOGEVTITEMDESC g_DevRwDataEvtItems[] =
 {
     {"abData",        "The data being read/written",                            RTTRACELOGTYPE_RAWDATA,  0}
 };
 
-static const RTTRACELOGEVTDESC g_DevGCPhysRwDataEvtDesc =
-{
-    "Dev.GCPhysRwData",
+static const RTTRACELOGEVTDESC g_DevRwDataEvtDesc =
+{
+    "Dev.RwData",
     "The data being read or written",
     RTTRACELOGEVTSEVERITY_DEBUG,
-    RT_ELEMENTS(g_DevGCPhysRwDataEvtItems),
-    &g_DevGCPhysRwDataEvtItems[0]
+    RT_ELEMENTS(g_DevRwDataEvtItems),
+    &g_DevRwDataEvtItems[0]
 };
 
@@ -295,5 +323,5 @@
  * @param   pThis                   The DBGF tracer instance.
  */
-static PDBGFTRACERGCPHYSRWAGG dbgfTracerR3EvtGCPhysRwAggNew(PDBGFTRACERINSR3 pThis)
+static PDBGFTRACERGCPHYSRWAGG dbgfTracerR3EvtRwAggNew(PDBGFTRACERINSR3 pThis)
 {
     for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aGstMemRwData); i++)
@@ -314,5 +342,5 @@
  * @param   idEvtPrev               The event ID to look for.
  */
-static PDBGFTRACERGCPHYSRWAGG dbgfTracerR3EvtGCPhysRwAggFind(PDBGFTRACERINSR3 pThis, uint64_t idEvtPrev)
+static PDBGFTRACERGCPHYSRWAGG dbgfTracerR3EvtRwAggFind(PDBGFTRACERINSR3 pThis, uint64_t idEvtPrev)
 {
     for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aGstMemRwData); i++)
@@ -324,4 +352,67 @@
 
     return NULL;
+}
+
+
+/**
+ * Common code for the guest memory and string I/O port read/write events.
+ *
+ * @returns VBox status code.
+ * @param   pThis                   The DBGF tracer instance.
+ * @param   pEvtHdr                 The event header.
+ * @param   cbXfer                  Overall number of bytes of data for this event.
+ * @param   pvData                  Initial data supplied in the event starting the aggregation.
+ * @param   cbData                  Number of initial bytes of data.
+ */
+static int dbgfTracerR3EvtRwStartCommon(PDBGFTRACERINSR3 pThis, PCDBGFTRACEREVTHDR pEvtHdr, size_t cbXfer, const void *pvData, size_t cbData)
+{
+    /* Slow path, find an empty aggregation structure. */
+    int rc = VINF_SUCCESS;
+    PDBGFTRACERGCPHYSRWAGG pDataAgg = dbgfTracerR3EvtRwAggNew(pThis);
+    if (RT_LIKELY(pDataAgg))
+    {
+        /* Initialize it. */
+        pDataAgg->idEvtStart = pEvtHdr->idEvt;
+        pDataAgg->idEvtPrev  = pEvtHdr->idEvt;
+        pDataAgg->cbXfer     = cbXfer;
+        pDataAgg->cbLeft     = pDataAgg->cbXfer;
+        pDataAgg->offBuf     = 0;
+
+        /* Need to reallocate the buffer to hold the complete data? */
+        if (RT_UNLIKELY(pDataAgg->cbBufMax < pDataAgg->cbXfer))
+        {
+            uint8_t *pbBufNew = (uint8_t *)RTMemRealloc(pDataAgg->pbBuf, pDataAgg->cbXfer);
+            if (RT_LIKELY(pbBufNew))
+            {
+                pDataAgg->pbBuf    = pbBufNew;
+                pDataAgg->cbBufMax = pDataAgg->cbXfer;
+            }
+            else
+                rc = VERR_NO_MEMORY;
+        }
+
+        if (RT_SUCCESS(rc))
+        {
+            memcpy(pDataAgg->pbBuf, pvData, cbData);
+            pDataAgg->offBuf += cbData;
+            pDataAgg->cbLeft -= cbData;
+        }
+    }
+    else
+        rc = VERR_NO_MEMORY;
+
+    if (RT_FAILURE(rc))
+    {
+        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));
+
+        /* Write out the finish event without any data. */
+        size_t cbEvtData = 0;
+        rc = RTTraceLogWrEvtAdd(pThis->hTraceLog, &g_DevRwDataEvtDesc, RTTRACELOG_WR_ADD_EVT_F_GRP_FINISH,
+                                pEvtHdr->idEvt, pEvtHdr->hEvtSrc, NULL, &cbEvtData);
+        if (pDataAgg) /* Reset the aggregation event. */
+            pDataAgg->idEvtStart = DBGF_TRACER_EVT_HDR_ID_INVALID;
+    }
+
+    return rc;
 }
 
@@ -352,55 +443,9 @@
             size_t cbEvtData = pEvtGCPhysRw->cbXfer;
 
-            rc = RTTraceLogWrEvtAdd(pThis->hTraceLog, &g_DevGCPhysRwDataEvtDesc, RTTRACELOG_WR_ADD_EVT_F_GRP_FINISH,
+            rc = RTTraceLogWrEvtAdd(pThis->hTraceLog, &g_DevRwDataEvtDesc, RTTRACELOG_WR_ADD_EVT_F_GRP_FINISH,
                                     pEvtHdr->idEvt, pEvtHdr->hEvtSrc, &pEvtGCPhysRw->abData[0], &cbEvtData);
         }
         else
-        {
-            /* Slow path, find an empty aggregation structure. */
-            PDBGFTRACERGCPHYSRWAGG pDataAgg = dbgfTracerR3EvtGCPhysRwAggNew(pThis);
-            if (RT_LIKELY(pDataAgg))
-            {
-                /* Initialize it. */
-                pDataAgg->idEvtStart = pEvtHdr->idEvt;
-                pDataAgg->idEvtPrev  = pEvtHdr->idEvt;
-                pDataAgg->cbXfer     = pEvtGCPhysRw->cbXfer;
-                pDataAgg->cbLeft     = pDataAgg->cbXfer;
-                pDataAgg->offBuf     = 0;
-
-                /* Need to reallocate the buffer to hold the complete data? */
-                if (RT_UNLIKELY(pDataAgg->cbBufMax < pDataAgg->cbXfer))
-                {
-                    uint8_t *pbBufNew = (uint8_t *)RTMemRealloc(pDataAgg->pbBuf, pDataAgg->cbXfer);
-                    if (RT_LIKELY(pbBufNew))
-                    {
-                        pDataAgg->pbBuf    = pbBufNew;
-                        pDataAgg->cbBufMax = pDataAgg->cbXfer;
-                    }
-                    else
-                        rc = VERR_NO_MEMORY;
-                }
-
-                if (RT_SUCCESS(rc))
-                {
-                    memcpy(pDataAgg->pbBuf, &pEvtGCPhysRw->abData[0], sizeof(pEvtGCPhysRw->abData));
-                    pDataAgg->offBuf += sizeof(pEvtGCPhysRw->abData);
-                    pDataAgg->cbLeft -= sizeof(pEvtGCPhysRw->abData);
-                }
-            }
-            else
-                rc = VERR_NO_MEMORY;
-
-            if (RT_FAILURE(rc))
-            {
-                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));
-
-                /* Write out the finish event without any data. */
-                size_t cbEvtData = 0;
-                rc = RTTraceLogWrEvtAdd(pThis->hTraceLog, &g_DevGCPhysRwDataEvtDesc, RTTRACELOG_WR_ADD_EVT_F_GRP_FINISH,
-                                        pEvtHdr->idEvt, pEvtHdr->hEvtSrc, NULL, &cbEvtData);
-                if (pDataAgg) /* Reset the aggregation event. */
-                    pDataAgg->idEvtStart = DBGF_TRACER_EVT_HDR_ID_INVALID;
-            }
-        }
+            rc = dbgfTracerR3EvtRwStartCommon(pThis, pEvtHdr, pEvtGCPhysRw->cbXfer, &pEvtGCPhysRw->abData[0], sizeof(pEvtGCPhysRw->abData));
     }
 
@@ -410,5 +455,44 @@
 
 /**
- * Continues a previously started guest memory read/write event.
+ * Starts a new I/O port string read/write event.
+ *
+ * @returns VBox status code.
+ * @param   pThis                   The DBGF tracer instance.
+ * @param   pEvtHdr                 The event header.
+ * @param   pEvtIoPortStrRw         The I/O port string read/write event descriptor.
+ * @param   cbXfer                  Number of bytes of valid data for this event.
+ * @param   pEvtDesc                The event descriptor written to the trace log.
+ */
+static int dbgfTracerR3EvtIoPortStrRwStart(PDBGFTRACERINSR3 pThis, PCDBGFTRACEREVTHDR pEvtHdr,
+                                           PCDBGFTRACEREVTIOPORTSTR pEvtIoPortStrRw, size_t cbXfer,
+                                           PCRTTRACELOGEVTDESC pEvtDesc)
+{
+    /* Write out the event header first in any case. */
+    int rc = RTTraceLogWrEvtAddL(pThis->hTraceLog, pEvtDesc, RTTRACELOG_WR_ADD_EVT_F_GRP_START,
+                                 pEvtHdr->idEvt, pEvtHdr->hEvtSrc, pEvtIoPortStrRw->hIoPorts, pEvtIoPortStrRw->offPort,
+                                 pEvtIoPortStrRw->cbItem, pEvtIoPortStrRw->cTransfersReq, pEvtIoPortStrRw->cTransfersRet);
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * If the amount of data is small enough to fit into the single event descriptor we can skip allocating
+         * an aggregation tracking structure and write the event containing the complete data out immediately.
+         */
+        if (cbXfer <= sizeof(pEvtIoPortStrRw->abData))
+        {
+            size_t cbEvtData = cbXfer;
+
+            rc = RTTraceLogWrEvtAdd(pThis->hTraceLog, &g_DevRwDataEvtDesc, RTTRACELOG_WR_ADD_EVT_F_GRP_FINISH,
+                                    pEvtHdr->idEvt, pEvtHdr->hEvtSrc, &pEvtIoPortStrRw->abData[0], &cbEvtData);
+        }
+        else
+            rc = dbgfTracerR3EvtRwStartCommon(pThis, pEvtHdr, cbXfer, &pEvtIoPortStrRw->abData[0], sizeof(pEvtIoPortStrRw->abData));
+    }
+
+    return rc;
+}
+
+
+/**
+ * Continues a previously started guest memory or string I/O port read/write event.
  *
  * @returns VBox status code.
@@ -417,8 +501,8 @@
  * @param   pvData                  The data to log.
  */
-static int dbgfTracerR3EvtGCPhysRwContinue(PDBGFTRACERINSR3 pThis, PCDBGFTRACEREVTHDR pEvtHdr, void *pvData)
+static int dbgfTracerR3EvtRwContinue(PDBGFTRACERINSR3 pThis, PCDBGFTRACEREVTHDR pEvtHdr, void *pvData)
 {
     int rc = VINF_SUCCESS;
-    PDBGFTRACERGCPHYSRWAGG pDataAgg = dbgfTracerR3EvtGCPhysRwAggFind(pThis, pEvtHdr->idEvtPrev);
+    PDBGFTRACERGCPHYSRWAGG pDataAgg = dbgfTracerR3EvtRwAggFind(pThis, pEvtHdr->idEvtPrev);
 
     if (RT_LIKELY(pDataAgg))
@@ -433,5 +517,5 @@
         {
             /* All data aggregated, write it out and reset the structure. */
-            rc = RTTraceLogWrEvtAdd(pThis->hTraceLog, &g_DevGCPhysRwDataEvtDesc, RTTRACELOG_WR_ADD_EVT_F_GRP_FINISH,
+            rc = RTTraceLogWrEvtAdd(pThis->hTraceLog, &g_DevRwDataEvtDesc, RTTRACELOG_WR_ADD_EVT_F_GRP_FINISH,
                                     pDataAgg->idEvtStart, pEvtHdr->hEvtSrc, pDataAgg->pbBuf, &pDataAgg->cbXfer);
             pDataAgg->offBuf     = 0;
@@ -543,4 +627,29 @@
                                      pEvtHdr->idEvt, pEvtHdr->hEvtSrc, pEvtIoPortRw->hIoPorts, pEvtIoPortRw->offPort,
                                      pEvtIoPortRw->cbXfer, pEvtIoPortRw->u32Val);
+            break;
+        }
+        case DBGFTRACEREVT_IOPORT_READ_STR:
+        case DBGFTRACEREVT_IOPORT_WRITE_STR:
+        {
+            PCRTTRACELOGEVTDESC pEvtDesc =   pEvtHdr->enmEvt == DBGFTRACEREVT_IOPORT_WRITE_STR
+                                           ? &g_DevIoPortWriteStrEvtDesc
+                                           : &g_DevIoPortReadStrEvtDesc;
+
+            /* If the previous event ID is invalid this starts a new read/write we have to aggregate all the data for. */
+            if (pEvtHdr->idEvtPrev == DBGF_TRACER_EVT_HDR_ID_INVALID)
+            {
+                PCDBGFTRACEREVTIOPORTSTR pEvtIoPortStrRw = (PCDBGFTRACEREVTIOPORTSTR)(pEvtHdr + 1);
+                size_t cbXfer =   pEvtHdr->enmEvt == DBGFTRACEREVT_IOPORT_WRITE_STR
+                                ? pEvtIoPortStrRw->cTransfersReq * pEvtIoPortStrRw->cbItem
+                                : pEvtIoPortStrRw->cTransfersRet * pEvtIoPortStrRw->cbItem;
+
+                rc = dbgfTracerR3EvtIoPortStrRwStart(pThis, pEvtHdr, pEvtIoPortStrRw, cbXfer, pEvtDesc);
+            }
+            else
+            {
+                /* Continuation of a started read or write, look up the right tracking structure and process the new data. */
+                void *pvData = pEvtHdr + 1;
+                rc = dbgfTracerR3EvtRwContinue(pThis, pEvtHdr, pvData);
+            }
             break;
         }
@@ -578,5 +687,5 @@
                 /* Continuation of a started read or write, look up the right tracking structure and process the new data. */
                 void *pvData = pEvtHdr + 1;
-                rc = dbgfTracerR3EvtGCPhysRwContinue(pThis, pEvtHdr, pvData);
+                rc = dbgfTracerR3EvtRwContinue(pThis, pEvtHdr, pvData);
             }
             break;
