VirtualBox

Changeset 84458 in vbox for trunk/src/VBox/VMM/include


Ignore:
Timestamp:
May 22, 2020 12:51:49 PM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
138165
Message:

VMM/DBGF: First commit of new tracing facility, bugref:9210

The new DBGF tracing facility allows efficient capturing of events to a compact binary
trace log for later analysis. It is primarily intended for recording device/guest
interactions for now but can be extended easily for other types of events later on.
It supports capturing events happening in both R0 and R3 by using a shared ring buffer
to post events to. The events are processed by a dedicated I/O thread which writes
new events into the binary trace log file.

This is only the core VMM/DBGF part providing the API, the integration with PDM
comes in a separate commit.

Disabled by default for now because it is still work in progress,
enable with VBOX_WITH_DBGF_TRACING.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/include/DBGFInternal.h

    r82968 r84458  
    3232#include <iprt/avl.h>
    3333#include <iprt/dbg.h>
     34#include <iprt/tracelog.h>
    3435#include <VBox/vmm/dbgf.h>
    3536
     
    4142 * @{
    4243 */
     44
     45/** The maximum tracer instance (total) size, ring-0/raw-mode capable tracers. */
     46#define DBGF_MAX_TRACER_INSTANCE_SIZE    _8M
     47/** The maximum tracers instance (total) size, ring-3 only tracers. */
     48#define DBGF_MAX_TRACER_INSTANCE_SIZE_R3 _16M
     49/** Event ringbuffer header size. */
     50#define DBGF_TRACER_EVT_HDR_SZ           (32)
     51/** Event ringbuffer payload size. */
     52#define DBGF_TRACER_EVT_PAYLOAD_SZ       (32)
     53/** Event ringbuffer entry size. */
     54#define DBGF_TRACER_EVT_SZ               (DBGF_TRACER_EVT_HDR_SZ + DBGF_TRACER_EVT_PAYLOAD_SZ)
     55
     56
     57
     58/*******************************************************************************
     59*   Structures and Typedefs                                                    *
     60*******************************************************************************/
     61
     62/**
     63 * Event entry types.
     64 */
     65typedef enum DBGFTRACEREVT
     66{
     67    /** Invalid type. */
     68    DBGFTRACEREVT_INVALID = 0,
     69    /** MMIO map region event. */
     70    DBGFTRACEREVT_MMIO_MAP,
     71    /** MMIO unmap region event. */
     72    DBGFTRACEREVT_MMIO_UNMAP,
     73    /** MMIO read event. */
     74    DBGFTRACEREVT_MMIO_READ,
     75    /** MMIO write event. */
     76    DBGFTRACEREVT_MMIO_WRITE,
     77    /** MMIO fill event. */
     78    DBGFTRACEREVT_MMIO_FILL,
     79    /** I/O port map event. */
     80    DBGFTRACEREVT_IOPORT_MAP,
     81    /** I/O port unmap event. */
     82    DBGFTRACEREVT_IOPORT_UNMAP,
     83    /** I/O port read event. */
     84    DBGFTRACEREVT_IOPORT_READ,
     85    /** I/O port write event. */
     86    DBGFTRACEREVT_IOPORT_WRITE,
     87    /** IRQ event. */
     88    DBGFTRACEREVT_IRQ,
     89    /** I/O APIC MSI event. */
     90    DBGFTRACEREVT_IOAPIC_MSI,
     91    /** Read from guest physical memory. */
     92    DBGFTRACEREVT_GCPHYS_READ,
     93    /** Write to guest physical memory. */
     94    DBGFTRACEREVT_GCPHYS_WRITE,
     95    /** 32bit hack. */
     96    DBGFTRACEREVT_32BIT_HACK
     97} DBGFTRACEREVT;
     98/** Pointer to a trace event entry type. */
     99typedef DBGFTRACEREVT *PDBGFTRACEREVT;
     100
     101
     102/**
     103 * MMIO region map event.
     104 */
     105typedef struct DBGFTRACEREVTMMIOMAP
     106{
     107    /** Unique region handle for the event source. */
     108    uint64_t                                hMmioRegion;
     109    /** The base guest physical address of the MMIO region. */
     110    RTGCPHYS                                GCPhysMmioBase;
     111    /** Padding to 32byte. */
     112    uint64_t                                au64Pad0[2];
     113} DBGFTRACEREVTMMIOMAP;
     114/** Pointer to a MMIO map event. */
     115typedef DBGFTRACEREVTMMIOMAP *PDBGFTRACEREVTMMIOMAP;
     116/** Pointer to a const MMIO map event. */
     117typedef const DBGFTRACEREVTMMIOMAP *PCDBGFTRACEREVTMMIOMAP;
     118
     119AssertCompileSize(DBGFTRACEREVTMMIOMAP, DBGF_TRACER_EVT_PAYLOAD_SZ);
     120
     121
     122/**
     123 * MMIO region unmap event.
     124 */
     125typedef struct DBGFTRACEREVTMMIOUNMAP
     126{
     127    /** Unique region handle for the event source. */
     128    uint64_t                                hMmioRegion;
     129    /** Padding to 32byte. */
     130    uint64_t                                au64Pad0[3];
     131} DBGFTRACEREVTMMIOUNMAP;
     132/** Pointer to a MMIO map event. */
     133typedef DBGFTRACEREVTMMIOUNMAP *PDBGFTRACEREVTMMIOUNMAP;
     134/** Pointer to a const MMIO map event. */
     135typedef const DBGFTRACEREVTMMIOUNMAP *PCDBGFTRACEREVTMMIOUNMAP;
     136
     137AssertCompileSize(DBGFTRACEREVTMMIOUNMAP, DBGF_TRACER_EVT_PAYLOAD_SZ);
     138
     139
     140/**
     141 * MMIO event.
     142 */
     143typedef struct DBGFTRACEREVTMMIO
     144{
     145    /** Unique region handle for the event source. */
     146    uint64_t                                hMmioRegion;
     147    /** Offset into the region the access happened. */
     148    RTGCPHYS                                offMmio;
     149    /** Number of bytes transfered (the direction is in the event header). */
     150    uint64_t                                cbXfer;
     151    /** The value transfered. */
     152    uint64_t                                u64Val;
     153} DBGFTRACEREVTMMIO;
     154/** Pointer to a MMIO event. */
     155typedef DBGFTRACEREVTMMIO *PDBGFTRACEREVTMMIO;
     156/** Pointer to a const MMIO event. */
     157typedef const DBGFTRACEREVTMMIO *PCDBGFTRACEREVTMMIO;
     158
     159AssertCompileSize(DBGFTRACEREVTMMIO, DBGF_TRACER_EVT_PAYLOAD_SZ);
     160
     161
     162/**
     163 * MMIO fill event.
     164 */
     165typedef struct DBGFTRACEREVTMMIOFILL
     166{
     167    /** Unique region handle for the event source. */
     168    uint64_t                                hMmioRegion;
     169    /** Offset into the region the access happened. */
     170    RTGCPHYS                                offMmio;
     171    /** Item size in bytes. */
     172    uint32_t                                cbItem;
     173    /** Amount of items being filled. */
     174    uint32_t                                cItems;
     175    /** The fill value. */
     176    uint32_t                                u32Item;
     177    /** Padding to 32bytes. */
     178    uint32_t                                u32Pad0;
     179} DBGFTRACEREVTMMIOFILL;
     180/** Pointer to a MMIO event. */
     181typedef DBGFTRACEREVTMMIOFILL *PDBGFTRACEREVTMMIOFILL;
     182/** Pointer to a const MMIO event. */
     183typedef const DBGFTRACEREVTMMIOFILL *PCDBGFTRACEREVTMMIOFILL;
     184
     185AssertCompileSize(DBGFTRACEREVTMMIOFILL, DBGF_TRACER_EVT_PAYLOAD_SZ);
     186
     187
     188/**
     189 * I/O port region map event.
     190 */
     191typedef struct DBGFTRACEREVTIOPORTMAP
     192{
     193    /** Unique I/O port region handle for the event source. */
     194    uint64_t                                hIoPorts;
     195    /** The base I/O port for the region. */
     196    RTIOPORT                                IoPortBase;
     197    /** Padding to 32byte. */
     198    uint16_t                                au16Pad0[11];
     199} DBGFTRACEREVTIOPORTMAP;
     200/** Pointer to a MMIO map event. */
     201typedef DBGFTRACEREVTIOPORTMAP *PDBGFTRACEREVTIOPORTMAP;
     202/** Pointer to a const MMIO map event. */
     203typedef const DBGFTRACEREVTIOPORTMAP *PCDBGFTRACEREVTIOPORTMAP;
     204
     205AssertCompileSize(DBGFTRACEREVTIOPORTMAP, DBGF_TRACER_EVT_PAYLOAD_SZ);
     206
     207
     208/**
     209 * MMIO region unmap event.
     210 */
     211typedef struct DBGFTRACEREVTIOPORTUNMAP
     212{
     213    /** Unique region handle for the event source. */
     214    uint64_t                                hIoPorts;
     215    /** Padding to 32byte. */
     216    uint64_t                                au64Pad0[3];
     217} DBGFTRACEREVTIOPORTUNMAP;
     218/** Pointer to a MMIO map event. */
     219typedef DBGFTRACEREVTIOPORTUNMAP *PDBGFTRACEREVTIOPORTUNMAP;
     220/** Pointer to a const MMIO map event. */
     221typedef const DBGFTRACEREVTIOPORTUNMAP *PCDBGFTRACEREVTIOPORTUNMAP;
     222
     223AssertCompileSize(DBGFTRACEREVTIOPORTUNMAP, DBGF_TRACER_EVT_PAYLOAD_SZ);
     224
     225
     226/**
     227 * I/O port event.
     228 */
     229typedef struct DBGFTRACEREVTIOPORT
     230{
     231    /** Unique region handle for the event source. */
     232    uint64_t                                hIoPorts;
     233    /** Offset into the I/O port region. */
     234    RTIOPORT                                offPort;
     235    /** 8 byte alignment. */
     236    uint8_t                                 abPad0[6];
     237    /** Number of bytes transfered (the direction is in the event header). */
     238    uint64_t                                cbXfer;
     239    /** The value transfered. */
     240    uint32_t                                u32Val;
     241    /** Padding to 32bytes. */
     242    uint8_t                                 abPad1[4];
     243} DBGFTRACEREVTIOPORT;
     244/** Pointer to a MMIO event. */
     245typedef DBGFTRACEREVTIOPORT *PDBGFTRACEREVTIOPORT;
     246/** Pointer to a const MMIO event. */
     247typedef const DBGFTRACEREVTIOPORT *PCDBGFTRACEREVTIOPORT;
     248
     249AssertCompileSize(DBGFTRACEREVTIOPORT, DBGF_TRACER_EVT_PAYLOAD_SZ);
     250
     251
     252/**
     253 * IRQ event.
     254 */
     255typedef struct DBGFTRACEREVTIRQ
     256{
     257    /** The IRQ line. */
     258    int32_t                                 iIrq;
     259    /** IRQ level flags. */
     260    int32_t                                 fIrqLvl;
     261    /** Padding to 32bytes. */
     262    uint32_t                                au32Pad0[6];
     263} DBGFTRACEREVTIRQ;
     264/** Pointer to a MMIO event. */
     265typedef DBGFTRACEREVTIRQ *PDBGFTRACEREVTIRQ;
     266/** Pointer to a const MMIO event. */
     267typedef const DBGFTRACEREVTIRQ *PCDBGFTRACEREVTIRQ;
     268
     269AssertCompileSize(DBGFTRACEREVTIRQ, DBGF_TRACER_EVT_PAYLOAD_SZ);
     270
     271
     272/**
     273 * I/O APIC MSI event.
     274 */
     275typedef struct DBGFTRACEREVTIOAPICMSI
     276{
     277    /** The guest physical address being written. */
     278    RTGCPHYS                                GCPhys;
     279    /** The value being written. */
     280    uint32_t                                u32Val;
     281    /** Padding to 32bytes. */
     282    uint32_t                                au32Pad0[5];
     283} DBGFTRACEREVTIOAPICMSI;
     284/** Pointer to a MMIO event. */
     285typedef DBGFTRACEREVTIOAPICMSI *PDBGFTRACEREVTIOAPICMSI;
     286/** Pointer to a const MMIO event. */
     287typedef const DBGFTRACEREVTIOAPICMSI *PCDBGFTRACEREVTIOAPICMSI;
     288
     289AssertCompileSize(DBGFTRACEREVTIOAPICMSI, DBGF_TRACER_EVT_PAYLOAD_SZ);
     290
     291
     292/**
     293 * Guest physical memory transfer.
     294 */
     295typedef struct DBGFTRACEREVTGCPHYS
     296{
     297    /** Guest physical address of the access. */
     298    RTGCPHYS                                GCPhys;
     299    /** Number of bytes transfered (the direction is in the event header).
     300     * If the number is small enough to fit into the remaining space of the entry
     301     * it is stored here, otherwise it will be stored in the next entry (and following
     302     * entries). */
     303    uint64_t                                cbXfer;
     304    /** Guest data being transfered. */
     305    uint8_t                                 abData[16];
     306} DBGFTRACEREVTGCPHYS;
     307/** Pointer to a guest physical memory transfer event. */
     308typedef DBGFTRACEREVTGCPHYS *PDBGFTRACEREVTGCPHYS;
     309/** Pointer to a const uest physical memory transfer event. */
     310typedef const DBGFTRACEREVTGCPHYS *PCDBGFTRACEREVTGCPHYS;
     311
     312AssertCompileSize(DBGFTRACEREVTGCPHYS, DBGF_TRACER_EVT_PAYLOAD_SZ);
     313
     314
     315/**
     316 * A trace event header in the shared ring buffer.
     317 */
     318typedef struct DBGFTRACEREVTHDR
     319{
     320    /** Event ID. */
     321    volatile uint64_t                       idEvt;
     322    /** The previous event ID this one links to,
     323     * DBGF_TRACER_EVT_HDR_ID_INVALID if it links to no other event. */
     324    uint64_t                                idEvtPrev;
     325    /** Event source. */
     326    DBGFTRACEREVTSRC                        hEvtSrc;
     327    /** The event entry type. */
     328    DBGFTRACEREVT                           enmEvt;
     329    /** Flags for this event. */
     330    uint32_t                                fFlags;
     331} DBGFTRACEREVTHDR;
     332/** Pointer to a trace event header. */
     333typedef DBGFTRACEREVTHDR *PDBGFTRACEREVTHDR;
     334/** Pointer to a const trace event header. */
     335typedef const DBGFTRACEREVTHDR *PCDBGFTRACEREVTHDR;
     336
     337AssertCompileSize(DBGFTRACEREVTHDR, DBGF_TRACER_EVT_HDR_SZ);
     338
     339/** Invalid event ID, this is always set by the flush thread after processing one entry
     340 * so the producers know when they are about to overwrite not yet processed entries in the ring buffer. */
     341#define DBGF_TRACER_EVT_HDR_ID_INVALID      UINT64_C(0xffffffffffffffff)
     342
     343/** The event came from R0. */
     344#define DBGF_TRACER_EVT_HDR_F_R0            RT_BIT(0)
     345
     346/** Default event header tracer flags. */
     347#ifdef IN_RING0
     348# define DBGF_TRACER_EVT_HDR_F_DEFAULT      DBGF_TRACER_EVT_HDR_F_R0
     349#else
     350# define DBGF_TRACER_EVT_HDR_F_DEFAULT      (0)
     351#endif
     352
     353
     354/**
     355 * Tracer instance data, shared structure.
     356 */
     357typedef struct DBGFTRACERSHARED
     358{
     359    /** The global event ID counter, monotonically increasing.
     360     * Accessed by all threads causing a trace event. */
     361    volatile uint64_t                       idEvt;
     362    /** The SUP event semaphore for poking the flush thread. */
     363    SUPSEMEVENT                             hSupSemEvtFlush;
     364    /** Ring buffer size. */
     365    size_t                                  cbRingBuf;
     366    /** Flag whether there are events in the ring buffer to get processed. */
     367    volatile bool                           fEvtsWaiting;
     368    /** Flag whether the flush thread is actively running or was kicked. */
     369    volatile bool                           fFlushThrdActive;
     370    /** Padding to a 64byte alignment. */
     371    uint8_t                                 abAlignment0[32];
     372} DBGFTRACERSHARED;
     373/** Pointer to the shared tarcer instance data. */
     374typedef DBGFTRACERSHARED *PDBGFTRACERSHARED;
     375
     376AssertCompileSizeAlignment(DBGFTRACERSHARED, 64);
     377
     378
     379/**
     380 * Tracer instance data, ring-3
     381 */
     382typedef struct DBGFTRACERINSR3
     383{
     384    /** Pointer to the next instance.
     385     * (Head is pointed to by PDM::pTracerInstances.) */
     386    R3PTRTYPE(struct DBGFTRACERINSR3 *)     pNextR3;
     387    /** R3 pointer to the VM this instance was created for. */
     388    PVMR3                                   pVMR3;
     389    /** Tracer instance number. */
     390    uint32_t                                idTracer;
     391    /** Flag whether the tracer has the R0 part enabled. */
     392    bool                                    fR0Enabled;
     393    /** Flag whether the tracer flush thread should shut down. */
     394    volatile bool                           fShutdown;
     395    /** Padding. */
     396    bool                                    afPad0[6];
     397    /** Next event source ID to return for a source registration. */
     398    volatile DBGFTRACEREVTSRC               hEvtSrcNext;
     399    /** Pointer to the shared tracer instance data. */
     400    R3PTRTYPE(PDBGFTRACERSHARED)            pSharedR3;
     401    /** The I/O thread writing the log from the shared event ringbuffer. */
     402    RTTHREAD                                hThrdFlush;
     403    /** Pointer to the start of the ring buffer. */
     404    R3PTRTYPE(uint8_t *)                    pbRingBufR3;
     405    /** The last processed event ID. */
     406    uint64_t                                idEvtLast;
     407    /** The trace log writer handle. */
     408    RTTRACELOGWR                            hTraceLog;
     409} DBGFTRACERINSR3;
     410/** Pointer to a tarcer instance - Ring-3 Ptr. */
     411typedef R3PTRTYPE(DBGFTRACERINSR3 *) PDBGFTRACERINSR3;
     412
     413
     414/**
     415 * Private tracer instance data, ring-0
     416 */
     417typedef struct DBGFTRACERINSR0
     418{
     419    /** Pointer to the VM this instance was created for. */
     420    R0PTRTYPE(PGVM)                         pGVM;
     421    /** The tracer instance memory. */
     422    RTR0MEMOBJ                              hMemObj;
     423    /** The ring-3 mapping object. */
     424    RTR0MEMOBJ                              hMapObj;
     425    /** Pointer to the shared tracer instance data. */
     426    R0PTRTYPE(PDBGFTRACERSHARED)            pSharedR0;
     427    /** Size of the ring buffer in bytes, kept here so R3 can not manipulate the ring buffer
     428     * size afterwards to trick R0 into doing something harmful. */
     429    size_t                                  cbRingBuf;
     430    /** Pointer to the start of the ring buffer. */
     431    R0PTRTYPE(uint8_t *)                    pbRingBufR0;
     432} DBGFTRACERINSR0;
     433/** Pointer to a VM - Ring-0 Ptr. */
     434typedef R0PTRTYPE(DBGFTRACERINSR0 *) PDBGFTRACERINSR0;
     435
     436
     437/**
     438 * Private device instance data, raw-mode
     439 */
     440typedef struct DBGFTRACERINSRC
     441{
     442    /** Pointer to the VM this instance was created for. */
     443    RGPTRTYPE(PVM)                          pVMRC;
     444} DBGFTRACERINSRC;
    43445
    44446
     
    482884
    483885/**
     886 * DBGF data kept in the ring-0 GVM.
     887 */
     888typedef struct DBGFR0PERVM
     889{
     890    /** Pointer to the tracer instance if enabled. */
     891    R0PTRTYPE(struct DBGFTRACERINSR0 *) pTracerR0;
     892} DBGFR0PERVM;
     893
     894/**
    484895 * The DBGF data kept in the UVM.
    485896 */
     
    529940    /** List of registered info handlers. */
    530941    R3PTRTYPE(PDBGFINFO)        pInfoFirst;
     942
     943    /** The configured tracer. */
     944    PDBGFTRACERINSR3            pTracerR3;
    531945
    532946    /** The type database lock. */
     
    577991void dbgfR3PlugInTerm(PUVM pUVM);
    578992int  dbgfR3BugCheckInit(PVM pVM);
     993DECLHIDDEN(int) dbgfR3TracerInit(PVM pVM);
     994DECLHIDDEN(void) dbgfR3TracerTerm(PVM pVM);
    579995
    580996/**
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