SUPDrvTracer.cpp revision cb70b5cc08e3b666361766188f99cc86ed1626fb
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync/* $Id$ */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync/** @file
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * VBoxDrv - The VirtualBox Support Driver - Tracer Interface.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync/*
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync * Copyright (C) 2012 Oracle Corporation
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * available from http://www.virtualbox.org. This file is free software;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * you can redistribute it and/or modify it under the terms of the GNU
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * General Public License (GPL) as published by the Free Software
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * The contents of this file may alternatively be used under the terms
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * of the Common Development and Distribution License Version 1.0
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * VirtualBox OSE distribution, in which case the provisions of the
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * CDDL are applicable instead of those of the GPL.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * You may elect to license modified versions of this file under the
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * terms and conditions of either the GPL or the CDDL or both.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync/*******************************************************************************
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync* Header Files *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync*******************************************************************************/
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#define LOG_GROUP LOG_GROUP_SUP_DRV
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#define SUPDRV_AGNOSTIC
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#include "SUPDrvInternal.h"
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#include <VBox/err.h>
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#include <VBox/log.h>
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#include <VBox/VBoxTpG.h>
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#include <iprt/assert.h>
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#include <iprt/ctype.h>
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#include <iprt/list.h>
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#include <iprt/mem.h>
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#include <iprt/semaphore.h>
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#include <iprt/thread.h>
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync/*******************************************************************************
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync* Structures and Typedefs *
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync*******************************************************************************/
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync/**
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync * Data for a tracepoint provider.
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync */
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsynctypedef struct SUPDRVTPPROVIDER
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync{
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync /** The entry in the provider list for this image. */
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync RTLISTNODE ListEntry;
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync /** The core structure. */
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync SUPDRVVDTPROVIDERCORE Core;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync /** Pointer to the image this provider resides in. NULL if it's a
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * driver. */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync PSUPDRVLDRIMAGE pImage;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync /** The session this provider is associated with if registered via
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * SUPR0VtgRegisterDrv. NULL if pImage is set. */
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync PSUPDRVSESSION pSession;
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync /** Used to indicate that we've called pfnProviderDeregistered already and it
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync * failed because the provider was busy. Next time we must try
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync * pfnProviderDeregisterZombie.
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync *
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync * @remarks This does not necessiarly mean the provider is in the zombie
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * list. See supdrvTracerCommonDeregisterImpl. */
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync bool fZombie;
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync /** Set if the provider has been successfully registered with the
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync * tracer. */
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync bool fRegistered;
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync /** The provider name (for logging purposes). */
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync char szName[1];
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync} SUPDRVTPPROVIDER;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync/** Pointer to the data for a tracepoint provider. */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsynctypedef SUPDRVTPPROVIDER *PSUPDRVTPPROVIDER;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync/*******************************************************************************
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync* Defined Constants And Macros *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync*******************************************************************************/
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync/** Simple SUPR0Printf-style logging. */
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync#ifdef DEBUG_bird
bf8889d6b20936475381d2ed2b80b06eaf2a03d1vboxsync# define LOG_TRACER(a_Args) SUPR0Printf a_Args
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync#else
bf8889d6b20936475381d2ed2b80b06eaf2a03d1vboxsync# define LOG_TRACER(a_Args) do { } while (0)
bf8889d6b20936475381d2ed2b80b06eaf2a03d1vboxsync#endif
bf8889d6b20936475381d2ed2b80b06eaf2a03d1vboxsync
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync/*******************************************************************************
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync* Global Variables *
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync*******************************************************************************/
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync/** The address of the current probe fire routine for kernel mode. */
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsyncPFNRT g_pfnSupdrvProbeFireKernel = supdrvTracerProbeFireStub;
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync/**
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync * Validates a VTG string against length and characterset limitations.
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync *
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync * @returns VINF_SUCCESS, VERR_SUPDRV_VTG_BAD_STRING or
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync * VERR_SUPDRV_VTG_STRING_TOO_LONG.
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync * @param psz The string.
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsyncstatic int supdrvVtgValidateString(const char *psz)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync{
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync size_t off = 0;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync while (off < _4K)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync char const ch = psz[off++];
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync if (!ch)
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync return VINF_SUCCESS;
e94ff1af89bf631c68367d4e291ddbb491b5e5c0vboxsync if ( !RTLocCIsAlNum(ch)
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync && ch != ' '
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync && ch != '_'
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync && ch != '-'
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync && ch != '('
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync && ch != ')'
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync && ch != ','
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync && ch != '*'
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync && ch != '&'
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync )
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync /*RTAssertMsg2("off=%u '%s'\n", off, psz);*/
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync return VERR_SUPDRV_VTG_BAD_STRING;
e94ff1af89bf631c68367d4e291ddbb491b5e5c0vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync return VERR_SUPDRV_VTG_STRING_TOO_LONG;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync}
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync/**
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Validates the VTG data.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @returns VBox status code.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pVtgHdr The VTG object header of the data to validate.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param cbVtgObj The size of the VTG object.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pbImage The image base. For validating the probe
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * locations.
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync * @param cbImage The image size to go with @a pbImage.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsyncstatic int supdrvVtgValidate(PVTGOBJHDR pVtgHdr, size_t cbVtgObj, const uint8_t *pbImage, size_t cbImage)
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync{
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync uintptr_t cbTmp;
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync uintptr_t offTmp;
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync uintptr_t i;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync uintptr_t cProviders;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync int rc;
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (!pbImage || !cbImage)
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync {
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync pbImage = NULL;
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync cbImage = 0;
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync#define MY_VALIDATE_PTR(p, cb, cMin, cMax, cbUnit, rcBase) \
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync do { \
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync if ( (cb) >= cbVtgObj \
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync || (uintptr_t)(p) - (uintptr_t)pVtgHdr > cbVtgObj - (cb) ) \
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync { \
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync SUPR0Printf("supdrvVtgValidate: " #rcBase "_TOO_PTR - p=%p cb=%#zx pVtgHdr=%p cbVtgHdr=%#zu line=%u %s\n", \
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync p, (size_t)(cb), pVtgHdr, cbVtgObj, __LINE__, #p); \
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync return rcBase ## _PTR; \
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync } \
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync if ((cb) < (cMin) * (cbUnit)) \
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync { \
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync SUPR0Printf("supdrvVtgValidate: " #rcBase "_TOO_FEW - cb=%#zx cMin=%#zx cbUnit=%#zx line=%u %s\n", \
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync (size_t)(cb), (size_t)(cMin), (size_t)cbUnit, __LINE__, #p); \
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync return rcBase ## _TOO_FEW; \
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync } \
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync if ((cb) >= (cMax) * (cbUnit)) \
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync { \
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync SUPR0Printf("supdrvVtgValidate: " #rcBase "_TOO_MUCH - cb=%#zx cMax=%#zx cbUnit=%#zx line=%u %s\n", \
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync (size_t)(cb), (size_t)(cMax), (size_t)cbUnit, __LINE__, #p); \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync return rcBase ## _TOO_MUCH; \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync } \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync if ((cb) / (cbUnit) * (cbUnit) != (cb)) \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync { \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync SUPR0Printf("supdrvVtgValidate: " #rcBase "_NOT_MULTIPLE - cb=%#zx cbUnit=%#zx line=%u %s\n", \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync (size_t)(cb), (size_t)cbUnit, __LINE__, #p); \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync return rcBase ## _NOT_MULTIPLE; \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync } \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync } while (0)
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync#define MY_WITHIN_IMAGE(p, rc) \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync do { \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync if (pbImage) \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync { \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync if ((uintptr_t)(p) - (uintptr_t)pbImage > cbImage) \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync { \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync SUPR0Printf("supdrvVtgValidate: " #rc " - p=%p pbImage=%p cbImage=%#zxline=%u %s\n", \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync p, pbImage, cbImage, #p); \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync return (rc); \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync } \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync } \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync else if (!RT_VALID_PTR(p)) \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync return (rc); \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync } while (0)
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync#define MY_VALIDATE_STR(offStrTab) \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync do { \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync if ((offStrTab) >= pVtgHdr->cbStrTab) \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync return VERR_SUPDRV_VTG_STRTAB_OFF; \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync rc = supdrvVtgValidateString(pVtgHdr->pachStrTab + (offStrTab)); \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync if (rc != VINF_SUCCESS) \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync return rc; \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync } while (0)
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync#define MY_VALIDATE_ATTR(Attr) \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync do { \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync if ((Attr).u8Code <= (uint8_t)kVTGStability_Invalid || (Attr).u8Code >= (uint8_t)kVTGStability_End) \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync return VERR_SUPDRV_VTG_BAD_ATTR; \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync if ((Attr).u8Data <= (uint8_t)kVTGStability_Invalid || (Attr).u8Data >= (uint8_t)kVTGStability_End) \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync return VERR_SUPDRV_VTG_BAD_ATTR; \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync if ((Attr).u8DataDep <= (uint8_t)kVTGClass_Invalid || (Attr).u8DataDep >= (uint8_t)kVTGClass_End) \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync return VERR_SUPDRV_VTG_BAD_ATTR; \
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync } while (0)
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync /*
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync * The header.
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync */
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync if (memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)))
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync return VERR_SUPDRV_VTG_MAGIC;
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync if (pVtgHdr->cBits != ARCH_BITS)
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync return VERR_SUPDRV_VTG_BITS;
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync if (pVtgHdr->u32Reserved0)
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync return VERR_SUPDRV_VTG_BAD_HDR;
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync MY_VALIDATE_PTR(pVtgHdr->paProviders, pVtgHdr->cbProviders, 1, 16, sizeof(VTGDESCPROVIDER), VERR_SUPDRV_VTG_BAD_HDR);
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync MY_VALIDATE_PTR(pVtgHdr->paProbes, pVtgHdr->cbProbes, 1, _32K, sizeof(VTGDESCPROBE), VERR_SUPDRV_VTG_BAD_HDR);
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync MY_VALIDATE_PTR(pVtgHdr->pafProbeEnabled, pVtgHdr->cbProbeEnabled, 1, _32K, sizeof(bool), VERR_SUPDRV_VTG_BAD_HDR);
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync MY_VALIDATE_PTR(pVtgHdr->pachStrTab, pVtgHdr->cbStrTab, 4, _1M, sizeof(char), VERR_SUPDRV_VTG_BAD_HDR);
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync MY_VALIDATE_PTR(pVtgHdr->paArgLists, pVtgHdr->cbArgLists, 1, _32K, sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync MY_WITHIN_IMAGE(pVtgHdr->paProbLocs, VERR_SUPDRV_VTG_BAD_HDR_PTR);
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync MY_WITHIN_IMAGE(pVtgHdr->paProbLocsEnd, VERR_SUPDRV_VTG_BAD_HDR_PTR);
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync if ((uintptr_t)pVtgHdr->paProbLocs > (uintptr_t)pVtgHdr->paProbLocsEnd)
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync {
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_PTR - paProbeLocs=%p > paProbLocsEnd=%p\n",
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd);
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync return VERR_SUPDRV_VTG_BAD_HDR_PTR;
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync }
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync cbTmp = (uintptr_t)pVtgHdr->paProbLocsEnd - (uintptr_t)pVtgHdr->paProbLocs;
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync if (cbTmp < sizeof(VTGPROBELOC))
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync {
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_TOO_FEW - cbTmp=%#zx paProbeLocs=%p paProbLocsEnd=%p\n",
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync cbTmp, pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd);
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync return VERR_SUPDRV_VTG_BAD_HDR_TOO_FEW;
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync }
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync if (cbTmp >= _128K * sizeof(VTGPROBELOC))
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync {
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH - cbTmp=%#zx paProbeLocs=%p paProbLocsEnd=%p\n",
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync cbTmp, pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd);
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync return VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH;
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync }
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync if (cbTmp / sizeof(VTGPROBELOC) * sizeof(VTGPROBELOC) != cbTmp)
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync {
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_NOT_MULTIPLE - cbTmp=%#zx cbUnit=%#zx paProbeLocs=%p paProbLocsEnd=%p\n",
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync cbTmp, sizeof(VTGPROBELOC), pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd);
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync return VERR_SUPDRV_VTG_BAD_HDR_NOT_MULTIPLE;
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync }
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync if (pVtgHdr->cbProbes / sizeof(VTGDESCPROBE) != pVtgHdr->cbProbeEnabled)
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync {
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR - cbProbeEnabled=%#zx cbProbes=%#zx\n",
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync pVtgHdr->cbProbeEnabled, pVtgHdr->cbProbes);
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync return VERR_SUPDRV_VTG_BAD_HDR;
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync }
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync /*
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync * Validate the providers.
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync */
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync cProviders = i = pVtgHdr->cbProviders / sizeof(VTGDESCPROVIDER);
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync while (i-- > 0)
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync {
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync MY_VALIDATE_STR(pVtgHdr->paProviders[i].offName);
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync if (pVtgHdr->paProviders[i].iFirstProbe >= pVtgHdr->cbProbeEnabled)
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync return VERR_SUPDRV_VTG_BAD_PROVIDER;
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync if (pVtgHdr->paProviders[i].iFirstProbe + pVtgHdr->paProviders[i].cProbes > pVtgHdr->cbProbeEnabled)
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync return VERR_SUPDRV_VTG_BAD_PROVIDER;
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrSelf);
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrModules);
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrFunctions);
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrNames);
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrArguments);
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync if (pVtgHdr->paProviders[i].bReserved)
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync return VERR_SUPDRV_VTG_BAD_PROVIDER;
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync }
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync /*
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync * Validate probes.
ba6cd8af51db6aeff784fd6d73cadaf13ec45996vboxsync */
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync i = pVtgHdr->cbProbes / sizeof(VTGDESCPROBE);
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync while (i-- > 0)
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync {
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync PVTGDESCARGLIST pArgList;
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync unsigned iArg;
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync MY_VALIDATE_STR(pVtgHdr->paProbes[i].offName);
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync if (pVtgHdr->paProbes[i].offArgList >= pVtgHdr->cbArgLists)
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync return VERR_SUPDRV_VTG_BAD_PROBE;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (pVtgHdr->paProbes[i].offArgList & 3)
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync return VERR_SUPDRV_VTG_BAD_PROBE;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (pVtgHdr->paProbes[i].idxEnabled != i) /* The lists are parallel. */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync return VERR_SUPDRV_VTG_BAD_PROBE;
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync if (pVtgHdr->paProbes[i].idxProvider >= cProviders)
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync return VERR_SUPDRV_VTG_BAD_PROBE;
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync if ( i - pVtgHdr->paProviders[pVtgHdr->paProbes[i].idxProvider].iFirstProbe
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync >= pVtgHdr->paProviders[pVtgHdr->paProbes[i].idxProvider].cProbes)
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync return VERR_SUPDRV_VTG_BAD_PROBE;
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync if (pVtgHdr->paProbes[i].u32User)
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync return VERR_SUPDRV_VTG_BAD_PROBE;
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync /* The referenced argument list. */
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync pArgList = (PVTGDESCARGLIST)((uintptr_t)pVtgHdr->paArgLists + pVtgHdr->paProbes[i].offArgList);
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync if (pArgList->cArgs > 16)
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync return VERR_SUPDRV_VTG_BAD_ARGLIST;
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync if ( pArgList->abReserved[0]
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync || pArgList->abReserved[1]
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync || pArgList->abReserved[2])
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync return VERR_SUPDRV_VTG_BAD_ARGLIST;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync iArg = pArgList->cArgs;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync while (iArg-- > 0)
b9473064e26edc9a65150b4206ea1e52f3ca600avboxsync {
b9473064e26edc9a65150b4206ea1e52f3ca600avboxsync MY_VALIDATE_STR(pArgList->aArgs[iArg].offType);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync MY_VALIDATE_STR(pArgList->aArgs[iArg].offName);
b9473064e26edc9a65150b4206ea1e52f3ca600avboxsync }
b9473064e26edc9a65150b4206ea1e52f3ca600avboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync /*
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync * Check that pafProbeEnabled is all zero.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync i = pVtgHdr->cbProbeEnabled;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync while (i-- > 0)
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync if (pVtgHdr->pafProbeEnabled[0])
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync return VERR_SUPDRV_VTG_BAD_PROBE_ENABLED;
b9473064e26edc9a65150b4206ea1e52f3ca600avboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync /*
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * Probe locations.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync i = pVtgHdr->paProbLocsEnd - pVtgHdr->paProbLocs;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync while (i-- > 0)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync if (pVtgHdr->paProbLocs[i].uLine >= _1G)
b9473064e26edc9a65150b4206ea1e52f3ca600avboxsync return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync if (pVtgHdr->paProbLocs[i].fEnabled)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync if (pVtgHdr->paProbLocs[i].idProbe != UINT32_MAX)
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync MY_WITHIN_IMAGE(pVtgHdr->paProbLocs[i].pszFunction, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync offTmp = (uintptr_t)pVtgHdr->paProbLocs[i].pbProbe - (uintptr_t)pVtgHdr->paProbes;
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync if (offTmp >= pVtgHdr->cbProbes)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync if (offTmp / sizeof(VTGDESCPROBE) * sizeof(VTGDESCPROBE) != offTmp)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync return VINF_SUCCESS;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync#undef MY_VALIDATE_STR
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync#undef MY_VALIDATE_PTR
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync#undef MY_WITHIN_IMAGE
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync}
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync/**
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync * Gets a string from the string table.
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync *
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync * @returns Pointer to the string.
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync * @param pVtgHdr The VTG object header.
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync * @param offStrTab The string table offset.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsyncstatic const char *supdrvVtgGetString(PVTGOBJHDR pVtgHdr, uint32_t offStrTab)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync{
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync Assert(offStrTab < pVtgHdr->cbStrTab);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync return &pVtgHdr->pachStrTab[offStrTab];
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync}
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync/**
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Frees the provider structure and associated resources.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pProv The provider to free.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsyncstatic void supdrvTracerFreeProvider(PSUPDRVTPPROVIDER pProv)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync{
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync LOG_TRACER(("Freeing tracepoint provider '%s' / %p\n", pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->fRegistered = false;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->fZombie = true;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->Core.pDesc = NULL;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->Core.pHdr = NULL;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RT_ZERO(pProv->Core.TracerData);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTMemFree(pProv);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync}
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync/**
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Deregisters a provider.
2b114c590cf5a19f8047cd7bde9c7e5ae00aa22bvboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * If the provider is still busy, it will be put in the zombie list.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pDevExt The device extension.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pProv The provider.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @remarks The caller owns mtxTracer.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsyncstatic void supdrvTracerDeregisterVtgObj(PSUPDRVDEVEXT pDevExt, PSUPDRVTPPROVIDER pProv)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync{
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync int rc;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (!pProv->fRegistered || !pDevExt->pTracerOps)
2b114c590cf5a19f8047cd7bde9c7e5ae00aa22bvboxsync rc = VINF_SUCCESS;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync else
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = pDevExt->pTracerOps->pfnProviderDeregister(pDevExt->pTracerOps, &pProv->Core);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (RT_SUCCESS(rc))
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync supdrvTracerFreeProvider(pProv);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync return;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->fZombie = true;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTListAppend(&pDevExt->TracerProviderZombieList, &pProv->ListEntry);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync LOG_TRACER(("Invalidated provider '%s' / %p and put it on the zombie list (rc=%Rrc)\n",
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync}
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync/**
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Processes the zombie list.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pDevExt The device extension.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsyncstatic void supdrvTracerProcessZombies(PSUPDRVDEVEXT pDevExt)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync{
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync PSUPDRVTPPROVIDER pProv, pProvNext;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync int rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (RT_SUCCESS(rc))
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTListNodeRemove(&pProv->ListEntry);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync supdrvTracerFreeProvider(pProv);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync}
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync/**
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Unregisters all providers, including zombies, waiting for busy providers to
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * go idle and unregister smoothly.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * This may block.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pDevExt The device extension.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsyncstatic void supdrvTracerRemoveAllProviders(PSUPDRVDEVEXT pDevExt)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync{
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync uint32_t i;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync PSUPDRVTPPROVIDER pProv;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync PSUPDRVTPPROVIDER pProvNext;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync /*
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Unregister all probes (there should only be one).
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTListNodeRemove(&pProv->ListEntry);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync supdrvTracerDeregisterVtgObj(pDevExt, pProv);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync /*
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Try unregister zombies now, sleep on busy ones and tracer opens.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync for (i = 0; ; i++)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync bool fEmpty;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync /* Zombies */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync int rc;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync LOG_TRACER(("supdrvTracerRemoveAllProviders: Attemting to unregister '%s' / %p...\n",
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (pDevExt->pTracerOps)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync else
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = VINF_SUCCESS;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (!rc)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTListNodeRemove(&pProv->ListEntry);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync supdrvTracerFreeProvider(pProv);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync else if (!(i & 0xf))
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync SUPR0Printf("supdrvTracerRemoveAllProviders: Waiting on busy provider '%s' / %p (rc=%d)\n",
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync else
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync LOG_TRACER(("supdrvTracerRemoveAllProviders: Failed to unregister provider '%s' / %p - rc=%d\n",
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync fEmpty = RTListIsEmpty(&pDevExt->TracerProviderZombieList);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync /* Tracer opens. */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if ( pDevExt->cTracerOpens
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync && pDevExt->pTracerOps)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync fEmpty = false;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (!(i & 0xf))
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync SUPR0Printf("supdrvTracerRemoveAllProviders: Waiting on %u opens\n", pDevExt->cTracerOpens);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync else
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync LOG_TRACER(("supdrvTracerRemoveAllProviders: Waiting on %u opens\n", pDevExt->cTracerOpens));
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (fEmpty)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync break;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync /* Delay...*/
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTThreadSleep(1000);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync}
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync/**
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Registers the VTG tracepoint providers of a driver.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * @returns VBox status code.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pszName The driver name.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pVtgHdr The VTG object header.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pVtgObj The size of the VTG object.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pImage The image if applicable.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pSession The session if applicable.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pszModName The module name.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsyncstatic int supdrvTracerRegisterVtgObj(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, size_t cbVtgObj, PSUPDRVLDRIMAGE pImage,
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync PSUPDRVSESSION pSession, const char *pszModName)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync{
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync int rc;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync uintptr_t i;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync PSUPDRVTPPROVIDER pProv;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync /*
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Validate input.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync AssertPtrNullReturn(pImage, VERR_INVALID_POINTER);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync AssertPtrNullReturn(pSession, VERR_INVALID_POINTER);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync AssertPtrReturn(pszModName, VERR_INVALID_POINTER);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (pImage)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = supdrvVtgValidate(pVtgHdr, cbVtgObj, (const uint8_t *)pImage->pvImage, pImage->cbImageBits);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync else
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = supdrvVtgValidate(pVtgHdr, cbVtgObj, NULL, 0);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (RT_FAILURE(rc))
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync return rc;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (RT_FAILURE(rc))
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync return rc;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTListForEach(&pDevExt->TracerProviderList, pProv, SUPDRVTPPROVIDER, ListEntry)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (pProv->Core.pHdr == pVtgHdr)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = VERR_SUPDRV_VTG_ALREADY_REGISTERED;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync break;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if ( pProv->pSession == pSession
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync && pProv->pImage == pImage)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = VERR_SUPDRV_VTG_ONLY_ONCE_PER_SESSION;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync break;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (RT_FAILURE(rc))
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync return rc;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync /*
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Register the providers.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync i = pVtgHdr->cbProviders / sizeof(VTGDESCPROVIDER);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync while (i-- > 0)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync PVTGDESCPROVIDER pDesc = &pVtgHdr->paProviders[i];
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync const char *pszName = supdrvVtgGetString(pVtgHdr, pDesc->offName);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync size_t const cchName = strlen(pszName);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv = (PSUPDRVTPPROVIDER)RTMemAllocZ(RT_OFFSETOF(SUPDRVTPPROVIDER, szName[cchName + 1]));
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (pProv)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->Core.pDesc = pDesc;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->Core.pHdr = pVtgHdr;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->Core.pszName = &pProv->szName[0];
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->Core.pszModName = pszModName;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->pImage = pImage;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->pSession = pSession;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->fZombie = false;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->fRegistered = true;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync memcpy(&pProv->szName[0], pszName, cchName + 1);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (RT_SUCCESS(rc))
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if ( pDevExt->pTracerOps
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync && !pDevExt->fTracerUnloading)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = pDevExt->pTracerOps->pfnProviderRegister(pDevExt->pTracerOps, &pProv->Core);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync else
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->fRegistered = false;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = VINF_SUCCESS;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (RT_SUCCESS(rc))
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTListAppend(&pDevExt->TracerProviderList, &pProv->ListEntry);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync LOG_TRACER(("Registered tracepoint provider '%s' in '%s' -> %p\n",
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->szName, pszModName, pProv->Core.TracerData.DTrace.idProvider));
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync else
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync LOG_TRACER(("Failed to register tracepoint provider '%s' in '%s' -> %Rrc\n",
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pProv->szName, pszModName, rc));
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTMemFree(pProv);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
7c19e11502220292d5270519296442234c2493cdvboxsync }
7c19e11502220292d5270519296442234c2493cdvboxsync }
7c19e11502220292d5270519296442234c2493cdvboxsync else
7c19e11502220292d5270519296442234c2493cdvboxsync rc = VERR_NO_MEMORY;
7c19e11502220292d5270519296442234c2493cdvboxsync
7c19e11502220292d5270519296442234c2493cdvboxsync if (RT_FAILURE(rc))
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync PSUPDRVTPPROVIDER pProvNext;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync supdrvTracerFreeProvider(pProv);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTListForEachReverseSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (pProv->Core.pHdr == pVtgHdr)
1f1f533d5b88c35cf740dca55c6f1937d1035a36vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTListNodeRemove(&pProv->ListEntry);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync supdrvTracerDeregisterVtgObj(pDevExt, pProv);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync return rc;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync return VINF_SUCCESS;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync}
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync/**
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Registers the VTG tracepoint providers of a driver.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @returns VBox status code.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pSession The support driver session handle.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pVtgHdr The VTG header.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pszName The driver name.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsyncSUPR0DECL(int) SUPR0TracerRegisterDrv(PSUPDRVSESSION pSession, PVTGOBJHDR pVtgHdr, const char *pszName)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync{
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync int rc;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync AssertPtrReturn(pszName, VERR_INVALID_POINTER);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync LOG_TRACER(("SUPR0TracerRegisterDrv: pSession=%p pVtgHdr=%p pszName=%s\n", pSession, pVtgHdr, pszName));
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = supdrvTracerRegisterVtgObj(pSession->pDevExt, pVtgHdr, _1M, NULL /*pImage*/, pSession, pszName);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync /*
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync * Try unregister zombies while we have a chance.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync supdrvTracerProcessZombies(pSession->pDevExt);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync return rc;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync}
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync/**
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Deregister the VTG tracepoint providers of a driver.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pSession The support driver session handle.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pVtgHdr The VTG header.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsyncSUPR0DECL(void) SUPR0TracerDeregisterDrv(PSUPDRVSESSION pSession)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync{
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync PSUPDRVTPPROVIDER pProv, pProvNext;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync PSUPDRVDEVEXT pDevExt;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync AssertReturnVoid(SUP_IS_SESSION_VALID(pSession));
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync AssertReturnVoid(pSession->R0Process == NIL_RTR0PROCESS);
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync LOG_TRACER(("SUPR0TracerDeregisterDrv: pSession=%p\n", pSession));
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync pDevExt = pSession->pDevExt;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync /*
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Search for providers belonging to this driver session.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (pProv->pSession == pSession)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTListNodeRemove(&pProv->ListEntry);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync supdrvTracerDeregisterVtgObj(pDevExt, pProv);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync /*
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Try unregister zombies while we have a chance.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync supdrvTracerProcessZombies(pDevExt);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync}
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync/**
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Registers the VTG tracepoint providers of a module loaded by
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * the support driver.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * This should be called from the ModuleInit code.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @returns VBox status code.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param hMod The module handle.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pVtgHdr The VTG header.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsyncSUPR0DECL(int) SUPR0TracerRegisterModule(void *hMod, PVTGOBJHDR pVtgHdr)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync{
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync PSUPDRVLDRIMAGE pImage = (PSUPDRVLDRIMAGE)hMod;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync PSUPDRVDEVEXT pDevExt;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync uintptr_t cbVtgObj;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync int rc;
7c19e11502220292d5270519296442234c2493cdvboxsync
7c19e11502220292d5270519296442234c2493cdvboxsync LOG_TRACER(("SUPR0TracerRegisterModule: %p\n", pVtgHdr));
7c19e11502220292d5270519296442234c2493cdvboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync /*
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * Validate input and context.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync AssertPtrReturn(pImage, VERR_INVALID_HANDLE);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
7c19e11502220292d5270519296442234c2493cdvboxsync AssertPtrReturn(pImage, VERR_INVALID_POINTER);
7c19e11502220292d5270519296442234c2493cdvboxsync pDevExt = pImage->pDevExt;
7c19e11502220292d5270519296442234c2493cdvboxsync AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync AssertReturn(pDevExt->pLdrInitImage == pImage, VERR_WRONG_ORDER);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync AssertReturn(pDevExt->hLdrInitThread == RTThreadNativeSelf(), VERR_WRONG_ORDER);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync /*
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Calculate the max VTG object size and hand it over to the common code.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync cbVtgObj = (uintptr_t)pVtgHdr - (uintptr_t)pImage->pvImage;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync AssertMsgReturn(cbVtgObj /*off*/ < pImage->cbImageBits,
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync ("pVtgHdr=%p offVtgObj=%p cbImageBits=%p\n", pVtgHdr, cbVtgObj, pImage->cbImageBits),
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync VERR_INVALID_PARAMETER);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync cbVtgObj = pImage->cbImageBits - cbVtgObj;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = supdrvTracerRegisterVtgObj(pDevExt, pVtgHdr, cbVtgObj, pImage, NULL, pImage->szName);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync LOG_TRACER(("SUPR0TracerRegisterModule: rc=%d\n", rc));
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync /*
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Try unregister zombies while we have a chance.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync supdrvTracerProcessZombies(pDevExt);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync return rc;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync}
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync/**
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Registers the tracer implementation.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * This should be called from the ModuleInit code or from a ring-0 session.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @returns VBox status code.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param hMod The module handle.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pSession Ring-0 session handle.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pReg Pointer to the tracer registration structure.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param ppHlp Where to return the tracer helper method table.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsyncSUPR0DECL(int) SUPR0TracerRegisterImpl(void *hMod, PSUPDRVSESSION pSession, PCSUPDRVTRACERREG pReg, PCSUPDRVTRACERHLP *ppHlp)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync{
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync PSUPDRVLDRIMAGE pImage = (PSUPDRVLDRIMAGE)hMod;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync PSUPDRVDEVEXT pDevExt;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync PSUPDRVTPPROVIDER pProv;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync int rc;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync /*
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Validate input and context.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync AssertPtrReturn(ppHlp, VERR_INVALID_POINTER);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *ppHlp = NULL;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync AssertPtrReturn(pReg, VERR_INVALID_HANDLE);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (pImage)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync AssertPtrReturn(pImage, VERR_INVALID_POINTER);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync AssertReturn(pSession == NULL, VERR_INVALID_PARAMETER);
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync pDevExt = pImage->pDevExt;
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync AssertReturn(pDevExt->pLdrInitImage == pImage, VERR_WRONG_ORDER);
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync AssertReturn(pDevExt->hLdrInitThread == RTThreadNativeSelf(), VERR_WRONG_ORDER);
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync else
e819feefdc34d50781a3c95edecda1072e8575d0vboxsync {
e819feefdc34d50781a3c95edecda1072e8575d0vboxsync AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
e819feefdc34d50781a3c95edecda1072e8575d0vboxsync AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync pDevExt = pSession->pDevExt;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync }
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync AssertReturn(pReg->u32Magic == SUPDRVTRACERREG_MAGIC, VERR_INVALID_MAGIC);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync AssertReturn(pReg->u32Version == SUPDRVTRACERREG_VERSION, VERR_VERSION_MISMATCH);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync AssertReturn(pReg->uEndMagic == SUPDRVTRACERREG_MAGIC, VERR_VERSION_MISMATCH);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync AssertPtrReturn(pReg->pfnProbeFireKernel, VERR_INVALID_POINTER);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync AssertPtrReturn(pReg->pfnProbeFireUser, VERR_INVALID_POINTER);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync AssertPtrReturn(pReg->pfnTracerOpen, VERR_INVALID_POINTER);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync AssertPtrReturn(pReg->pfnTracerIoCtl, VERR_INVALID_POINTER);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync AssertPtrReturn(pReg->pfnTracerClose, VERR_INVALID_POINTER);
e819feefdc34d50781a3c95edecda1072e8575d0vboxsync AssertPtrReturn(pReg->pfnProviderRegister, VERR_INVALID_POINTER);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync AssertPtrReturn(pReg->pfnProviderDeregister, VERR_INVALID_POINTER);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync AssertPtrReturn(pReg->pfnProviderDeregisterZombie, VERR_INVALID_POINTER);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync /*
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync * Do the job.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync if (RT_SUCCESS(rc))
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync {
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync if (!pDevExt->pTracerOps)
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync {
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync LOG_TRACER(("SUPR0TracerRegisterImpl: pReg=%p\n", pReg));
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync pDevExt->pTracerOps = pReg;
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync pDevExt->pTracerSession = pSession;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync pDevExt->pTracerImage = pImage;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync g_pfnSupdrvProbeFireKernel = (PFNRT)pDevExt->pTracerOps->pfnProbeFireKernel;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync *ppHlp = &pDevExt->TracerHlp;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync rc = VINF_SUCCESS;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync /*
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * Iterate the already loaded modules and register their providers.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTListForEach(&pDevExt->TracerProviderList, pProv, SUPDRVTPPROVIDER, ListEntry)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
e819feefdc34d50781a3c95edecda1072e8575d0vboxsync Assert(!pProv->fRegistered);
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync pProv->fRegistered = true;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync int rc2 = pDevExt->pTracerOps->pfnProviderRegister(pDevExt->pTracerOps, &pProv->Core);
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync if (RT_FAILURE(rc2))
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync pProv->fRegistered = false;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync SUPR0Printf("SUPR0TracerRegisterImpl: Failed to register provider %s::%s - rc=%d\n",
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync pProv->Core.pszModName, pProv->szName, rc2);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync else
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync rc = VERR_SUPDRV_TRACER_ALREADY_REGISTERED;
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync return rc;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync}
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync/**
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * Common tracer implementation deregistration code.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync *
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * The caller sets fTracerUnloading prior to calling this function.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync *
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * @param pDevExt The device extension structure.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsyncstatic void supdrvTracerCommonDeregisterImpl(PSUPDRVDEVEXT pDevExt)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync{
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync uint32_t i;
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync PSUPDRVTPPROVIDER pProv;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync PSUPDRVTPPROVIDER pProvNext;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync /*
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * Reinstall the stub probe-fire function.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync g_pfnSupdrvProbeFireKernel = supdrvTracerProbeFireStub;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync /*
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * Disassociate the tracer implementation from all providers.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * We will have to wait on busy providers.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync for (i = 0; ; i++)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync uint32_t cZombies = 0;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync /* Live providers. */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
e819feefdc34d50781a3c95edecda1072e8575d0vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync int rc;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Attemting to unregister '%s' / %p...\n",
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync if (!pProv->fRegistered)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync continue;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync if (!pProv->fZombie)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync rc = pDevExt->pTracerOps->pfnProviderDeregister(pDevExt->pTracerOps, &pProv->Core);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync if (RT_FAILURE(rc))
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync pProv->fZombie = true;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync else
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync if (RT_SUCCESS(rc))
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync pProv->fZombie = pProv->fRegistered = false;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync else
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync cZombies++;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync if (!(i & 0xf))
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync SUPR0Printf("supdrvTracerCommonDeregisterImpl: Waiting on busy provider '%s' / %p (rc=%d)\n",
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync else
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Failed to unregister provider '%s' / %p - rc=%d\n",
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync /* Zombies providers. */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTListForEachSafe(&pDevExt->TracerProviderZombieList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync int rc;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Attemting to unregister '%s' / %p (zombie)...\n",
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync rc = pDevExt->pTracerOps->pfnProviderDeregisterZombie(pDevExt->pTracerOps, &pProv->Core);
e819feefdc34d50781a3c95edecda1072e8575d0vboxsync if (RT_SUCCESS(rc))
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTListNodeRemove(&pProv->ListEntry);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync supdrvTracerFreeProvider(pProv);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync else
e819feefdc34d50781a3c95edecda1072e8575d0vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync cZombies++;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync if (!(i & 0xf))
e819feefdc34d50781a3c95edecda1072e8575d0vboxsync SUPR0Printf("supdrvTracerCommonDeregisterImpl: Waiting on busy provider '%s' / %p (rc=%d)\n",
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync else
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Failed to unregister provider '%s' / %p - rc=%d\n",
e819feefdc34d50781a3c95edecda1072e8575d0vboxsync pProv->szName, pProv->Core.TracerData.DTrace.idProvider, rc));
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync /* Tracer opens. */
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync if (pDevExt->cTracerOpens)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync cZombies++;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync if (!(i & 0xf))
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync SUPR0Printf("supdrvTracerCommonDeregisterImpl: Waiting on %u opens\n", pDevExt->cTracerOpens);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync else
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Waiting on %u opens\n", pDevExt->cTracerOpens));
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
e819feefdc34d50781a3c95edecda1072e8575d0vboxsync /* Done? */
815647972e1e2746466be1ea725e702459693cd5vboxsync if (cZombies == 0)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync break;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync /* Delay...*/
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTThreadSleep(1000);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync /*
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * Deregister the tracer implementation.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync pDevExt->pTracerImage = NULL;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync pDevExt->pTracerSession = NULL;
815647972e1e2746466be1ea725e702459693cd5vboxsync pDevExt->pTracerOps = NULL;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync pDevExt->fTracerUnloading = false;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync}
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync/**
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * Deregister a tracer implementation.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync *
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * This should be called from the ModuleTerm code or from a ring-0 session.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync *
815647972e1e2746466be1ea725e702459693cd5vboxsync * @returns VBox status code.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * @param hMod The module handle.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * @param pSession Ring-0 session handle.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsyncSUPR0DECL(int) SUPR0TracerDeregisterImpl(void *hMod, PSUPDRVSESSION pSession)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync{
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync PSUPDRVLDRIMAGE pImage = (PSUPDRVLDRIMAGE)hMod;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync PSUPDRVDEVEXT pDevExt;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync int rc;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync /*
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * Validate input and context.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
815647972e1e2746466be1ea725e702459693cd5vboxsync if (pImage)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync AssertPtrReturn(pImage, VERR_INVALID_POINTER);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync AssertReturn(pSession == NULL, VERR_INVALID_PARAMETER);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync pDevExt = pImage->pDevExt;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync else
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync AssertReturn(pSession->R0Process == NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync pDevExt = pSession->pDevExt;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync /*
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * Do the job.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
815647972e1e2746466be1ea725e702459693cd5vboxsync if (RT_SUCCESS(rc))
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync if ( pImage
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync ? pDevExt->pTracerImage == pImage
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync : pDevExt->pTracerSession == pSession)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
815647972e1e2746466be1ea725e702459693cd5vboxsync LOG_TRACER(("SUPR0TracerDeregisterImpl: Unloading ...\n"));
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync pDevExt->fTracerUnloading = true;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync supdrvTracerCommonDeregisterImpl(pDevExt);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync LOG_TRACER(("SUPR0TracerDeregisterImpl: ... done.\n"));
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync else
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync rc = VERR_SUPDRV_TRACER_NOT_REGISTERED;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
815647972e1e2746466be1ea725e702459693cd5vboxsync return rc;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync}
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync/*
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * The probe function is a bit more fun since we need tail jump optimizating.
815647972e1e2746466be1ea725e702459693cd5vboxsync *
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * Since we cannot ship yasm sources for linux and freebsd, owing to the cursed
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * rebuilding of the kernel module from scratch at install time, we have to
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * deploy some ugly gcc inline assembly here.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync#if defined(__GNUC__) && (defined(RT_OS_FREEBSD) || defined(RT_OS_LINUX))
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync__asm__("\
815647972e1e2746466be1ea725e702459693cd5vboxsync .section .text \n\
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync \n\
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync .p2align 2,,3 \n\
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync .global SUPR0TracerFireProbe \n\
07557d07616212d7ba6e7ab3059e85cb14633775vboxsyncSUPR0TracerFireProbe: \n\
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync");
815647972e1e2746466be1ea725e702459693cd5vboxsync# if defined(RT_ARCH_AMD64)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync__asm__(" \
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync movq g_pfnSupdrvProbeFireKernel(%rip), %rax \n\
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync jmp *%rax \n\
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync");
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync# elif defined(RT_ARCH_X86)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync__asm__("\
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync movl g_pfnSupdrvProbeFireKernel, %eax \n\
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync jmp *%eax \n\
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync");
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync# else
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync# error "Which arch is this?"
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync# endif
815647972e1e2746466be1ea725e702459693cd5vboxsync__asm__("\
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync \n\
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync .type supdrvTracerProbeFireStub,@function \n\
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync .global supdrvTracerProbeFireStub \n\
07557d07616212d7ba6e7ab3059e85cb14633775vboxsyncsupdrvTracerProbeFireStub: \n\
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync ret \n\
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync \n\
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync .previous \n\
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync");
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync# if 0 /* Slickedit on windows highlighting fix */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync )
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync# endif
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync#endif
815647972e1e2746466be1ea725e702459693cd5vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync/**
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * Module unloading hook, called after execution in the module have ceased.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync *
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * @param pDevExt The device extension structure.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * @param pImage The image being unloaded.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsyncvoid VBOXCALL supdrvTracerModuleUnloading(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync{
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync PSUPDRVTPPROVIDER pProv, pProvNext;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync AssertPtrReturnVoid(pImage); /* paranoia */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
815647972e1e2746466be1ea725e702459693cd5vboxsync /*
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * If it is the tracer image, we have to unload all the providers.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync if (pDevExt->pTracerImage == pImage)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync LOG_TRACER(("supdrvTracerModuleUnloading: Unloading tracer ...\n"));
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync pDevExt->fTracerUnloading = true;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
e819feefdc34d50781a3c95edecda1072e8575d0vboxsync supdrvTracerCommonDeregisterImpl(pDevExt);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync LOG_TRACER(("supdrvTracerModuleUnloading: ... done.\n"));
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync else
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync /*
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * Unregister all providers belonging to this image.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync if (pProv->pImage == pImage)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTListNodeRemove(&pProv->ListEntry);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync supdrvTracerDeregisterVtgObj(pDevExt, pProv);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync /*
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * Try unregister zombies while we have a chance.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync supdrvTracerProcessZombies(pDevExt);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync}
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync/**
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * Called when a session is being cleaned up.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pDevExt The device extension structure.
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync * @param pSession The session that is being torn down.
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsyncvoid VBOXCALL supdrvTracerCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync{
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync /*
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync * If ring-0 session, make sure it has deregistered VTG objects and the tracer.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync if (pSession->R0Process == NIL_RTR0PROCESS)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync SUPDRVTPPROVIDER *pProvNext;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync SUPDRVTPPROVIDER *pProv;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync if (pProv->pSession == pSession)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTListNodeRemove(&pProv->ListEntry);
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync supdrvTracerDeregisterVtgObj(pDevExt, pProv);
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync (void)SUPR0TracerDeregisterImpl(NULL, pSession);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync /*
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * Clean up instance data the trace may have associated with the session.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync if (pSession->uTracerData)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync supdrvIOCtl_TracerClose(pDevExt, pSession);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync}
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync/**
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * Open the tracer.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync *
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * @returns VBox status code
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * @param pDevExt The device extension structure.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * @param pSession The current session.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * @param uCookie The tracer cookie.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * @param uArg The tracer open argument.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsyncint VBOXCALL supdrvIOCtl_TracerOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uint32_t uCookie, uintptr_t uArg)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync{
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync int rc;
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync if (!pSession->uTracerData)
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync {
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync if (pDevExt->pTracerOps)
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync {
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync if (pDevExt->pTracerSession != pSession)
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync {
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync if (!pDevExt->fTracerUnloading)
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync {
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync if (pSession->hTracerCaller == NIL_RTNATIVETHREAD)
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync {
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync pDevExt->cTracerOpens++;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pSession->uTracerData = ~(uintptr_t)0;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pSession->hTracerCaller = hNativeSelf;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = pDevExt->pTracerOps->pfnTracerOpen(pDevExt->pTracerOps, pSession, uCookie, uArg, &pSession->uTracerData);
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync
bf8889d6b20936475381d2ed2b80b06eaf2a03d1vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync if (RT_FAILURE(rc))
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync {
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync pDevExt->cTracerOpens--;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pSession->uTracerData = 0;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync pSession->hTracerCaller = NIL_RTNATIVETHREAD;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync else
bf8889d6b20936475381d2ed2b80b06eaf2a03d1vboxsync rc = VERR_SUPDRV_TRACER_SESSION_BUSY;
bf8889d6b20936475381d2ed2b80b06eaf2a03d1vboxsync }
bf8889d6b20936475381d2ed2b80b06eaf2a03d1vboxsync else
bf8889d6b20936475381d2ed2b80b06eaf2a03d1vboxsync rc = VERR_SUPDRV_TRACER_UNLOADING;
bf8889d6b20936475381d2ed2b80b06eaf2a03d1vboxsync }
bf8889d6b20936475381d2ed2b80b06eaf2a03d1vboxsync else
bf8889d6b20936475381d2ed2b80b06eaf2a03d1vboxsync rc = VERR_SUPDRV_TRACER_CANNOT_OPEN_SELF;
bf8889d6b20936475381d2ed2b80b06eaf2a03d1vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync else
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync rc = VERR_SUPDRV_TRACER_NOT_PRESENT;
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync }
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync else
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync rc = VERR_SUPDRV_TRACER_ALREADY_OPENED;
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync return rc;
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync}
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync/**
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Closes the tracer.
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync *
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync * @returns VBox status code.
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync * @param pDevExt The device extension structure.
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync * @param pSession The current session.
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync */
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsyncint VBOXCALL supdrvIOCtl_TracerClose(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync{
ad2e12b64b9ccbde05d913515deced851c446b3evboxsync RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync int rc;
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync if (pSession->uTracerData)
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync {
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync Assert(pDevExt->cTracerOpens > 0);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync if (pDevExt->pTracerOps)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (pSession->hTracerCaller == NIL_RTNATIVETHREAD)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync uintptr_t uTracerData = pSession->uTracerData;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pSession->uTracerData = 0;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pSession->hTracerCaller = hNativeSelf;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync pDevExt->pTracerOps->pfnTracerClose(pDevExt->pTracerOps, pSession, uTracerData);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync rc = VINF_SUCCESS;
7c19e11502220292d5270519296442234c2493cdvboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pSession->hTracerCaller = NIL_RTNATIVETHREAD;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync Assert(pDevExt->cTracerOpens > 0);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pDevExt->cTracerOpens--;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
7c19e11502220292d5270519296442234c2493cdvboxsync else
7c19e11502220292d5270519296442234c2493cdvboxsync rc = VERR_SUPDRV_TRACER_SESSION_BUSY;
7c19e11502220292d5270519296442234c2493cdvboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync else
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = VERR_SUPDRV_TRACER_NOT_PRESENT;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pSession->uTracerData = 0;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync Assert(pDevExt->cTracerOpens > 0);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pDevExt->cTracerOpens--;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync }
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync else
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync rc = VERR_SUPDRV_TRACER_NOT_OPENED;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync return rc;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync}
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync/**
529e6bec97f5ef2e005c99c205c9624583ecb7f0vboxsync * Performs a tracer I/O control request.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
7c19e11502220292d5270519296442234c2493cdvboxsync * @returns VBox status code.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * @param pDevExt The device extension structure.
7c19e11502220292d5270519296442234c2493cdvboxsync * @param pSession The current session.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * @param uCmd The tracer command.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync * @param uArg The tracer argument.
7c19e11502220292d5270519296442234c2493cdvboxsync * @param piRetVal Where to store the tracer specific return value.
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync */
7c19e11502220292d5270519296442234c2493cdvboxsyncint VBOXCALL supdrvIOCtl_TracerIOCtl(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uintptr_t uCmd, uintptr_t uArg, int32_t *piRetVal)
7c19e11502220292d5270519296442234c2493cdvboxsync{
7c19e11502220292d5270519296442234c2493cdvboxsync RTNATIVETHREAD hNativeSelf = RTThreadNativeSelf();
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync int rc;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
7c19e11502220292d5270519296442234c2493cdvboxsync *piRetVal = 0;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync if (pSession->uTracerData)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync Assert(pDevExt->cTracerOpens > 0);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync if (pDevExt->pTracerOps)
7c19e11502220292d5270519296442234c2493cdvboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync if (!pDevExt->fTracerUnloading)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync if (pSession->hTracerCaller == NIL_RTNATIVETHREAD)
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync {
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync uintptr_t uTracerData = pSession->uTracerData;
7c19e11502220292d5270519296442234c2493cdvboxsync pDevExt->cTracerOpens++;
7c19e11502220292d5270519296442234c2493cdvboxsync pSession->hTracerCaller = hNativeSelf;
7c19e11502220292d5270519296442234c2493cdvboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync rc = pDevExt->pTracerOps->pfnTracerIoCtl(pDevExt->pTracerOps, pSession, uTracerData, uCmd, uArg, piRetVal);
7c19e11502220292d5270519296442234c2493cdvboxsync
7c19e11502220292d5270519296442234c2493cdvboxsync RTSemFastMutexRequest(pDevExt->mtxTracer);
7c19e11502220292d5270519296442234c2493cdvboxsync pSession->hTracerCaller = NIL_RTNATIVETHREAD;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync Assert(pDevExt->cTracerOpens > 0);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pDevExt->cTracerOpens--;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync else
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = VERR_SUPDRV_TRACER_SESSION_BUSY;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync else
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = VERR_SUPDRV_TRACER_UNLOADING;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync else
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = VERR_SUPDRV_TRACER_NOT_PRESENT;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync else
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = VERR_SUPDRV_TRACER_NOT_OPENED;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTSemFastMutexRelease(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync return rc;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync}
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync/**
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Early module initialization hook.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @returns VBox status code.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @param pDevExt The device extension structure.
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync */
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsyncint VBOXCALL supdrvTracerInit(PSUPDRVDEVEXT pDevExt)
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync{
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync /*
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Initialize the tracer.
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync int rc = RTSemFastMutexCreate(&pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (RT_SUCCESS(rc))
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync {
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pDevExt->TracerHlp.uVersion = SUPDRVTRACERHLP_VERSION;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync /** @todo */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pDevExt->TracerHlp.uEndVersion = SUPDRVTRACERHLP_VERSION;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTListInit(&pDevExt->TracerProviderList);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTListInit(&pDevExt->TracerProviderZombieList);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#ifdef VBOX_WITH_NATIVE_DTRACE_R0DRV
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pDevExt->pTracerOps = supdrvDTraceInit();
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (pDevExt->pTracerOps)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync g_pfnSupdrvProbeFireKernel = (PFNRT)pDevExt->pTracerOps->pfnProbeFireKernel;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#endif
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync /*
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Register the provider for this module, if compiled in.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#ifdef VBOX_WITH_DTRACE_R0DRV
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync rc = supdrvTracerRegisterVtgObj(pDevExt, &g_VTGObjHeader, _1M, NULL /*pImage*/, NULL /*pSession*/, "vboxdrv");
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync if (RT_SUCCESS(rc))
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync return rc;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync SUPR0Printf("supdrvTracerInit: supdrvTracerRegisterVtgObj failed with rc=%d\n", rc);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTSemFastMutexDestroy(pDevExt->mtxTracer);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#else
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync return VINF_SUCCESS;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync#endif
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync }
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync pDevExt->mtxTracer = NIL_RTSEMFASTMUTEX;
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync return rc;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync}
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
6b07d9a23ed1c650aa0a3b8de9d19f51b6b67e9fvboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync/**
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Late module termination hook.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync *
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * @returns VBox status code.
815647972e1e2746466be1ea725e702459693cd5vboxsync * @param pDevExt The device extension structure.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync */
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsyncvoid VBOXCALL supdrvTracerTerm(PSUPDRVDEVEXT pDevExt)
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync{
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync LOG_TRACER(("supdrvTracerTerm\n"));
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync supdrvTracerRemoveAllProviders(pDevExt);
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync RTSemFastMutexDestroy(pDevExt->mtxTracer);
815647972e1e2746466be1ea725e702459693cd5vboxsync pDevExt->mtxTracer = NIL_RTSEMFASTMUTEX;
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync LOG_TRACER(("supdrvTracerTerm: Done\n"));
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync}
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync