summaryrefslogtreecommitdiffstats
path: root/src/VBox/VMM/VMMAll/DBGFAllTracer.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/VBox/VMM/VMMAll/DBGFAllTracer.cpp715
1 files changed, 715 insertions, 0 deletions
diff --git a/src/VBox/VMM/VMMAll/DBGFAllTracer.cpp b/src/VBox/VMM/VMMAll/DBGFAllTracer.cpp
new file mode 100644
index 00000000..8e79602b
--- /dev/null
+++ b/src/VBox/VMM/VMMAll/DBGFAllTracer.cpp
@@ -0,0 +1,715 @@
+/* $Id: DBGFAllTracer.cpp $ */
+/** @file
+ * DBGF - Debugger Facility, All Context Code tracing part.
+ */
+
+/*
+ * Copyright (C) 2020-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DBGF
+#include "DBGFInternal.h"
+#include <VBox/types.h>
+#include <VBox/err.h>
+#include <VBox/vmm/dbgf.h>
+#if defined(IN_RING3)
+# include <VBox/vmm/uvm.h>
+# include <VBox/vmm/vm.h>
+#elif defined(IN_RING0)
+# include <VBox/vmm/gvm.h>
+#else
+# error "Invalid environment"
+#endif
+
+
+/*********************************************************************************************************************************
+* Internal Functions *
+*********************************************************************************************************************************/
+
+/**
+ * Returns the current context tracer instance of the given VM instance.
+ *
+ * @returns Current context pointer to the DBGF tracer instance.
+ */
+DECLINLINE(PDBGFTRACERINSCC) dbgfTracerGetInstance(PVMCC pVM)
+{
+#if defined(IN_RING0)
+ return pVM->dbgfr0.s.pTracerR0;
+#elif defined(IN_RING3)
+ PUVM pUVM = pVM->pUVM;
+ return pUVM->dbgf.s.pTracerR3;
+#elif defined(IN_RC)
+# error "Not implemented"
+#else
+# error "No/Invalid context specified"
+#endif
+}
+
+
+/**
+ * Returns the size of the tracing ring buffer.
+ *
+ * @returns Size of the ring buffer in bytes.
+ * @param pThisCC The event tracer instance current context data.
+ */
+DECLINLINE(size_t) dbgfTracerGetRingBufSz(PDBGFTRACERINSCC pThisCC)
+{
+#if defined(IN_RING0) /* For R0 we are extra cautious and use the ring buffer size stored in R0 memory so R3 can't corrupt it. */
+ return pThisCC->cbRingBuf;
+#else
+ return pThisCC->CTX_SUFF(pShared)->cbRingBuf;
+#endif
+}
+
+
+/**
+ * Posts a single event descriptor to the ring buffer of the given tracer instance - extended version.
+ *
+ * @returns VBox status code.
+ * @param pVM The current context VM instance data.
+ * @param pThisCC The event tracer instance current context data.
+ * @param hEvtSrc The event source for the posted event.
+ * @param enmTraceEvt The trace event type posted.
+ * @param idEvtPrev The previous event ID the posted event links to.
+ * @param pvEvtDesc The event descriptor to copy after the header.
+ * @param cbEvtDesc Size of the event descriptor.
+ * @param pidEvt Where to store the assigned event ID, optional.
+ */
+static int dbgfTracerEvtPostEx(PVMCC pVM, PDBGFTRACERINSCC pThisCC, DBGFTRACEREVTSRC hEvtSrc,
+ DBGFTRACEREVT enmTraceEvt, uint64_t idEvtPrev, const void *pvEvtDesc,
+ size_t cbEvtDesc, uint64_t *pidEvt)
+{
+ LogFlowFunc(("pVM=%p pThisCC=%p hEvtSrc=%llu enmTraceEvt=%u idEvtPrev=%llu pvEvtDesc=%p cbEvtDesc=%zu pidEvt=%p\n",
+ pVM, pThisCC, hEvtSrc, enmTraceEvt, idEvtPrev, pvEvtDesc, cbEvtDesc, pidEvt));
+
+ PDBGFTRACERSHARED pSharedCC = pThisCC->CTX_SUFF(pShared);
+ size_t cRingBufEvts = dbgfTracerGetRingBufSz(pThisCC) / DBGF_TRACER_EVT_SZ;
+ AssertReturn(cRingBufEvts, VERR_DBGF_TRACER_IPE_1);
+ AssertReturn(cbEvtDesc <= DBGF_TRACER_EVT_PAYLOAD_SZ, VERR_DBGF_TRACER_IPE_1);
+
+ /* Grab a new event ID first. */
+ uint64_t idEvt = ASMAtomicIncU64(&pSharedCC->idEvt) - 1;
+ uint64_t idxRingBuf = idEvt % cRingBufEvts; /* This gives the index in the ring buffer for the event. */
+ PDBGFTRACEREVTHDR pEvtHdr = (PDBGFTRACEREVTHDR)(pThisCC->CTX_SUFF(pbRingBuf) + idxRingBuf * DBGF_TRACER_EVT_SZ);
+
+ if (RT_UNLIKELY(ASMAtomicReadU64(&pEvtHdr->idEvt) != DBGF_TRACER_EVT_HDR_ID_INVALID))
+ {
+ /** @todo The event ring buffer is full and we need to go back (from R0 to R3) and wait for the flusher thread to
+ * get its act together.
+ */
+ AssertMsgFailed(("Flush thread can't keep up with event amount!\n"));
+ }
+
+ /* Write the event and kick the flush thread if necessary. */
+ if (cbEvtDesc)
+ memcpy(pEvtHdr + 1, pvEvtDesc, cbEvtDesc);
+ pEvtHdr->idEvtPrev = idEvtPrev;
+ pEvtHdr->hEvtSrc = hEvtSrc;
+ pEvtHdr->enmEvt = enmTraceEvt;
+ pEvtHdr->fFlags = DBGF_TRACER_EVT_HDR_F_DEFAULT;
+ ASMAtomicWriteU64(&pEvtHdr->idEvt, idEvt);
+
+ int rc = VINF_SUCCESS;
+ if (!ASMAtomicXchgBool(&pSharedCC->fEvtsWaiting, true))
+ {
+ if (!ASMAtomicXchgBool(&pSharedCC->fFlushThrdActive, true))
+ rc = SUPSemEventSignal(pVM->pSession, pSharedCC->hSupSemEvtFlush);
+ }
+
+ if (pidEvt)
+ *pidEvt = idEvt;
+ return rc;
+}
+
+
+/**
+ * Posts a single event descriptor to the ring buffer of the given tracer instance.
+ *
+ * @returns VBox status code.
+ * @param pVM The current context VM instance data.
+ * @param pThisCC The event tracer instance current context data.
+ * @param hEvtSrc The event source for the posted event.
+ * @param enmTraceEvt The trace event type posted.
+ * @param pvEvtDesc The event descriptor to copy after the header.
+ * @param pidEvt Where to store the assigned event ID, optional.
+ */
+DECLINLINE(int) dbgfTracerEvtPostSingle(PVMCC pVM, PDBGFTRACERINSCC pThisCC, DBGFTRACEREVTSRC hEvtSrc,
+ DBGFTRACEREVT enmTraceEvt, const void *pvEvtDesc, uint64_t *pidEvt)
+{
+ return dbgfTracerEvtPostEx(pVM, pThisCC, hEvtSrc, enmTraceEvt, DBGF_TRACER_EVT_HDR_ID_INVALID,
+ pvEvtDesc, DBGF_TRACER_EVT_PAYLOAD_SZ, pidEvt);
+}
+
+
+#ifdef IN_RING3
+/**
+ * Posts a single event descriptor to the ring buffer of the given tracer instance - R3 only variant
+ * (used for the register/deregister event source events currently).
+ *
+ * @returns VBox status code.
+ * @param pVM The current context VM instance data.
+ * @param pThisCC The event tracer instance current context data.
+ * @param hEvtSrc The event source for the posted event.
+ * @param enmTraceEvt The trace event type posted.
+ * @param pvEvtDesc The event descriptor to copy after the header.
+ * @param cbEvtDesc Event descriptor size in bytes.
+ * @param pidEvt Where to store the assigned event ID, optional.
+ */
+DECLHIDDEN(int) dbgfTracerR3EvtPostSingle(PVMCC pVM, PDBGFTRACERINSCC pThisCC, DBGFTRACEREVTSRC hEvtSrc,
+ DBGFTRACEREVT enmTraceEvt, const void *pvEvtDesc, size_t cbEvtDesc,
+ uint64_t *pidEvt)
+{
+ return dbgfTracerEvtPostEx(pVM, pThisCC, hEvtSrc, enmTraceEvt, DBGF_TRACER_EVT_HDR_ID_INVALID,
+ pvEvtDesc, cbEvtDesc, pidEvt);
+}
+#endif
+
+/**
+ * Copies the given MMIO value into the event descriptor based on the given size.
+ *
+ * @param pEvtMmio Pointer to the MMIO event descriptor to fill.
+ * @param pvVal The value to copy.
+ * @param cbVal Size of the value in bytes.
+ */
+static void dbgfTracerEvtMmioCopyVal(PDBGFTRACEREVTMMIO pEvtMmio, const void *pvVal, size_t cbVal)
+{
+ switch (cbVal)
+ {
+ case 1:
+ pEvtMmio->u64Val = *(uint8_t *)pvVal;
+ break;
+ case 2:
+ pEvtMmio->u64Val = *(uint16_t *)pvVal;
+ break;
+ case 4:
+ pEvtMmio->u64Val = *(uint32_t *)pvVal;
+ break;
+ case 8:
+ pEvtMmio->u64Val = *(uint64_t *)pvVal;
+ break;
+ default:
+ AssertMsgFailed(("The value size %zu is not supported!\n", cbVal));
+ }
+}
+
+
+/**
+ * Copies the given I/O port value into the event descriptor based on the given size.
+ *
+ * @param pEvtIoPort Pointer to the I/O port read/write event descriptor to fill.
+ * @param pvVal The value to copy.
+ * @param cbVal Size of the value in bytes.
+ */
+static void dbgfTracerEvtIoPortCopyVal(PDBGFTRACEREVTIOPORT pEvtIoPort, const void *pvVal, size_t cbVal)
+{
+ switch (cbVal)
+ {
+ case 1:
+ pEvtIoPort->u32Val = *(uint8_t *)pvVal;
+ break;
+ case 2:
+ pEvtIoPort->u32Val = *(uint16_t *)pvVal;
+ break;
+ case 4:
+ pEvtIoPort->u32Val = *(uint32_t *)pvVal;
+ break;
+ default:
+ AssertMsgFailed(("The value size %zu is not supported!\n", cbVal));
+ }
+}
+
+
+/**
+ * Handles a guest memory 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 GCPhys The guest physical address the transfer starts at.
+ * @param pvBuf The data being transfered.
+ * @param cbXfer Number of bytes being transfered.
+ */
+static int dbgfTracerEvtGCPhys(PVMCC pVM, PDBGFTRACERINSCC pThisCC, DBGFTRACEREVT enmTraceEvt, DBGFTRACEREVTSRC hEvtSrc,
+ RTGCPHYS GCPhys, const void *pvBuf, size_t cbXfer)
+{
+ /* Fast path for really small transfers where everything fits into the descriptor. */
+ DBGFTRACEREVTGCPHYS EvtGCPhys;
+ EvtGCPhys.GCPhys = GCPhys;
+ EvtGCPhys.cbXfer = cbXfer;
+ if (cbXfer <= sizeof(EvtGCPhys.abData))
+ {
+ memcpy(&EvtGCPhys.abData[0], pvBuf, cbXfer);
+ return dbgfTracerEvtPostSingle(pVM, pThisCC, hEvtSrc, enmTraceEvt, &EvtGCPhys, 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 *)pvBuf;
+ size_t cbLeft = cbXfer;
+ uint64_t idEvtPrev = 0;
+ memcpy(&EvtGCPhys.abData[0], pbBuf, sizeof(EvtGCPhys.abData));
+ pbBuf += sizeof(EvtGCPhys.abData);
+ cbLeft -= sizeof(EvtGCPhys.abData);
+
+ int rc = dbgfTracerEvtPostSingle(pVM, pThisCC, hEvtSrc, enmTraceEvt, &EvtGCPhys, &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;
+}
+
+
+/**
+ * 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 = (uint32_t)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.
+ *
+ * @returns VBox status code.
+ * @param pVM The current context VM instance data.
+ * @param hEvtSrc The event source for the posted event.
+ * @param hRegion The MMIO region handle being mapped.
+ * @param GCPhysMmio The guest physical address where the region is mapped.
+ */
+VMM_INT_DECL(int) DBGFTracerEvtMmioMap(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hRegion, RTGCPHYS GCPhysMmio)
+{
+ PDBGFTRACERINSCC pThisCC = dbgfTracerGetInstance(pVM);
+ AssertReturn(pThisCC, VERR_DBGF_TRACER_IPE_1);
+
+ DBGFTRACEREVTMMIOMAP EvtMmioMap;
+ EvtMmioMap.hMmioRegion = hRegion;
+ EvtMmioMap.GCPhysMmioBase = GCPhysMmio;
+ EvtMmioMap.au64Pad0[0] = 0;
+ EvtMmioMap.au64Pad0[1] = 0;
+
+ return dbgfTracerEvtPostSingle(pVM, pThisCC, hEvtSrc, DBGFTRACEREVT_MMIO_MAP, &EvtMmioMap, NULL /*pidEvt*/);
+}
+
+
+/**
+ * Registers an MMIO region unmap 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 hRegion The MMIO region handle being unmapped.
+ */
+VMM_INT_DECL(int) DBGFTracerEvtMmioUnmap(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hRegion)
+{
+ PDBGFTRACERINSCC pThisCC = dbgfTracerGetInstance(pVM);
+ AssertReturn(pThisCC, VERR_DBGF_TRACER_IPE_1);
+
+ DBGFTRACEREVTMMIOUNMAP EvtMmioUnmap;
+ EvtMmioUnmap.hMmioRegion = hRegion;
+ EvtMmioUnmap.au64Pad0[0] = 0;
+ EvtMmioUnmap.au64Pad0[1] = 0;
+ EvtMmioUnmap.au64Pad0[2] = 0;
+
+ return dbgfTracerEvtPostSingle(pVM, pThisCC, hEvtSrc, DBGFTRACEREVT_MMIO_UNMAP, &EvtMmioUnmap, NULL /*pidEvt*/);
+}
+
+
+/**
+ * Registers an MMIO region 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 hRegion The MMIO region handle being read.
+ * @param offMmio The MMIO offset into the region where the read happened.
+ * @param pvVal The value being read.
+ * @param cbVal Value size in bytes.
+ */
+VMM_INT_DECL(int) DBGFTracerEvtMmioRead(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hRegion, RTGCPHYS offMmio, const void *pvVal, size_t cbVal)
+{
+ PDBGFTRACERINSCC pThisCC = dbgfTracerGetInstance(pVM);
+ AssertReturn(pThisCC, VERR_DBGF_TRACER_IPE_1);
+
+ DBGFTRACEREVTMMIO EvtMmio;
+ EvtMmio.hMmioRegion = hRegion;
+ EvtMmio.offMmio = offMmio;
+ EvtMmio.cbXfer = cbVal;
+ dbgfTracerEvtMmioCopyVal(&EvtMmio, pvVal, cbVal);
+
+ return dbgfTracerEvtPostSingle(pVM, pThisCC, hEvtSrc, DBGFTRACEREVT_MMIO_READ, &EvtMmio, NULL /*pidEvt*/);
+}
+
+
+/**
+ * Registers an MMIO region 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 hRegion The MMIO region handle being written to.
+ * @param offMmio The MMIO offset into the region where the write happened.
+ * @param pvVal The value being written.
+ * @param cbVal Value size in bytes.
+ */
+VMM_INT_DECL(int) DBGFTracerEvtMmioWrite(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hRegion, RTGCPHYS offMmio, const void *pvVal, size_t cbVal)
+{
+ PDBGFTRACERINSCC pThisCC = dbgfTracerGetInstance(pVM);
+ AssertReturn(pThisCC, VERR_DBGF_TRACER_IPE_1);
+
+ DBGFTRACEREVTMMIO EvtMmio;
+ EvtMmio.hMmioRegion = hRegion;
+ EvtMmio.offMmio = offMmio;
+ EvtMmio.cbXfer = cbVal;
+ dbgfTracerEvtMmioCopyVal(&EvtMmio, pvVal, cbVal);
+
+ return dbgfTracerEvtPostSingle(pVM, pThisCC, hEvtSrc, DBGFTRACEREVT_MMIO_WRITE, &EvtMmio, NULL /*pidEvt*/);
+}
+
+
+/**
+ * Registers an MMIO region fill 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 hRegion The MMIO region handle being filled.
+ * @param offMmio The MMIO offset into the region where the fill starts.
+ * @param u32Item The value being used for filling.
+ * @param cbItem Item size in bytes.
+ * @param cItems Number of items being written.
+ */
+VMM_INT_DECL(int) DBGFTracerEvtMmioFill(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hRegion, RTGCPHYS offMmio,
+ uint32_t u32Item, uint32_t cbItem, uint32_t cItems)
+{
+ PDBGFTRACERINSCC pThisCC = dbgfTracerGetInstance(pVM);
+ AssertReturn(pThisCC, VERR_DBGF_TRACER_IPE_1);
+
+ DBGFTRACEREVTMMIOFILL EvtMmioFill;
+ EvtMmioFill.hMmioRegion = hRegion;
+ EvtMmioFill.offMmio = offMmio;
+ EvtMmioFill.cbItem = cbItem;
+ EvtMmioFill.cItems = cItems;
+ EvtMmioFill.u32Item = u32Item;
+ EvtMmioFill.u32Pad0 = 0;
+
+ return dbgfTracerEvtPostSingle(pVM, pThisCC, hEvtSrc, DBGFTRACEREVT_MMIO_FILL, &EvtMmioFill, NULL /*pidEvt*/);
+}
+
+
+/**
+ * Registers an I/O region mapping 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 mapped.
+ * @param IoPortBase The I/O port base where the region is mapped.
+ */
+VMM_INT_DECL(int) DBGFTracerEvtIoPortMap(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hIoPorts, RTIOPORT IoPortBase)
+{
+ PDBGFTRACERINSCC pThisCC = dbgfTracerGetInstance(pVM);
+ AssertReturn(pThisCC, VERR_DBGF_TRACER_IPE_1);
+
+ DBGFTRACEREVTIOPORTMAP EvtIoPortMap;
+ RT_ZERO(EvtIoPortMap);
+ EvtIoPortMap.hIoPorts = hIoPorts;
+ EvtIoPortMap.IoPortBase = IoPortBase;
+
+ return dbgfTracerEvtPostSingle(pVM, pThisCC, hEvtSrc, DBGFTRACEREVT_IOPORT_MAP, &EvtIoPortMap, NULL /*pidEvt*/);
+}
+
+
+/**
+ * Registers an I/O region unmap 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 unmapped.
+ */
+VMM_INT_DECL(int) DBGFTracerEvtIoPortUnmap(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hIoPorts)
+{
+ PDBGFTRACERINSCC pThisCC = dbgfTracerGetInstance(pVM);
+ AssertReturn(pThisCC, VERR_DBGF_TRACER_IPE_1);
+
+ DBGFTRACEREVTIOPORTUNMAP EvtIoPortUnmap;
+ EvtIoPortUnmap.hIoPorts = hIoPorts;
+ EvtIoPortUnmap.au64Pad0[0] = 0;
+ EvtIoPortUnmap.au64Pad0[1] = 0;
+ EvtIoPortUnmap.au64Pad0[2] = 0;
+
+ return dbgfTracerEvtPostSingle(pVM, pThisCC, hEvtSrc, DBGFTRACEREVT_IOPORT_UNMAP, &EvtIoPortUnmap, NULL /*pidEvt*/);
+}
+
+
+/**
+ * Registers an I/O region 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 pvVal The value being read.
+ * @param cbVal Value size in bytes.
+ */
+VMM_INT_DECL(int) DBGFTracerEvtIoPortRead(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hIoPorts, RTIOPORT offPort, const void *pvVal, size_t cbVal)
+{
+ PDBGFTRACERINSCC pThisCC = dbgfTracerGetInstance(pVM);
+ AssertReturn(pThisCC, VERR_DBGF_TRACER_IPE_1);
+
+ DBGFTRACEREVTIOPORT EvtIoPort;
+ RT_ZERO(EvtIoPort);
+ EvtIoPort.hIoPorts = hIoPorts;
+ EvtIoPort.offPort = offPort;
+ EvtIoPort.cbXfer = cbVal;
+ dbgfTracerEvtIoPortCopyVal(&EvtIoPort, pvVal, cbVal);
+
+ return dbgfTracerEvtPostSingle(pVM, pThisCC, hEvtSrc, DBGFTRACEREVT_IOPORT_READ, &EvtIoPort, NULL /*pidEvt*/);
+}
+
+
+/**
+ * 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.
+ *
+ * @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 pvVal The value being written.
+ * @param cbVal Value size in bytes.
+ */
+VMM_INT_DECL(int) DBGFTracerEvtIoPortWrite(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hIoPorts, RTIOPORT offPort, const void *pvVal, size_t cbVal)
+{
+ PDBGFTRACERINSCC pThisCC = dbgfTracerGetInstance(pVM);
+ AssertReturn(pThisCC, VERR_DBGF_TRACER_IPE_1);
+
+ DBGFTRACEREVTIOPORT EvtIoPort;
+ RT_ZERO(EvtIoPort);
+ EvtIoPort.hIoPorts = hIoPorts;
+ EvtIoPort.offPort = offPort;
+ EvtIoPort.cbXfer = cbVal;
+ dbgfTracerEvtIoPortCopyVal(&EvtIoPort, pvVal, cbVal);
+
+ return dbgfTracerEvtPostSingle(pVM, pThisCC, hEvtSrc, DBGFTRACEREVT_IOPORT_WRITE, &EvtIoPort, NULL /*pidEvt*/);
+}
+
+
+/**
+ * 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.
+ *
+ * @returns VBox status code.
+ * @param pVM The current context VM instance data.
+ * @param hEvtSrc The event source for the posted event.
+ * @param iIrq The IRQ line changed.
+ * @param fIrqLvl The new IRQ level mask.
+ */
+VMM_INT_DECL(int) DBGFTracerEvtIrq(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, int32_t iIrq, int32_t fIrqLvl)
+{
+ PDBGFTRACERINSCC pThisCC = dbgfTracerGetInstance(pVM);
+ AssertReturn(pThisCC, VERR_DBGF_TRACER_IPE_1);
+
+ DBGFTRACEREVTIRQ EvtIrq;
+ RT_ZERO(EvtIrq);
+ EvtIrq.iIrq = iIrq;
+ EvtIrq.fIrqLvl = fIrqLvl;
+
+ return dbgfTracerEvtPostSingle(pVM, pThisCC, hEvtSrc, DBGFTRACEREVT_IRQ, &EvtIrq, NULL /*pidEvt*/);
+}
+
+
+/**
+ * Registers an I/O APIC MSI 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 GCPhys Guest physical address where the value is written to.
+ * @param u32Val The MSI event value being written.
+ */
+VMM_INT_DECL(int) DBGFTracerEvtIoApicMsi(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, RTGCPHYS GCPhys, uint32_t u32Val)
+{
+ PDBGFTRACERINSCC pThisCC = dbgfTracerGetInstance(pVM);
+ AssertReturn(pThisCC, VERR_DBGF_TRACER_IPE_1);
+
+ DBGFTRACEREVTIOAPICMSI EvtMsi;
+ RT_ZERO(EvtMsi);
+ EvtMsi.GCPhys = GCPhys;
+ EvtMsi.u32Val = u32Val;
+
+ return dbgfTracerEvtPostSingle(pVM, pThisCC, hEvtSrc, DBGFTRACEREVT_IOAPIC_MSI, &EvtMsi, NULL /*pidEvt*/);
+}
+
+
+/**
+ * Registers an guest physical memory 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 GCPhys Guest physical address the read started at.
+ * @param pvBuf The read data.
+ * @param cbRead Number of bytes read.
+ */
+VMM_INT_DECL(int) DBGFTracerEvtGCPhysRead(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, RTGCPHYS GCPhys, const void *pvBuf, size_t cbRead)
+{
+ PDBGFTRACERINSCC pThisCC = dbgfTracerGetInstance(pVM);
+ AssertReturn(pThisCC, VERR_DBGF_TRACER_IPE_1);
+
+ return dbgfTracerEvtGCPhys(pVM, pThisCC, DBGFTRACEREVT_GCPHYS_READ, hEvtSrc, GCPhys, pvBuf, cbRead);
+}
+
+
+/**
+ * Registers an guest physical memory 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 GCPhys Guest physical address the write started at.
+ * @param pvBuf The written data.
+ * @param cbWrite Number of bytes written.
+ */
+VMM_INT_DECL(int) DBGFTracerEvtGCPhysWrite(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
+{
+ PDBGFTRACERINSCC pThisCC = dbgfTracerGetInstance(pVM);
+ AssertReturn(pThisCC, VERR_DBGF_TRACER_IPE_1);
+
+ return dbgfTracerEvtGCPhys(pVM, pThisCC, DBGFTRACEREVT_GCPHYS_WRITE, hEvtSrc, GCPhys, pvBuf, cbWrite);
+}
+