[82789] | 1 | /* $Id: DrvIfsTrace.cpp 104992 2024-06-21 08:50:59Z vboxsync $ */
|
---|
| 2 | /** @file
|
---|
| 3 | * VBox interface callback tracing driver.
|
---|
| 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
[98103] | 7 | * Copyright (C) 2020-2023 Oracle and/or its affiliates.
|
---|
[82789] | 8 | *
|
---|
[96407] | 9 | * This file is part of VirtualBox base platform packages, as
|
---|
| 10 | * available from https://www.virtualbox.org.
|
---|
| 11 | *
|
---|
| 12 | * This program is free software; you can redistribute it and/or
|
---|
| 13 | * modify it under the terms of the GNU General Public License
|
---|
| 14 | * as published by the Free Software Foundation, in version 3 of the
|
---|
| 15 | * License.
|
---|
| 16 | *
|
---|
| 17 | * This program is distributed in the hope that it will be useful, but
|
---|
| 18 | * WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
| 20 | * General Public License for more details.
|
---|
| 21 | *
|
---|
| 22 | * You should have received a copy of the GNU General Public License
|
---|
| 23 | * along with this program; if not, see <https://www.gnu.org/licenses>.
|
---|
| 24 | *
|
---|
| 25 | * SPDX-License-Identifier: GPL-3.0-only
|
---|
[82789] | 26 | */
|
---|
| 27 |
|
---|
| 28 |
|
---|
| 29 | /*********************************************************************************************************************************
|
---|
| 30 | * Header Files *
|
---|
| 31 | *********************************************************************************************************************************/
|
---|
| 32 | #define LOG_GROUP LOG_GROUP_MISC
|
---|
| 33 | #include <VBox/log.h>
|
---|
| 34 | #include <VBox/version.h>
|
---|
| 35 |
|
---|
| 36 | #include <iprt/errcore.h>
|
---|
| 37 | #include <iprt/buildconfig.h>
|
---|
| 38 | #include <iprt/tracelog.h>
|
---|
| 39 | #include <iprt/uuid.h>
|
---|
| 40 |
|
---|
| 41 | #include "VBoxDD.h"
|
---|
| 42 | #include "DrvIfsTraceInternal.h"
|
---|
| 43 |
|
---|
| 44 |
|
---|
| 45 | /*
|
---|
| 46 | *
|
---|
| 47 | * IBase Implementation.
|
---|
| 48 | *
|
---|
| 49 | */
|
---|
| 50 |
|
---|
| 51 |
|
---|
| 52 | static DECLCALLBACK(void *) drvIfTraceIBase_QueryInterface(PPDMIBASE pInterface, const char *pszIID)
|
---|
| 53 | {
|
---|
| 54 | PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
|
---|
| 55 | PDRVIFTRACE pThis = PDMINS_2_DATA(pDrvIns, PDRVIFTRACE);
|
---|
| 56 |
|
---|
| 57 | PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
|
---|
| 58 | if (pThis->pISerialConBelow)
|
---|
| 59 | PDMIBASE_RETURN_INTERFACE(pszIID, PDMISERIALCONNECTOR, &pThis->ISerialConnector);
|
---|
| 60 | if (pThis->pISerialPortAbove)
|
---|
| 61 | PDMIBASE_RETURN_INTERFACE(pszIID, PDMISERIALPORT, &pThis->ISerialPort);
|
---|
| 62 |
|
---|
[104894] | 63 | if (pThis->pITpmConBelow)
|
---|
| 64 | PDMIBASE_RETURN_INTERFACE(pszIID, PDMITPMCONNECTOR, &pThis->ITpmConnector);
|
---|
| 65 | if (pThis->pITpmPortAbove)
|
---|
| 66 | PDMIBASE_RETURN_INTERFACE(pszIID, PDMITPMPORT, &pThis->ITpmPort);
|
---|
| 67 |
|
---|
[82789] | 68 | return NULL;
|
---|
| 69 | }
|
---|
| 70 |
|
---|
| 71 |
|
---|
| 72 | /*
|
---|
| 73 | *
|
---|
| 74 | * PDMDRVREG Methods
|
---|
| 75 | *
|
---|
| 76 | */
|
---|
[104992] | 77 | static const RTTRACELOGEVTDESC g_IfTraceVmResumeEvtDesc =
|
---|
| 78 | {
|
---|
| 79 | "IfTrace.VmResume",
|
---|
| 80 | "VM was resumed",
|
---|
| 81 | RTTRACELOGEVTSEVERITY_DEBUG,
|
---|
| 82 | 0,
|
---|
| 83 | NULL
|
---|
| 84 | };
|
---|
[82789] | 85 |
|
---|
[104992] | 86 |
|
---|
[82789] | 87 | /**
|
---|
[104992] | 88 | * @callback_method_impl{FNPDMDRVRESUME}
|
---|
| 89 | */
|
---|
| 90 | static DECLCALLBACK(void) drvIfTrace_Resume(PPDMDRVINS pDrvIns)
|
---|
| 91 | {
|
---|
| 92 | PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
|
---|
| 93 | PDRVIFTRACE pThis = PDMINS_2_DATA(pDrvIns, PDRVIFTRACE);
|
---|
| 94 | LogFlow(("%s: iInstance=%d\n", __FUNCTION__, pDrvIns->iInstance));
|
---|
| 95 |
|
---|
| 96 | int rcTraceLog = RTTraceLogWrEvtAddL(pThis->hTraceLog, &g_IfTraceVmResumeEvtDesc, 0, 0, 0);
|
---|
| 97 | if (RT_FAILURE(rcTraceLog))
|
---|
| 98 | LogRelMax(10, ("DrvIfTrace#%d: Failed to add event to trace log %Rrc\n", pThis->pDrvIns->iInstance, rcTraceLog));
|
---|
| 99 | }
|
---|
| 100 |
|
---|
| 101 |
|
---|
| 102 |
|
---|
| 103 | static const RTTRACELOGEVTDESC g_IfTraceVmSuspendEvtDesc =
|
---|
| 104 | {
|
---|
| 105 | "IfTrace.VmSuspend",
|
---|
| 106 | "VM was suspended",
|
---|
| 107 | RTTRACELOGEVTSEVERITY_DEBUG,
|
---|
| 108 | 0,
|
---|
| 109 | NULL
|
---|
| 110 | };
|
---|
| 111 |
|
---|
| 112 |
|
---|
| 113 | /**
|
---|
| 114 | * @callback_method_impl{FNPDMDRVSUSPEND}
|
---|
| 115 | */
|
---|
| 116 | static DECLCALLBACK(void) drvIfTrace_Suspend(PPDMDRVINS pDrvIns)
|
---|
| 117 | {
|
---|
| 118 | PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
|
---|
| 119 | PDRVIFTRACE pThis = PDMINS_2_DATA(pDrvIns, PDRVIFTRACE);
|
---|
| 120 | LogFlow(("%s: iInstance=%d\n", __FUNCTION__, pDrvIns->iInstance));
|
---|
| 121 |
|
---|
| 122 | int rcTraceLog = RTTraceLogWrEvtAddL(pThis->hTraceLog, &g_IfTraceVmSuspendEvtDesc, 0, 0, 0);
|
---|
| 123 | if (RT_FAILURE(rcTraceLog))
|
---|
| 124 | LogRelMax(10, ("DrvIfTrace#%d: Failed to add event to trace log %Rrc\n", pThis->pDrvIns->iInstance, rcTraceLog));
|
---|
| 125 | }
|
---|
| 126 |
|
---|
| 127 |
|
---|
| 128 | static const RTTRACELOGEVTDESC g_IfTraceVmResetEvtDesc =
|
---|
| 129 | {
|
---|
| 130 | "IfTrace.VmReset",
|
---|
| 131 | "VM was reset",
|
---|
| 132 | RTTRACELOGEVTSEVERITY_DEBUG,
|
---|
| 133 | 0,
|
---|
| 134 | NULL
|
---|
| 135 | };
|
---|
| 136 |
|
---|
| 137 | /**
|
---|
| 138 | * @callback_method_impl{FNPDMDRVRESET}
|
---|
| 139 | */
|
---|
| 140 | static DECLCALLBACK(void) drvIfTrace_Reset(PPDMDRVINS pDrvIns)
|
---|
| 141 | {
|
---|
| 142 | PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
|
---|
| 143 | PDRVIFTRACE pThis = PDMINS_2_DATA(pDrvIns, PDRVIFTRACE);
|
---|
| 144 | LogFlow(("%s: iInstance=%d\n", __FUNCTION__, pDrvIns->iInstance));
|
---|
| 145 |
|
---|
| 146 | int rcTraceLog = RTTraceLogWrEvtAddL(pThis->hTraceLog, &g_IfTraceVmResetEvtDesc, 0, 0, 0);
|
---|
| 147 | if (RT_FAILURE(rcTraceLog))
|
---|
| 148 | LogRelMax(10, ("DrvIfTrace#%d: Failed to add event to trace log %Rrc\n", pThis->pDrvIns->iInstance, rcTraceLog));
|
---|
| 149 | }
|
---|
| 150 |
|
---|
| 151 |
|
---|
| 152 |
|
---|
| 153 | /**
|
---|
[82789] | 154 | * Destroys a interface filter driver instance.
|
---|
| 155 | *
|
---|
| 156 | * @copydoc FNPDMDRVDESTRUCT
|
---|
| 157 | */
|
---|
| 158 | static DECLCALLBACK(void) drvIfTrace_Destruct(PPDMDRVINS pDrvIns)
|
---|
| 159 | {
|
---|
| 160 | PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
|
---|
| 161 | PDRVIFTRACE pThis = PDMINS_2_DATA(pDrvIns, PDRVIFTRACE);
|
---|
| 162 | LogFlow(("%s: iInstance=%d\n", __FUNCTION__, pDrvIns->iInstance));
|
---|
| 163 |
|
---|
| 164 | if (pThis->hTraceLog != NIL_RTTRACELOGWR)
|
---|
| 165 | {
|
---|
| 166 | RTTraceLogWrDestroy(pThis->hTraceLog);
|
---|
| 167 | pThis->hTraceLog = NIL_RTTRACELOGWR;
|
---|
| 168 | }
|
---|
| 169 | }
|
---|
| 170 |
|
---|
| 171 |
|
---|
| 172 | /**
|
---|
| 173 | * Construct a interface filter driver instance.
|
---|
| 174 | *
|
---|
| 175 | * @copydoc FNPDMDRVCONSTRUCT
|
---|
| 176 | */
|
---|
| 177 | static DECLCALLBACK(int) drvIfTrace_Construct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
|
---|
| 178 | {
|
---|
| 179 | PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
|
---|
[91870] | 180 | PDRVIFTRACE pThis = PDMINS_2_DATA(pDrvIns, PDRVIFTRACE);
|
---|
| 181 | PCPDMDRVHLPR3 pHlp = pDrvIns->pHlpR3;
|
---|
[82789] | 182 |
|
---|
[91870] | 183 |
|
---|
[82789] | 184 | /*
|
---|
| 185 | * Initialize the instance data.
|
---|
| 186 | */
|
---|
| 187 | pThis->pDrvIns = pDrvIns;
|
---|
| 188 | pThis->hTraceLog = NIL_RTTRACELOGWR;
|
---|
| 189 | pDrvIns->IBase.pfnQueryInterface = drvIfTraceIBase_QueryInterface;
|
---|
| 190 |
|
---|
| 191 | drvIfsTrace_SerialIfInit(pThis);
|
---|
[104894] | 192 | drvIfsTrace_TpmIfInit(pThis);
|
---|
[82789] | 193 |
|
---|
| 194 | /*
|
---|
| 195 | * Validate and read config.
|
---|
| 196 | */
|
---|
[104976] | 197 | PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, "TraceFilePath|TraceLocation", "");
|
---|
[82789] | 198 |
|
---|
[104976] | 199 | char *pszLocation = NULL;
|
---|
| 200 | int rc = pHlp->pfnCFGMQueryStringAlloc(pCfg, "TraceFilePath", &pszLocation);
|
---|
| 201 | if (RT_SUCCESS(rc))
|
---|
| 202 | {
|
---|
| 203 | /* Try to create a file based trace log. */
|
---|
| 204 | rc = RTTraceLogWrCreateFile(&pThis->hTraceLog, RTBldCfgVersion(), pszLocation);
|
---|
| 205 | PDMDrvHlpMMHeapFree(pDrvIns, pszLocation);
|
---|
[82789] | 206 |
|
---|
[104976] | 207 | AssertLogRelRCReturn(rc, rc);
|
---|
| 208 | }
|
---|
| 209 | else if (rc == VERR_CFGM_VALUE_NOT_FOUND)
|
---|
| 210 | {
|
---|
| 211 | /* Try to connect to an external server. */
|
---|
| 212 | rc = pHlp->pfnCFGMQueryStringAlloc(pCfg, "TraceLocation", &pszLocation);
|
---|
| 213 | if (RT_FAILURE(rc))
|
---|
| 214 | return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
|
---|
| 215 | N_("Configuration error: querying \"TraceLocation\" resulted in %Rrc"), rc);
|
---|
[82789] | 216 |
|
---|
[104976] | 217 | char *pszPort = strchr(pszLocation, ':');
|
---|
| 218 | if (!pszPort)
|
---|
| 219 | return PDMDrvHlpVMSetError(pDrvIns, VERR_NOT_FOUND, RT_SRC_POS,
|
---|
| 220 | N_("IfTrace#%d: The location misses the port to connect to"),
|
---|
| 221 | pDrvIns->iInstance);
|
---|
| 222 |
|
---|
| 223 | *pszPort = '\0'; /* Overwrite temporarily to avoid copying the hostname into a temporary buffer. */
|
---|
| 224 | uint32_t uPort = 0;
|
---|
| 225 | rc = RTStrToUInt32Ex(pszPort + 1, NULL, 10, &uPort);
|
---|
| 226 | if (RT_FAILURE(rc))
|
---|
| 227 | return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
|
---|
| 228 | N_("IfTrace#%d: The port part of the location is not a numerical value"),
|
---|
| 229 | pDrvIns->iInstance);
|
---|
| 230 |
|
---|
| 231 | rc = RTTraceLogWrCreateTcpClient(&pThis->hTraceLog, RTBldCfgVersion(), pszLocation, uPort);
|
---|
| 232 | *pszPort = ':'; /* Restore delimiter before checking the status. */
|
---|
| 233 | if (RT_FAILURE(rc))
|
---|
| 234 | return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
|
---|
| 235 | N_("IfTrace#%d: Failed to connect to socket %s"),
|
---|
| 236 | pDrvIns->iInstance, pszLocation);
|
---|
| 237 |
|
---|
| 238 | PDMDrvHlpMMHeapFree(pDrvIns, pszLocation);
|
---|
| 239 | }
|
---|
| 240 |
|
---|
| 241 |
|
---|
[82789] | 242 | /*
|
---|
| 243 | * Query interfaces from the driver/device above us.
|
---|
| 244 | */
|
---|
| 245 | pThis->pISerialPortAbove = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMISERIALPORT);
|
---|
[104894] | 246 | pThis->pITpmPortAbove = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMITPMPORT);
|
---|
[82789] | 247 |
|
---|
| 248 | /*
|
---|
| 249 | * Attach driver below us.
|
---|
| 250 | */
|
---|
| 251 | PPDMIBASE pIBaseBelow;
|
---|
| 252 | rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pIBaseBelow);
|
---|
| 253 | AssertLogRelRCReturn(rc, rc);
|
---|
| 254 |
|
---|
| 255 | pThis->pISerialConBelow = PDMIBASE_QUERY_INTERFACE(pIBaseBelow, PDMISERIALCONNECTOR);
|
---|
[104894] | 256 | pThis->pITpmConBelow = PDMIBASE_QUERY_INTERFACE(pIBaseBelow, PDMITPMCONNECTOR);
|
---|
[82789] | 257 |
|
---|
| 258 | return VINF_SUCCESS;
|
---|
| 259 | }
|
---|
| 260 |
|
---|
| 261 |
|
---|
| 262 | /**
|
---|
| 263 | * Storage filter driver registration record.
|
---|
| 264 | */
|
---|
| 265 | const PDMDRVREG g_DrvIfTrace =
|
---|
| 266 | {
|
---|
| 267 | /* u32Version */
|
---|
| 268 | PDM_DRVREG_VERSION,
|
---|
| 269 | /* szName */
|
---|
| 270 | "IfTrace",
|
---|
| 271 | /* szRCMod */
|
---|
| 272 | "",
|
---|
| 273 | /* szR0Mod */
|
---|
| 274 | "",
|
---|
| 275 | /* pszDescription */
|
---|
| 276 | "Interface callback tracing driver",
|
---|
| 277 | /* fFlags */
|
---|
| 278 | PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
|
---|
| 279 | /* fClass. */
|
---|
| 280 | PDM_DRVREG_CLASS_STATUS,
|
---|
| 281 | /* cMaxInstances */
|
---|
| 282 | ~0U,
|
---|
| 283 | /* cbInstance */
|
---|
| 284 | sizeof(DRVIFTRACE),
|
---|
| 285 | /* pfnConstruct */
|
---|
| 286 | drvIfTrace_Construct,
|
---|
| 287 | /* pfnDestruct */
|
---|
| 288 | drvIfTrace_Destruct,
|
---|
| 289 | /* pfnRelocate */
|
---|
| 290 | NULL,
|
---|
| 291 | /* pfnIOCtl */
|
---|
| 292 | NULL,
|
---|
| 293 | /* pfnPowerOn */
|
---|
| 294 | NULL,
|
---|
| 295 | /* pfnReset */
|
---|
[104992] | 296 | drvIfTrace_Reset,
|
---|
[82789] | 297 | /* pfnSuspend */
|
---|
[104992] | 298 | drvIfTrace_Suspend,
|
---|
[82789] | 299 | /* pfnResume */
|
---|
[104992] | 300 | drvIfTrace_Resume,
|
---|
[82789] | 301 | /* pfnAttach */
|
---|
| 302 | NULL,
|
---|
| 303 | /* pfnDetach */
|
---|
| 304 | NULL,
|
---|
| 305 | /* pfnPowerOff */
|
---|
| 306 | NULL,
|
---|
| 307 | /* pfnSoftReset */
|
---|
| 308 | NULL,
|
---|
| 309 | /* u32EndVersion */
|
---|
| 310 | PDM_DRVREG_VERSION
|
---|
| 311 | };
|
---|
| 312 |
|
---|