VirtualBox

Changeset 53667 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jan 2, 2015 12:32:53 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
97444
Message:

VBoxDTrace: implemented a bunch of glue and reduced the required solaris glue. (r44)

Location:
trunk/src/VBox/ExtPacks/VBoxDTrace
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ExtPacks/VBoxDTrace/VBoxDTraceR0/VBoxDTraceR0.cpp

    r53666 r53667  
    3434*******************************************************************************/
    3535#include <VBox/sup.h>
     36#include <VBox/log.h>
    3637
    3738#include <iprt/asm-amd64-x86.h>
    3839#include <iprt/assert.h>
     40#include <iprt/ctype.h>
    3941#include <iprt/err.h>
    4042#include <iprt/mem.h>
    4143#include <iprt/mp.h>
     44#include <iprt/spinlock.h>
    4245#include <iprt/string.h>
    4346#include <iprt/time.h>
    4447
    4548#include <sys/dtrace_impl.h>
     49
     50#include <VBox/VBoxTpG.h>
     51
    4652
    4753
     
    5460    RTDEV       uMajor;
    5561};
     62
     63
     64/** Caller indicator. */
     65typedef enum VBOXDTCALLER
     66{
     67    kVBoxDtCaller_Invalid = 0,
     68    kVBoxDtCaller_Generic,
     69    kVBoxDtCaller_ProbeFireUser,
     70    kVBoxDtCaller_ProbeFireKernel
     71} VBOXDTCALLER;
     72
     73/**
     74 * Stack data used for thread structure and such.
     75 *
     76 * This is planted in every external entry point and used to emulate solaris
     77 * curthread, CRED, curproc and similar.  It is also used to get at the
     78 * uncached probe arguments.
     79 */
     80typedef struct VBoxDtStackData
     81{
     82    /** Eyecatcher no. 1 (VBDT_STACK_DATA_MAGIC2). */
     83    uint32_t                u32Magic1;
     84    /** Eyecatcher no. 2 (VBDT_STACK_DATA_MAGIC2). */
     85    uint32_t                u32Magic2;
     86    /** The format of the caller specific data. */
     87    VBOXDTCALLER            enmCaller;
     88    /** Caller specific data.  */
     89    union
     90    {
     91        /** kVBoxDtCaller_ProbeFireKernel. */
     92        struct
     93        {
     94            /** The caller. */
     95            uintptr_t               uCaller;
     96            /** Pointer to the stack arguments of a probe function call. */
     97            uintptr_t              *pauStackArgs;
     98        } ProbeFireKernel;
     99        /** kVBoxDtCaller_ProbeFireUser. */
     100        struct
     101        {
     102            /** The user context.  */
     103            PCSUPDRVTRACERUSRCTX    pCtx;
     104        } ProbeFireUser;
     105    } u;
     106    /** Credentials allocated by VBoxDtGetCurrentCreds. */
     107    struct VBoxDtCred      *pCred;
     108    /** Pointer to this structure.
     109     * This is the final bit of integrity checking. */
     110    struct VBoxDtStackData *pSelf;
     111} VBDTSTACKDATA;
     112/** Pointer to the on-stack thread specific data. */
     113typedef VBDTSTACKDATA *PVBDTSTACKDATA;
     114
     115/** The first magic value. */
     116#define VBDT_STACK_DATA_MAGIC1      RT_MAKE_U32_FROM_U8('V', 'B', 'o', 'x')
     117/** The second magic value. */
     118#define VBDT_STACK_DATA_MAGIC2      RT_MAKE_U32_FROM_U8('D', 'T', 'r', 'c')
     119
     120/** The alignment of the stack data.
     121 * The data doesn't require more than sizeof(uintptr_t) alignment, but the
     122 * greater alignment the quicker lookup. */
     123#define VBDT_STACK_DATA_ALIGN       32
     124
     125/** Plants the stack data. */
     126#define VBDT_SETUP_STACK_DATA(a_enmCaller) \
     127    uint8_t abBlob[sizeof(VBoxDtStackData) + VBDT_STACK_DATA_ALIGN - 1]; \
     128    PVBDTSTACKDATA pStackData = (PVBDTSTACKDATA)(   (uintptr_t)&abBlob[VBDT_STACK_DATA_ALIGN - 1] \
     129                                                 &        ~(uintptr_t)(VBDT_STACK_DATA_ALIGN - 1)); \
     130    pStackData->u32Magic1   = VBDT_STACK_DATA_MAGIC1; \
     131    pStackData->u32Magic2   = VBDT_STACK_DATA_MAGIC2; \
     132    pStackData->enmCaller   = a_enmCaller; \
     133    pStackData->pCred       = NULL; \
     134    pStackData->pSelf       = pStackData
     135
     136/** Passifies the stack data and frees up resource held within it. */
     137#define VBDT_CLEAR_STACK_DATA() \
     138    do \
     139    { \
     140        pStackData->u32Magic1   = 0; \
     141        pStackData->u32Magic2   = 0; \
     142        pStackData->pSelf       = NULL; \
     143        if (pStackData->pCred) \
     144            crfree(pStackData->pCred); \
     145    } while (0)
    56146
    57147
     
    80170void           (*dtrace_debugger_fini)(void);
    81171dtrace_cacheid_t dtrace_predcache_id = DTRACE_CACHEIDNONE + 1;
     172
     173
     174/**
     175 * Gets the stack data.
     176 *
     177 * @returns Pointer to the stack data.  Never NULL.
     178 */
     179static PVBDTSTACKDATA vboxDtGetStackData(void)
     180{
     181    int volatile    iDummy = 1; /* use this to get the stack address. */
     182    PVBDTSTACKDATA  pData = (PVBDTSTACKDATA)(  ((uintptr_t)&iDummy + VBDT_STACK_DATA_ALIGN - 1)
     183                                             & ~(uintptr_t)(VBDT_STACK_DATA_ALIGN - 1));
     184    for (;;)
     185    {
     186        if (   pData->u32Magic1 == VBDT_STACK_DATA_MAGIC1
     187            && pData->u32Magic2 == VBDT_STACK_DATA_MAGIC2
     188            && pData->pSelf     == pData)
     189            return pData;
     190        pData = (PVBDTSTACKDATA)((uintptr_t)pData + VBDT_STACK_DATA_ALIGN);
     191    }
     192}
    82193
    83194
     
    312423uintptr_t dtrace_caller(int cCallFrames)
    313424{
    314     /** @todo Will fix dtrace_probe this so it won't be necessary. */
    315     return (uintptr_t)~0;
     425    PVBDTSTACKDATA pData = vboxDtGetStackData();
     426    if (pData->enmCaller == kVBoxDtCaller_ProbeFireKernel)
     427        return pData->u.ProbeFireKernel.uCaller;
     428    return ~(uintptr_t)0;
    316429}
    317430
     
    326439uint64_t dtrace_getarg(int iArg, int cCallFrames)
    327440{
    328     /** @todo Will fix dtrace_probe this so that this will be easier to do on all
    329      *        platforms (MSC sucks, no frames on AMD64). */
    330     return 0xdeadbeef;
     441    PVBDTSTACKDATA pData = vboxDtGetStackData();
     442    AssertReturn(iArg >= 5, UINT64_MAX);
     443
     444    if (pData->enmCaller == kVBoxDtCaller_ProbeFireKernel)
     445        return pData->u.ProbeFireKernel.pauStackArgs[iArg - 5];
     446    return UINT64_MAX;
    331447}
    332448
     
    521637cred_t *VBoxDtGetCurrentCreds(void)
    522638{
    523     struct VBoxDtThread *pThread = VBoxDtGetCurrentThread();
    524     if (!pThread)
    525         return NULL;
    526     return pThread->t_proc->p_cred;
     639    PVBDTSTACKDATA pData = vboxDtGetStackData();
     640    if (!pData->pCred)
     641    {
     642        struct VBoxDtCred *pCred;
     643        int rc = RTMemAllocEx(sizeof(*pCred), 0, RTMEMALLOCEX_FLAGS_ANY_CTX, (void **)&pCred);
     644        AssertFatalRC(rc);
     645        pCred->cr_refs  = 1;
     646        /** @todo get the right creds on unix systems. */
     647        pCred->cr_uid   = 0;
     648        pCred->cr_ruid  = 0;
     649        pCred->cr_suid  = 0;
     650        pCred->cr_gid   = 0;
     651        pCred->cr_rgid  = 0;
     652        pCred->cr_sgid  = 0;
     653        pCred->cr_zone  = 0;
     654        pData->pCred = pCred;
     655    }
     656
     657    return pData->pCred;
    527658}
    528659
     
    546677
    547678
    548 /* ddi_driver_major implementation. */
    549 major_t VBoxDtDdiDriverMajor(struct VBoxDtDevInfo *pDevInfo)
    550 {
    551     Assert(pDevInfo == &g_DevInfo);
    552     return pDevInfo->uMajor;
    553 }
    554 
    555 /* ddi_report_dev stub.*/
    556 void    VBoxDtDdiReportDev(struct VBoxDtDevInfo *pDevInfo)
    557 {
    558     Assert(pDevInfo == &g_DevInfo);
    559 }
    560 
    561 
    562 //VBoxDtDdiSoftStateAllocZ
    563 //VBoxDtDdiSoftStateFree
    564 //VBoxDtDdiSoftStateGet
    565 //VBoxDtDdiSoftStateInit
    566 //VBoxDtDdiSoftStateTerm
    567 
    568 
     679/** The number of bits per chunk.
     680 * @remarks The 32 bytes are for heap headers and such like.  */
     681#define VBOXDTVMEMCHUNK_BITS    ( ((_64K - 32 - sizeof(uint32_t) * 2) / sizeof(uint32_t)) * 32)
     682
     683/**
     684 * Resource allocator chunk.
     685 */
     686typedef struct  VBoxDtVMemChunk
     687{
     688    /** The ordinal (unbased) of the first item. */
     689    uint32_t            iFirst;
     690    /** The current number of free items in this chunk. */
     691    uint32_t            cCurFree;
     692    /** The allocation bitmap. */
     693    uint32_t            bm[VBOXDTVMEMCHUNK_BITS / 32];
     694} VBOXDTVMEMCHUNK;
     695/** Pointer to a resource allocator chunk. */
     696typedef VBOXDTVMEMCHUNK *PVBOXDTVMEMCHUNK;
     697
     698
     699
     700/**
     701 * Resource allocator instance.
     702 */
     703typedef struct VBoxDtVMem
     704{
     705    /** Spinlock protecting the data. */
     706    RTSPINLOCK          hSpinlock;
     707    /** Magic value. */
     708    uint32_t            u32Magic;
     709    /** The current number of free items in the chunks. */
     710    uint32_t            cCurFree;
     711    /** The current number of chunks that we have allocated. */
     712    uint32_t            cCurChunks;
     713    /** The configured resource base. */
     714    uint32_t            uBase;
     715    /** The configured resource end (base included). */
     716    uint32_t            uEnd;
     717    /** The size of the apChunks array. */
     718    uint32_t            cMaxChunks;
     719    /** Array of chunk pointers.
     720     * (The size is determined at creation.) */
     721    PVBOXDTVMEMCHUNK    apChunks[1];
     722} VBOXDTVMEM;
     723/** Pointer to a resource allocator instance. */
     724typedef VBOXDTVMEM *PVBOXDTVMEM;
     725
     726/** Magic value for the VBOXDTVMEM structure. */
     727#define VBOXDTVMEM_MAGIC        RT_MAKE_U32_FROM_U8('V', 'M',  'e',  'm')
     728
     729
     730/* vmem_create implementation */
     731struct VBoxDtVMem *VBoxDtVMemCreate(const char *pszName, void *pvBase, size_t cb, size_t cbUnit,
     732                                    PFNRT pfnAlloc, PFNRT pfnFree, struct VBoxDtVMem *pSrc,
     733                                    size_t cbQCacheMax, uint32_t fFlags)
     734{
     735    /*
     736     * Assert preconditions of this implementation.
     737     */
     738    AssertMsgReturn((uintptr_t)pvBase <= UINT32_MAX, ("%p\n", pvBase), NULL);
     739    AssertMsgReturn((uintptr_t)pvBase + cb - 1 <= UINT32_MAX, ("%p %zu\n", pvBase, cb), NULL);
     740    AssertMsgReturn(cbUnit == 1, ("%zu\n", cbUnit), NULL);
     741    AssertReturn(!pfnAlloc, NULL);
     742    AssertReturn(!pfnFree, NULL);
     743    AssertReturn(!pSrc, NULL);
     744    AssertReturn(!cbQCacheMax, NULL);
     745    AssertReturn(fFlags & VM_SLEEP, NULL);
     746    AssertReturn(fFlags & VMC_IDENTIFIER, NULL);
     747
     748    /*
     749     * Allocate the instance.
     750     */
     751    uint32_t cChunks = (uint32_t)(cb - (uintptr_t)pvBase);
     752    cChunks += VBOXDTVMEMCHUNK_BITS - 1;
     753    cChunks /= VBOXDTVMEMCHUNK_BITS;
     754    PVBOXDTVMEM pThis = (PVBOXDTVMEM)RTMemAllocZ(RT_OFFSETOF(VBOXDTVMEM, apChunks[cChunks]));
     755    if (!pThis)
     756        return NULL;
     757    int rc = RTSpinlockCreate(&pThis->hSpinlock);
     758    if (RT_FAILURE(rc))
     759    {
     760        RTMemFree(pThis);
     761        return NULL;
     762    }
     763    pThis->u32Magic     = VBOXDTVMEM_MAGIC;
     764    pThis->cCurFree     = 0;
     765    pThis->cCurChunks   = 0;
     766    pThis->uBase        = (uint32_t)(uintptr_t)pvBase;
     767    pThis->uEnd         = (uint32_t)cb;
     768    pThis->cMaxChunks   = cChunks;
     769
     770    return pThis;
     771}
     772
     773
     774/* vmem_destroy implementation */
     775void  VBoxDtVMemDestroy(struct VBoxDtVMem *pThis)
     776{
     777    if (!pThis)
     778        return;
     779    AssertPtrReturnVoid(pThis);
     780    AssertReturnVoid(pThis->u32Magic == VBOXDTVMEM_MAGIC);
     781
     782    /*
     783     * Invalidate the instance.
     784     */
     785    RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
     786    RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); /* paranoia */
     787    pThis->u32Magic = 0;
     788    RTSpinlockRelease(pThis->hSpinlock, &Tmp);
     789    RTSpinlockDestroy(pThis->hSpinlock);
     790
     791    /*
     792     * Free the chunks, then the instance.
     793     */
     794    uint32_t iChunk = pThis->cCurChunks;
     795    while (iChunk-- > 0)
     796    {
     797        RTMemFree(pThis->apChunks[iChunk]);
     798        pThis->apChunks[iChunk] = NULL;
     799    }
     800    RTMemFree(pThis);
     801}
     802
     803
     804/* vmem_alloc implementation */
     805void *VBoxDtVMemAlloc(struct VBoxDtVMem *pThis, size_t cbMem, uint32_t fFlags)
     806{
     807    /*
     808     * Validate input.
     809     */
     810    AssertReturn(fFlags & VM_BESTFIT, NULL);
     811    AssertReturn(fFlags & VM_SLEEP, NULL);
     812    AssertReturn(cbMem == 1, NULL);
     813    AssertPtrReturn(pThis, NULL);
     814    AssertReturn(pThis->u32Magic == VBOXDTVMEM_MAGIC, NULL);
     815
     816    /*
     817     * Allocation loop.
     818     */
     819    RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
     820    RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp);
     821    for (;;)
     822    {
     823        PVBOXDTVMEMCHUNK pChunk;
     824        uint32_t const   cChunks = pThis->cCurChunks;
     825
     826        if (RT_LIKELY(pThis->cCurFree > 0))
     827        {
     828            for (uint32_t iChunk = 0; iChunk < cChunks; iChunk++)
     829            {
     830                pChunk = pThis->apChunks[iChunk];
     831                if (pChunk->cCurFree > 0)
     832                {
     833                    int iBit = ASMBitFirstClear(pChunk->bm, VBOXDTVMEMCHUNK_BITS);
     834                    AssertMsgReturnStmt(iBit >= 0 && (unsigned)iBit < VBOXDTVMEMCHUNK_BITS, ("%d\n", iBit),
     835                                        RTSpinlockRelease(pThis->hSpinlock, &Tmp),
     836                                        NULL);
     837
     838                    ASMBitSet(pChunk->bm, iBit);
     839                    pChunk->cCurFree--;
     840                    pThis->cCurFree--;
     841
     842                    uint32_t iRet = (uint32_t)iBit + pChunk->iFirst + pThis->uBase;
     843                    RTSpinlockRelease(pThis->hSpinlock, &Tmp);
     844                    return (void *)(uintptr_t)iRet;
     845                }
     846            }
     847            AssertFailedBreak();
     848        }
     849
     850        /* Out of resources? */
     851        if (cChunks >= pThis->cMaxChunks)
     852            break;
     853
     854        /*
     855         * Allocate another chunk.
     856         */
     857        uint32_t const  iFirstBit = cChunks > 0 ? pThis->apChunks[cChunks - 1]->iFirst + VBOXDTVMEMCHUNK_BITS : 0;
     858        uint32_t const  cFreeBits = cChunks + 1 == pThis->cMaxChunks
     859                                  ? pThis->uEnd - pThis->uBase - iFirstBit
     860                                  : VBOXDTVMEMCHUNK_BITS;
     861        Assert(cFreeBits <= VBOXDTVMEMCHUNK_BITS);
     862
     863        RTSpinlockRelease(pThis->hSpinlock, &Tmp);
     864
     865        pChunk = (PVBOXDTVMEMCHUNK)RTMemAllocZ(sizeof(*pChunk));
     866        if (!pChunk)
     867            return NULL;
     868
     869        pChunk->iFirst   = iFirstBit;
     870        pChunk->cCurFree = cFreeBits;
     871        if (cFreeBits != VBOXDTVMEMCHUNK_BITS)
     872        {
     873            /* lazy bird. */
     874            uint32_t iBit = cFreeBits;
     875            while (iBit < VBOXDTVMEMCHUNK_BITS)
     876            {
     877                ASMBitSet(pChunk->bm, iBit);
     878                iBit++;
     879            }
     880        }
     881
     882        RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp);
     883
     884        /*
     885         * Insert the new chunk.  If someone raced us here, we'll drop it to
     886         * avoid wasting resources.
     887         */
     888        if (pThis->cCurChunks == cChunks)
     889        {
     890            pThis->apChunks[cChunks] = pChunk;
     891            pThis->cCurFree   += pChunk->cCurFree;
     892            pThis->cCurChunks += 1;
     893        }
     894        else
     895        {
     896            RTSpinlockRelease(pThis->hSpinlock, &Tmp);
     897            RTMemFree(pChunk);
     898            RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp);
     899        }
     900    }
     901    RTSpinlockRelease(pThis->hSpinlock, &Tmp);
     902
     903    return NULL;
     904}
     905
     906/* vmem_free implementation */
     907void VBoxDtVMemFree(struct VBoxDtVMem *pThis, void *pvMem, size_t cbMem)
     908{
     909    /*
     910     * Validate input.
     911     */
     912    AssertReturnVoid(cbMem == 1);
     913    AssertPtrReturnVoid(pThis);
     914    AssertReturnVoid(pThis->u32Magic == VBOXDTVMEM_MAGIC);
     915
     916    AssertReturnVoid((uintptr_t)pvMem < UINT32_MAX);
     917    uint32_t uMem = (uint32_t)(uintptr_t)pvMem;
     918    AssertReturnVoid(uMem >= pThis->uBase);
     919    AssertReturnVoid(uMem < pThis->uEnd);
     920
     921    uMem -= pThis->uBase;
     922
     923    /*
     924     * Free it.
     925     */
     926    RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
     927    RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp);
     928    uint32_t const iChunk = uMem / VBOXDTVMEMCHUNK_BITS;
     929    if (iChunk < pThis->cCurChunks)
     930    {
     931        PVBOXDTVMEMCHUNK pChunk = pThis->apChunks[iChunk];
     932        uint32_t iBit = uMem - pChunk->iFirst;
     933        AssertReturnVoidStmt(iBit < VBOXDTVMEMCHUNK_BITS, RTSpinlockRelease(pThis->hSpinlock, &Tmp));
     934        AssertReturnVoidStmt(ASMBitTestAndClear(pChunk->bm, iBit), RTSpinlockRelease(pThis->hSpinlock, &Tmp));
     935
     936        pChunk->cCurFree++;
     937        pThis->cCurFree++;
     938    }
     939
     940    RTSpinlockRelease(pThis->hSpinlock, &Tmp);
     941}
    569942
    570943#if 0
    571 
     944VBoxDtMutexIsOwner
     945VBoxDtMutexExit
     946VBoxDtMutexEnter
     947
     948VBoxDtKMemFree
     949VBoxDtKMemCacheFree
     950VBoxDtKMemCacheDestroy
     951VBoxDtKMemCacheCreate
     952VBoxDtKMemCacheAlloc
     953
     954VBoxDtKMemAllocZ
     955VBoxDtKMemAlloc
     956
     957VBoxDtGetKernelBase
     958VBoxDtGetCurrentThread
    572959VBoxDtGetCurrentProc
    573 VBoxDtGetCurrentThread
    574 VBoxDtGetKernelBase
    575 
    576 VBoxDtKMemAlloc
    577 VBoxDtKMemAllocZ
    578 VBoxDtKMemCacheAlloc
    579 VBoxDtKMemCacheCreate
    580 VBoxDtKMemCacheDestroy
    581 VBoxDtKMemCacheFree
    582 VBoxDtKMemFree
    583 VBoxDtMutexEnter
    584 VBoxDtMutexExit
    585 VBoxDtMutexIsOwner
    586 VBoxDtVMemAlloc
    587 VBoxDtVMemCreate
    588 VBoxDtVMemDestroy
    589 VBoxDtVMemFree
    590 
    591 
    592 dtrace_xcall
    593 nocrt_strncpy
    594 RTErrConvertToErrno
    595960#endif
    596961
    597962
    598 
    599 #if 0
    600 #define VBDTR0_IOC_OPEN     UINT32_C(0xfeed0001)
    601 
    602 DECLEXPORT(int) VBoxDTraceR0SrvReqHandler(PSUPDRVSESSION pSession, uint32_t uOperation,
    603                                           uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr)
    604 {
    605     /*
    606      *
    607      */
    608     if (uOperation == VBDTR0_IOC_OPEN)
    609     {
    610 
    611     }
    612 
    613 }
    614 #endif
    615 
     963/*
     964 *
     965 * Helpers for handling VTG structures.
     966 * Helpers for handling VTG structures.
     967 * Helpers for handling VTG structures.
     968 *
     969 */
     970
     971
     972
     973/**
     974 * Converts an attribute from VTG description speak to DTrace.
     975 *
     976 * @param   pDtAttr             The DTrace attribute (dst).
     977 * @param   pVtgAttr            The VTG attribute descriptor (src).
     978 */
     979static void vboxDtVtgConvAttr(dtrace_attribute_t *pDtAttr, PCVTGDESCATTR pVtgAttr)
     980{
     981    pDtAttr->dtat_name  = pVtgAttr->u8Code - 1;
     982    pDtAttr->dtat_data  = pVtgAttr->u8Data - 1;
     983    pDtAttr->dtat_class = pVtgAttr->u8DataDep - 1;
     984}
     985
     986/**
     987 * Gets a string from the string table.
     988 *
     989 * @returns Pointer to the string.
     990 * @param   pVtgHdr             The VTG object header.
     991 * @param   offStrTab           The string table offset.
     992 */
     993static const char *vboxDtVtgGetString(PVTGOBJHDR pVtgHdr,  uint32_t offStrTab)
     994{
     995    Assert(offStrTab < pVtgHdr->cbStrTab);
     996    return &pVtgHdr->pachStrTab[offStrTab];
     997}
     998
     999
     1000
     1001/*
     1002 *
     1003 * DTrace Provider Interface.
     1004 * DTrace Provider Interface.
     1005 * DTrace Provider Interface.
     1006 *
     1007 */
     1008
     1009
     1010/**
     1011 * @callback_method_impl{dtrace_pops_t,dtps_provide}
     1012 */
     1013static void     vboxDtPOps_Provide(void *pvProv, const dtrace_probedesc_t *pDtProbeDesc)
     1014{
     1015    PSUPDRVVDTPROVIDERCORE  pProv        = (PSUPDRVVDTPROVIDERCORE)pvProv;
     1016    PVTGPROBELOC            pProbeLoc    = pProv->pHdr->paProbLocs;
     1017    PVTGPROBELOC            pProbeLocEnd = pProv->pHdr->paProbLocsEnd;
     1018    dtrace_provider_id_t    idProvider   = pProv->TracerData.DTrace.idProvider;
     1019    size_t const            cbFnNmBuf    = _4K + _1K;
     1020    char                   *pszFnNmBuf;
     1021    uint16_t                idxProv;
     1022
     1023    if (pDtProbeDesc)
     1024        return;  /* We don't generate probes, so never mind these requests. */
     1025
     1026    if (pProv->TracerData.DTrace.fZombie)
     1027        return;
     1028
     1029    if (pProv->TracerData.DTrace.cProvidedProbes >= pProbeLocEnd - pProbeLoc)
     1030        return;
     1031
     1032     /* Need a buffer for extracting the function names and mangling them in
     1033        case of collision. */
     1034     pszFnNmBuf = (char *)RTMemAlloc(cbFnNmBuf);
     1035     if (!pszFnNmBuf)
     1036         return;
     1037
     1038     /*
     1039      * Itereate the probe location list and register all probes related to
     1040      * this provider.
     1041      */
     1042     idxProv      = (uint16_t)(&pProv->pHdr->paProviders[0] - pProv->pDesc);
     1043     while ((uintptr_t)pProbeLoc < (uintptr_t)pProbeLocEnd)
     1044     {
     1045         PVTGDESCPROBE pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe;
     1046         if (   pProbeDesc->idxProvider == idxProv
     1047             && pProbeLoc->idProbe      == UINT32_MAX)
     1048         {
     1049             /* The function name normally needs to be stripped since we're
     1050                using C++ compilers for most of the code.  ASSUMES nobody are
     1051                brave/stupid enough to use function pointer returns without
     1052                typedef'ing properly them. */
     1053             const char *pszPrbName = vboxDtVtgGetString(pProv->pHdr, pProbeDesc->offName);
     1054             const char *pszFunc    = pProbeLoc->pszFunction;
     1055             const char *psz        = strchr(pProbeLoc->pszFunction, '(');
     1056             size_t      cch;
     1057             if (psz)
     1058             {
     1059                 /* skip blanks preceeding the parameter parenthesis. */
     1060                 while (   (uintptr_t)psz > (uintptr_t)pProbeLoc->pszFunction
     1061                        && RT_C_IS_BLANK(psz[-1]))
     1062                     psz--;
     1063
     1064                 /* Find the start of the function name. */
     1065                 pszFunc = psz - 1;
     1066                 while ((uintptr_t)pszFunc > (uintptr_t)pProbeLoc->pszFunction)
     1067                 {
     1068                     char ch = pszFunc[-1];
     1069                     if (!RT_C_IS_ALNUM(ch) && ch != '_' && ch != ':')
     1070                         break;
     1071                     pszFunc--;
     1072                 }
     1073                 cch = psz - pszFunc;
     1074             }
     1075             else
     1076                 cch = strlen(pszFunc);
     1077             RTStrCopyEx(pszFnNmBuf, cbFnNmBuf, pszFunc, cch);
     1078
     1079             /* Look up the probe, if we have one in the same function, mangle
     1080                the function name a little to avoid having to deal with having
     1081                multiple location entries with the same probe ID. (lazy bird) */
     1082             Assert(pProbeLoc->idProbe == UINT32_MAX);
     1083             if (dtrace_probe_lookup(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName) != DTRACE_IDNONE)
     1084             {
     1085                 RTStrPrintf(pszFnNmBuf+cch, cbFnNmBuf - cch, "-%u",  pProbeLoc->uLine);
     1086                 if (dtrace_probe_lookup(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName) != DTRACE_IDNONE)
     1087                 {
     1088                     unsigned iOrd = 2;
     1089                     while (iOrd < 128)
     1090                     {
     1091                         RTStrPrintf(pszFnNmBuf+cch, cbFnNmBuf - cch, "-%u-%u",  pProbeLoc->uLine, iOrd);
     1092                         if (dtrace_probe_lookup(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName) == DTRACE_IDNONE)
     1093                             break;
     1094                         iOrd++;
     1095                     }
     1096                     if (iOrd >= 128)
     1097                     {
     1098                         LogRel(("VBoxDrv: More than 128 duplicate probe location instances in file %s at line %u, function %s [%s], probe %s\n",
     1099                                 pProbeLoc->pszFile, pProbeLoc->uLine, pProbeLoc->pszFunction, pszFnNmBuf, pszPrbName));
     1100                         continue;
     1101                     }
     1102                 }
     1103             }
     1104
     1105             /* Create the probe. */
     1106             AssertCompile(sizeof(pProbeLoc->idProbe) == sizeof(dtrace_id_t));
     1107             pProbeLoc->idProbe = dtrace_probe_create(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName,
     1108                                                      0 /*aframes*/, pProbeLoc);
     1109             pProv->TracerData.DTrace.cProvidedProbes++;
     1110         }
     1111
     1112         pProbeLoc++;
     1113     }
     1114
     1115     RTMemFree(pszFnNmBuf);
     1116}
     1117
     1118
     1119/**
     1120 * @callback_method_impl{dtrace_pops_t,dtps_enable}
     1121 */
     1122static int      vboxDtPOps_Enable(void *pvProv, dtrace_id_t idProbe, void *pvProbe)
     1123{
     1124    PSUPDRVVDTPROVIDERCORE  pProv  = (PSUPDRVVDTPROVIDERCORE)pvProv;
     1125    if (!pProv->TracerData.DTrace.fZombie)
     1126    {
     1127        PVTGPROBELOC    pProbeLoc  = (PVTGPROBELOC)pvProbe;
     1128        PVTGDESCPROBE   pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe;
     1129
     1130        if (!pProbeLoc->fEnabled)
     1131        {
     1132            pProbeLoc->fEnabled = 1;
     1133            if (ASMAtomicIncU32(&pProbeDesc->u32User) == 1)
     1134                pProv->pHdr->pafProbeEnabled[pProbeDesc->idxEnabled] = 1;
     1135        }
     1136    }
     1137
     1138    return 0;
     1139}
     1140
     1141
     1142/**
     1143 * @callback_method_impl{dtrace_pops_t,dtps_disable}
     1144 */
     1145static void     vboxDtPOps_Disable(void *pvProv, dtrace_id_t idProbe, void *pvProbe)
     1146{
     1147    PSUPDRVVDTPROVIDERCORE  pProv  = (PSUPDRVVDTPROVIDERCORE)pvProv;
     1148    if (!pProv->TracerData.DTrace.fZombie)
     1149    {
     1150        PVTGPROBELOC    pProbeLoc  = (PVTGPROBELOC)pvProbe;
     1151        PVTGDESCPROBE   pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe;
     1152
     1153        if (pProbeLoc->fEnabled)
     1154        {
     1155            pProbeLoc->fEnabled = 0;
     1156            if (ASMAtomicDecU32(&pProbeDesc->u32User) == 0)
     1157                pProv->pHdr->pafProbeEnabled[pProbeDesc->idxEnabled] = 1;
     1158        }
     1159    }
     1160}
     1161
     1162
     1163/**
     1164 * @callback_method_impl{dtrace_pops_t,dtps_getargdesc}
     1165 */
     1166static void     vboxDtPOps_GetArgDesc(void *pvProv, dtrace_id_t idProbe, void *pvProbe,
     1167                                            dtrace_argdesc_t *pArgDesc)
     1168{
     1169    PSUPDRVVDTPROVIDERCORE  pProv  = (PSUPDRVVDTPROVIDERCORE)pvProv;
     1170    unsigned                uArg   = pArgDesc->dtargd_ndx;
     1171
     1172    if (!pProv->TracerData.DTrace.fZombie)
     1173    {
     1174        PVTGPROBELOC    pProbeLoc  = (PVTGPROBELOC)pvProbe;
     1175        PVTGDESCPROBE   pProbeDesc = (PVTGDESCPROBE)pProbeLoc->pbProbe;
     1176        PVTGDESCARGLIST pArgList   = (PVTGDESCARGLIST)((uintptr_t)pProv->pHdr->paArgLists + pProbeDesc->offArgList);
     1177
     1178        Assert(pProbeDesc->offArgList < pProv->pHdr->cbArgLists);
     1179        if (pArgList->cArgs > uArg)
     1180        {
     1181            const char *pszType = vboxDtVtgGetString(pProv->pHdr, pArgList->aArgs[uArg].offType);
     1182            size_t      cchType = strlen(pszType);
     1183            if (cchType < sizeof(pArgDesc->dtargd_native))
     1184            {
     1185                memcpy(pArgDesc->dtargd_native, pszType, cchType + 1);
     1186                /** @todo mapping */
     1187                return;
     1188            }
     1189        }
     1190    }
     1191
     1192    pArgDesc->dtargd_ndx = DTRACE_ARGNONE;
     1193}
     1194
     1195
     1196/**
     1197 * @callback_method_impl{dtrace_pops_t,dtps_getargval}
     1198 */
     1199static uint64_t vboxDtPOps_GetArgVal(void *pvProv, dtrace_id_t idProbe, void *pvProbe,
     1200                                     int iArg, int cFrames)
     1201{
     1202    PVBDTSTACKDATA pData = vboxDtGetStackData();
     1203    AssertReturn(iArg >= 5, UINT64_MAX);
     1204
     1205    if (pData->enmCaller == kVBoxDtCaller_ProbeFireKernel)
     1206        return pData->u.ProbeFireKernel.pauStackArgs[iArg - 5];
     1207
     1208    if (pData->enmCaller == kVBoxDtCaller_ProbeFireUser)
     1209    {
     1210        PCSUPDRVTRACERUSRCTX pCtx = pData->u.ProbeFireUser.pCtx;
     1211        if (pCtx->cBits == 32)
     1212        {
     1213            if ((unsigned)iArg < RT_ELEMENTS(pCtx->u.X86.aArgs))
     1214                return pCtx->u.X86.aArgs[iArg];
     1215        }
     1216        else if (pCtx->cBits == 64)
     1217        {
     1218            if ((unsigned)iArg < RT_ELEMENTS(pCtx->u.Amd64.aArgs))
     1219                return pCtx->u.Amd64.aArgs[iArg];
     1220        }
     1221        else
     1222            AssertFailed();
     1223    }
     1224
     1225    return UINT64_MAX;
     1226}
     1227
     1228
     1229/**
     1230 * @callback_method_impl{dtrace_pops_t,dtps_destroy}
     1231 */
     1232static void    vboxDtPOps_Destroy(void *pvProv, dtrace_id_t idProbe, void *pvProbe)
     1233{
     1234    PSUPDRVVDTPROVIDERCORE  pProv  = (PSUPDRVVDTPROVIDERCORE)pvProv;
     1235    if (!pProv->TracerData.DTrace.fZombie)
     1236    {
     1237        PVTGPROBELOC    pProbeLoc  = (PVTGPROBELOC)pvProbe;
     1238        Assert(!pProbeLoc->fEnabled);
     1239        Assert(pProbeLoc->idProbe == idProbe); NOREF(idProbe);
     1240        pProbeLoc->idProbe = UINT32_MAX;
     1241    }
     1242    pProv->TracerData.DTrace.cProvidedProbes--;
     1243}
     1244
     1245
     1246
     1247/**
     1248 * DTrace provider method table.
     1249 */
     1250static const dtrace_pops_t g_vboxDtVtgProvOps =
     1251{
     1252    /* .dtps_provide         = */ vboxDtPOps_Provide,
     1253    /* .dtps_provide_module  = */ NULL,
     1254    /* .dtps_enable          = */ vboxDtPOps_Enable,
     1255    /* .dtps_disable         = */ vboxDtPOps_Disable,
     1256    /* .dtps_suspend         = */ NULL,
     1257    /* .dtps_resume          = */ NULL,
     1258    /* .dtps_getargdesc      = */ vboxDtPOps_GetArgDesc,
     1259    /* .dtps_getargval       = */ vboxDtPOps_GetArgVal,
     1260    /* .dtps_usermode        = */ NULL,
     1261    /* .dtps_destroy         = */ vboxDtPOps_Destroy
     1262};
     1263
     1264
     1265
     1266
     1267/*
     1268 *
     1269 * Support Driver Tracer Interface.
     1270 * Support Driver Tracer Interface.
     1271 * Support Driver Tracer Interface.
     1272 *
     1273 */
     1274
     1275
     1276
     1277/**
     1278 * interface_method_impl{SUPDRVTRACERREG,pfnProbeFireUser}
     1279 */
     1280static DECLCALLBACK(void) vbdt_ProbeFireKernel(struct VTGPROBELOC *pVtgProbeLoc, uintptr_t uArg0, uintptr_t uArg1, uintptr_t uArg2,
     1281                                               uintptr_t uArg3, uintptr_t uArg4)
     1282{
     1283    VBDT_SETUP_STACK_DATA(kVBoxDtCaller_ProbeFireKernel);
     1284
     1285    pStackData->u.ProbeFireKernel.uCaller      = (uintptr_t)ASMReturnAddress();
     1286    pStackData->u.ProbeFireKernel.pauStackArgs = &uArg4 + 1;
     1287    dtrace_probe(pVtgProbeLoc->idProbe, uArg0, uArg1, uArg2, uArg3, uArg4);
     1288
     1289    VBDT_CLEAR_STACK_DATA();
     1290    return ;
     1291}
     1292
     1293
     1294/**
     1295 * interface_method_impl{SUPDRVTRACERREG,pfnProbeFireUser}
     1296 */
     1297static DECLCALLBACK(void) vbdt_ProbeFireUser(PCSUPDRVTRACERREG pThis, PSUPDRVSESSION pSession, PCSUPDRVTRACERUSRCTX pCtx)
     1298{
     1299    VBDT_SETUP_STACK_DATA(kVBoxDtCaller_ProbeFireUser);
     1300
     1301    pStackData->u.ProbeFireUser.pCtx = pCtx;
     1302    if (pCtx->cBits == 32)
     1303        dtrace_probe(pCtx->idProbe,
     1304                     pCtx->u.X86.aArgs[0],
     1305                     pCtx->u.X86.aArgs[1],
     1306                     pCtx->u.X86.aArgs[2],
     1307                     pCtx->u.X86.aArgs[3],
     1308                     pCtx->u.X86.aArgs[4]);
     1309    else if (pCtx->cBits == 64)
     1310        dtrace_probe(pCtx->idProbe,
     1311                     pCtx->u.Amd64.aArgs[0],
     1312                     pCtx->u.Amd64.aArgs[1],
     1313                     pCtx->u.Amd64.aArgs[2],
     1314                     pCtx->u.Amd64.aArgs[3],
     1315                     pCtx->u.Amd64.aArgs[4]);
     1316    else
     1317        AssertFailed();
     1318
     1319    VBDT_CLEAR_STACK_DATA();
     1320}
     1321
     1322
     1323/**
     1324 * interface_method_impl{SUPDRVTRACERREG,pfnTracerOpen}
     1325 */
     1326static DECLCALLBACK(int) vbdt_TracerOpen(PCSUPDRVTRACERREG pThis, PSUPDRVSESSION pSession, uint32_t uCookie, uintptr_t uArg,
     1327                                         uintptr_t *puSessionData)
     1328{
     1329    if (uCookie != RT_MAKE_U32_FROM_U8('V', 'B', 'D', 'T'))
     1330        return VERR_INVALID_MAGIC;
     1331    if (uArg)
     1332        return VERR_INVALID_PARAMETER;
     1333
     1334    VBDT_SETUP_STACK_DATA(kVBoxDtCaller_Generic);
     1335
     1336    int rc = dtrace_open((dtrace_state_t **)puSessionData, VBoxDtGetCurrentCreds());
     1337
     1338    VBDT_CLEAR_STACK_DATA();
     1339    return RTErrConvertFromErrno(rc);
     1340}
     1341
     1342
     1343/**
     1344 * interface_method_impl{SUPDRVTRACERREG,pfnTracerClose}
     1345 */
     1346static DECLCALLBACK(int) vbdt_TracerIoCtl(PCSUPDRVTRACERREG pThis, PSUPDRVSESSION pSession, uintptr_t uSessionData,
     1347                                          uintptr_t uCmd, uintptr_t uArg, int32_t *piRetVal)
     1348{
     1349    AssertPtrReturn(uSessionData, VERR_INVALID_POINTER);
     1350    VBDT_SETUP_STACK_DATA(kVBoxDtCaller_Generic);
     1351
     1352    int rc = dtrace_ioctl((dtrace_state_t *)uSessionData, (intptr_t)uCmd, (intptr_t)uArg, piRetVal);
     1353
     1354    VBDT_CLEAR_STACK_DATA();
     1355    return VINF_SUCCESS;
     1356}
     1357
     1358
     1359/**
     1360 * interface_method_impl{SUPDRVTRACERREG,pfnTracerClose}
     1361 */
     1362static DECLCALLBACK(void) vbdt_TracerClose(PCSUPDRVTRACERREG pThis, PSUPDRVSESSION pSession, uintptr_t uSessionData)
     1363{
     1364    AssertPtrReturnVoid(uSessionData);
     1365    VBDT_SETUP_STACK_DATA(kVBoxDtCaller_Generic);
     1366
     1367    dtrace_close((dtrace_state_t *)uSessionData);
     1368
     1369    VBDT_CLEAR_STACK_DATA();
     1370}
     1371
     1372
     1373/**
     1374 * interface_method_impl{SUPDRVTRACERREG,pfnProviderRegister}
     1375 */
     1376static DECLCALLBACK(int) vbdt_ProviderRegister(PCSUPDRVTRACERREG pThis, PSUPDRVVDTPROVIDERCORE pCore)
     1377{
     1378    AssertReturn(pCore->TracerData.DTrace.idProvider == UINT32_MAX || pCore->TracerData.DTrace.idProvider == 0,
     1379                 VERR_INTERNAL_ERROR_3);
     1380    VBDT_SETUP_STACK_DATA(kVBoxDtCaller_Generic);
     1381
     1382    PVTGDESCPROVIDER    pDesc = pCore->pDesc;
     1383    dtrace_pattr_t      DtAttrs;
     1384    vboxDtVtgConvAttr(&DtAttrs.dtpa_provider, &pDesc->AttrSelf);
     1385    vboxDtVtgConvAttr(&DtAttrs.dtpa_mod,      &pDesc->AttrModules);
     1386    vboxDtVtgConvAttr(&DtAttrs.dtpa_func,     &pDesc->AttrFunctions);
     1387    vboxDtVtgConvAttr(&DtAttrs.dtpa_name,     &pDesc->AttrNames);
     1388    vboxDtVtgConvAttr(&DtAttrs.dtpa_args,     &pDesc->AttrArguments);
     1389
     1390    dtrace_provider_id_t idProvider;
     1391    int rc = dtrace_register(pCore->pszName,
     1392                             &DtAttrs,
     1393                             DTRACE_PRIV_KERNEL,
     1394                             NULL /* cred */,
     1395                             &g_vboxDtVtgProvOps,
     1396                             pCore,
     1397                             &idProvider);
     1398    if (!rc)
     1399    {
     1400        Assert(idProvider != UINT32_MAX && idProvider != 0);
     1401        pCore->TracerData.DTrace.idProvider = idProvider;
     1402        Assert(pCore->TracerData.DTrace.idProvider == idProvider);
     1403        rc = VINF_SUCCESS;
     1404    }
     1405    else
     1406        rc = RTErrConvertFromErrno(rc);
     1407
     1408    VBDT_CLEAR_STACK_DATA();
     1409    return rc;
     1410}
     1411
     1412
     1413/**
     1414 * interface_method_impl{SUPDRVTRACERREG,pfnProviderDeregister}
     1415 */
     1416static DECLCALLBACK(int) vbdt_ProviderDeregister(PCSUPDRVTRACERREG pThis, PSUPDRVVDTPROVIDERCORE pCore)
     1417{
     1418    uint32_t idProvider = pCore->TracerData.DTrace.idProvider;
     1419    AssertReturn(idProvider != UINT32_MAX && idProvider != 0, VERR_INTERNAL_ERROR_4);
     1420    VBDT_SETUP_STACK_DATA(kVBoxDtCaller_Generic);
     1421
     1422    dtrace_invalidate(idProvider);
     1423    int rc = dtrace_unregister(idProvider);
     1424    if (!rc)
     1425    {
     1426        pCore->TracerData.DTrace.idProvider = UINT32_MAX;
     1427        rc = VINF_SUCCESS;
     1428    }
     1429    else
     1430    {
     1431        AssertMsg(rc == EBUSY, ("%d\n", rc));
     1432        rc = VERR_TRY_AGAIN;
     1433    }
     1434
     1435    VBDT_CLEAR_STACK_DATA();
     1436    return rc;
     1437}
     1438
     1439
     1440/**
     1441 * interface_method_impl{SUPDRVTRACERREG,pfnProviderDeregisterZombie}
     1442 */
     1443static DECLCALLBACK(int) vbdt_ProviderDeregisterZombie(PCSUPDRVTRACERREG pThis, PSUPDRVVDTPROVIDERCORE pCore)
     1444{
     1445    uint32_t idProvider = pCore->TracerData.DTrace.idProvider;
     1446    AssertReturn(idProvider != UINT32_MAX && idProvider != 0, VERR_INTERNAL_ERROR_4);
     1447    VBDT_SETUP_STACK_DATA(kVBoxDtCaller_Generic);
     1448
     1449    int rc = dtrace_unregister(idProvider);
     1450    if (!rc)
     1451    {
     1452        pCore->TracerData.DTrace.idProvider = UINT32_MAX;
     1453        rc = VINF_SUCCESS;
     1454    }
     1455    else
     1456    {
     1457        AssertMsg(rc == EBUSY, ("%d\n", rc));
     1458        rc = VERR_TRY_AGAIN;
     1459    }
     1460
     1461    VBDT_CLEAR_STACK_DATA();
     1462    return rc;
     1463}
     1464
     1465
     1466
     1467/**
     1468 * The tracer registration record of the VBox DTrace implementation
     1469 */
     1470static SUPDRVTRACERREG g_VBoxDTraceReg =
     1471{
     1472    SUPDRVTRACERREG_MAGIC,
     1473    SUPDRVTRACERREG_VERSION,
     1474    vbdt_ProbeFireKernel,
     1475    vbdt_ProbeFireUser,
     1476    vbdt_TracerOpen,
     1477    vbdt_TracerIoCtl,
     1478    vbdt_TracerClose,
     1479    vbdt_ProviderRegister,
     1480    vbdt_ProviderDeregister,
     1481    vbdt_ProviderDeregisterZombie,
     1482    SUPDRVTRACERREG_MAGIC
     1483};
     1484
  • trunk/src/VBox/ExtPacks/VBoxDTrace/include/VBoxDTraceTypes.h

    r53665 r53667  
    230230
    231231
    232 typedef struct VBoxDtProcess
     232typedef struct VBoxDtProcess    proc_t;
     233# if 0 /* not needed ? */
     234struct VBoxDtProcess    proc_t;
    233235{
    234     uint32_t                p_flag;
     236/*    uint32_t                p_flag; - don't bother with this */
    235237    RTPROCESS               p_pid;
    236238    struct dtrace_helpers  *p_dtrace_helpers;
    237     struct VBoxDtCred      *p_cred;
    238 } proc_t;
     239}
    239240proc_t *VBoxDtGetCurrentProc(void);
    240 #define curproc                     (VBoxDtGetCurrentProc())
    241 
    242 #define SNOCD                   RT_BIT(0)
    243 
     241# define curproc                 (VBoxDtGetCurrentProc())
     242/*# define SNOCD                  RT_BIT(0) - don't bother with this */
     243# endif
    244244
    245245typedef struct VBoxDtTaskQueue  taskq_t;
     
    331331
    332332
    333 typedef struct VBoxDtVMem
    334 {
    335     size_t                  cbTodo;
    336     void                   *pvTodo;
    337 } vmem_t;
     333typedef struct VBoxDtVMem       vmem_t;
    338334#define VM_SLEEP                RT_BIT(0)
    339335#define VM_BESTFIT              RT_BIT(1)
     
    372368 * DDI
    373369 */
    374 #define DDI_SUCCESS                 (0)
    375 #define DDI_FAILURE                 (-1)
    376 #define ddi_soft_state_init         VBoxDtDdiSoftStateInit
    377 #define ddi_soft_state_fini         VBoxDtDdiSoftStateTerm
    378 #define ddi_soft_state_zalloc       VBoxDtDdiSoftStateAllocZ
    379 #define ddi_get_soft_state          VBoxDtDdiSoftStateGet
    380 #define ddi_soft_state_free         VBoxDtDdiSoftStateFree
     370# define DDI_SUCCESS                (0)
     371# define DDI_FAILURE                (-1)
     372# if 0 /* not needed */
     373# define ddi_soft_state_init        VBoxDtDdiSoftStateInit
     374# define ddi_soft_state_fini        VBoxDtDdiSoftStateTerm
     375# define ddi_soft_state_zalloc      VBoxDtDdiSoftStateAllocZ
     376# define ddi_get_soft_state         VBoxDtDdiSoftStateGet
     377# define ddi_soft_state_free        VBoxDtDdiSoftStateFree
    381378int   VBoxDtDdiSoftStateInit(void **ppvSoftStates, size_t cbSoftState, uint32_t cMaxItems);
    382379int   VBoxDtDdiSoftStateTerm(void **ppvSoftStates);
     
    384381int   VBoxDtDdiSoftStateFree(void *pvSoftStates, RTDEV uMinor);
    385382void *VBoxDtDdiSoftStateGet(void *pvSoftStates, RTDEV uMinor);
    386 
    387 typedef struct VBoxDtDevInfo        dev_info_t;
     383# endif
     384
    388385typedef enum { DDI_ATT_CMD_DUMMY }  ddi_attach_cmd_t;
    389386typedef enum { DDI_DETACH, DDI_SUSPEND }  ddi_detach_cmd_t;
    390 #define ddi_driver_major            VBoxDtDdiDriverMajor
    391 #define ddi_report_dev              VBoxDtDdiReportDev
     387# if 0 /* not needed */
     388typedef struct VBoxDtDevInfo        dev_info_t;
     389# define ddi_driver_major           VBoxDtDdiDriverMajor
     390# define ddi_report_dev             VBoxDtDdiReportDev
    392391major_t VBoxDtDdiDriverMajor(struct VBoxDtDevInfo *pDevInfo);
    393392void    VBoxDtDdiReportDev(struct VBoxDtDevInfo *pDevInfo);
     393# endif
    394394
    395395/*
    396396 * DTrace bits we've made external.
    397397 */
    398 extern int dtrace_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
    399 extern int dtrace_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
    400 extern int dtrace_ioctl(dev_t dev, int cmd, intptr_t arg, int md, cred_t *cr, int *rv);
     398extern int dtrace_attach(ddi_attach_cmd_t cmd);
     399extern int dtrace_detach(ddi_detach_cmd_t cmd);
     400struct dtrace_state;
     401extern int dtrace_open(struct dtrace_state **ppState, struct VBoxDtCred *cred_p);
     402extern int dtrace_ioctl(struct dtrace_state *state, int cmd, intptr_t arg, int32_t *rv);
     403extern int dtrace_close(struct dtrace_state *state);
    401404
    402405#endif /* IN_RING0 */
  • trunk/src/VBox/ExtPacks/VBoxDTrace/onnv/uts/common/dtrace/dtrace.c

    r53666 r53667  
    206206 * DTrace Internal Variables
    207207 */
     208#ifndef VBOX
    208209static dev_info_t       *dtrace_devi;           /* device info */
     210#endif
    209211static vmem_t           *dtrace_arena;          /* probe ID arena */
     212#ifndef VBOX
    210213static vmem_t           *dtrace_minor;          /* minor number arena */
    211 #ifndef VBOX
    212214static taskq_t          *dtrace_taskq;          /* task queue */
    213215#endif
     
    218220static int              dtrace_opens;           /* number of opens */
    219221static int              dtrace_helpers;         /* number of helpers */
     222#ifndef VBOX
    220223static void             *dtrace_softstate;      /* softstate pointer */
     224#endif
    221225static dtrace_hash_t    *dtrace_bymod;          /* probes hashed by module */
    222226static dtrace_hash_t    *dtrace_byfunc;         /* probes hashed by function */
     
    518522static void dtrace_enabling_matchall(void);
    519523static dtrace_state_t *dtrace_anon_grab(void);
     524#ifndef VBOX
    520525static uint64_t dtrace_helper(int, dtrace_mstate_t *,
    521526    dtrace_state_t *, uint64_t, uint64_t);
    522527static dtrace_helpers_t *dtrace_helpers_create(proc_t *);
     528#endif
    523529static void dtrace_buffer_drop(dtrace_buffer_t *);
    524530static intptr_t dtrace_buffer_reserve(dtrace_buffer_t *, size_t, size_t,
     
    11521158dtrace_priv_proc_common_nocd(VBDTVOID)
    11531159{
     1160#ifndef VBOX
    11541161        proc_t *proc;
    11551162
     
    11591166
    11601167        return (0);
     1168#else
     1169        return (1);
     1170#endif
    11611171}
    11621172
     
    25192529}
    25202530
     2531#ifdef VBOX
     2532/** */
     2533static DECLCALLBACK(void) dtrace_speculation_clean_here_wrapper(RTCPUID idCpu, void *pvUser1, void *pvUser2)
     2534{
     2535    dtrace_speculation_clean_here((dtrace_state_t *)pvUser1);
     2536    NOREF(pvUser2); NOREF(idCpu);
     2537}
     2538#endif
     2539
    25212540/*
    25222541 * Note:  not called from probe context.  This function is called
     
    25492568                return;
    25502569
     2570#ifndef VBOX
    25512571        dtrace_xcall(DTRACE_CPUALL,
    25522572            (dtrace_xcall_t)dtrace_speculation_clean_here, state);
     2573#else
     2574        RTMpOnAll(dtrace_speculation_clean_here_wrapper, state, NULL);
     2575#endif
    25532576
    25542577        /*
     
    56925715                        break;
    56935716
     5717#ifndef VBOX
    56945718                sym = (char *)(uintptr_t)dtrace_helper(
    56955719                    DTRACE_HELPER_ACTION_USTACK,
    56965720                    mstate, state, pcs[i], fps[i]);
     5721#else
     5722                sym = NULL;
     5723#endif
    56975724
    56985725                /*
     
    59295956                                    s_cr->cr_gid != cr->cr_rgid ||
    59305957                                    s_cr->cr_gid != cr->cr_sgid ||
     5958#ifndef VBOX
    59315959                                    (proc = VBDT_GET_PROC()) == NULL ||
    59325960                                    (proc->p_flag & SNOCD))
     5961#else
     5962                                    0)
     5963
     5964#endif
    59335965                                        continue;
    59345966                        }
     
    61056137                                }
    61066138
     6139#ifndef VBOX /* no helpers */
    61076140                                if (DTRACE_USTACK_STRSIZE(rec->dtrd_arg) != 0 &&
    61086141                                    curproc->p_dtrace_helpers != NULL) {
     
    61196152                                        continue;
    61206153                                }
     6154#endif
    61216155
    61226156                                DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
     
    72777311                 */
    72787312                ASSERT(old == dtrace_provider);
     7313#ifndef VBOX
    72797314                ASSERT(dtrace_devi != NULL);
     7315#endif
    72807316                ASSERT(MUTEX_HELD(&dtrace_provider_lock));
    72817317                ASSERT(MUTEX_HELD(&dtrace_lock));
     
    73807416
    73817417        if ((prev = dtrace_provider) == old) {
     7418#ifndef VBOX
    73827419                ASSERT(self || dtrace_devi == NULL);
    73837420                ASSERT(old->dtpv_next == NULL || dtrace_devi == NULL);
     7421#endif
    73847422                dtrace_provider = old->dtpv_next;
    73857423        } else {
     
    1034810386}
    1034910387
     10388#ifdef VBOX
     10389static DECLCALLBACK(void) dtrace_buffer_switch_wrapper(RTCPUID idCpu, void *pvUser1, void *pvUser2)
     10390{
     10391    dtrace_buffer_switch((dtrace_buffer_t *)pvUser1);
     10392    NOREF(pvUser2); NOREF(idCpu);
     10393}
     10394#endif
     10395
    1035010396/*
    1035110397 * Note:  called from cross call context.  This function activates a buffer
     
    1037410420        dtrace_interrupt_enable(cookie);
    1037510421}
     10422
     10423#ifdef VBOX
     10424static DECLCALLBACK(void) dtrace_buffer_activate_wrapper(RTCPUID idCpu, void *pvUser1, void *pvUser2)
     10425{
     10426    dtrace_buffer_activate((dtrace_state_t *)pvUser1);
     10427    NOREF(pvUser2); NOREF(idCpu);
     10428}
     10429#endif
    1037610430
    1037710431static int
     
    1245112505
    1245212506VBDTSTATIC dtrace_state_t *
     12507#ifdef VBOX
     12508dtrace_state_create(cred_t *cr)
     12509#else
    1245312510dtrace_state_create(dev_t *devp, cred_t *cr)
     12511#endif
    1245412512{
    1245512513        minor_t minor;
     
    1246312521        ASSERT(MUTEX_HELD(&cpu_lock));
    1246412522
     12523#ifndef VBOX
    1246512524        minor = (minor_t)(uintptr_t)vmem_alloc(dtrace_minor, 1,
    1246612525            VM_BESTFIT | VM_SLEEP);
     
    1247212531
    1247312532        state = ddi_get_soft_state(dtrace_softstate, minor);
     12533#else
     12534        state = kmem_alloc(sizeof (*state), KM_SLEEP);
     12535        if (!state) {
     12536            return (NULL);
     12537        }
     12538#endif
    1247412539        state->dts_epid = DTRACE_EPIDNONE + 1;
    1247512540
     
    1247812543            NULL, NULL, NULL, 0, VM_SLEEP | VMC_IDENTIFIER);
    1247912544
     12545#ifndef VBOX
    1248012546        if (devp != NULL) {
    1248112547                major = getemajor(*devp);
     
    1248812554        if (devp != NULL)
    1248912555                *devp = state->dts_dev;
     12556#endif
    1249012557
    1249112558        /*
     
    1303113098         * processing all of them.
    1303213099         */
     13100#ifndef VBOX
    1303313101        dtrace_xcall(DTRACE_CPUALL,
    1303413102            (dtrace_xcall_t)dtrace_buffer_activate, state);
     13103#else
     13104        RTMpOnAll(dtrace_buffer_activate_wrapper, state, NULL);
     13105#endif
    1303513106        goto out;
    1303613107
     
    1317813249        dtrace_ecb_t *ecb;
    1317913250        dtrace_vstate_t *vstate = &state->dts_vstate;
     13251#ifndef VBOX
    1318013252        minor_t minor = getminor(state->dts_dev);
     13253#endif
    1318113254        int i, bufsize = NCPU * sizeof (dtrace_buffer_t);
    1318213255        dtrace_speculation_t *spec = state->dts_speculations;
     
    1328513358
    1328613359        vmem_destroy(state->dts_aggid_arena);
     13360#ifndef VBOX
    1328713361        ddi_soft_state_free(dtrace_softstate, minor);
    1328813362        vmem_free(dtrace_minor, (void *)(uintptr_t)minor, 1);
     13363#else
     13364        kmem_free(state, sizeof (*state));
     13365#endif
    1328913366}
    1329013367
     
    1342013497 * DTrace Helper Functions
    1342113498 */
     13499#ifndef VBOX /* No helper stuff */
    1342213500static void
    1342313501dtrace_helper_trace(dtrace_helper_action_t *helper,
     
    1441514493}
    1441614494
    14417 #ifndef VBOX
    14418 
    1441914495/*
    1442014496 * DTrace Hook Functions
     
    1469714773 * DTrace Driver Cookbook Functions
    1469814774 */
    14699 #ifndef VBOX
     14775#ifdef VBOX
     14776int dtrace_attach(ddi_attach_cmd_t cmd)
     14777#else
    1470014778/*ARGSUSED*/
    1470114779static int
    1470214780dtrace_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
    14703 #else
    14704 int dtrace_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
    1470514781#endif
    1470614782{
     
    1471314789        mutex_enter(&dtrace_lock);
    1471414790
     14791#ifndef VBOX
    1471514792        if (ddi_soft_state_init(&dtrace_softstate,
    1471614793            sizeof (dtrace_state_t), 0) != 0) {
     
    1472214799        }
    1472314800
    14724 #ifndef VBOX
    1472514801        if (ddi_create_minor_node(devi, DTRACEMNR_DTRACE, S_IFCHR,
    1472614802            DTRACEMNRN_DTRACE, DDI_PSEUDO, NULL) == DDI_FAILURE ||
     
    1473514811                return (DDI_FAILURE);
    1473614812        }
    14737 #endif
    1473814813
    1473914814        ddi_report_dev(devi);
    1474014815        dtrace_devi = devi;
    1474114816
    14742 #ifndef VBOX
    1474314817        dtrace_modload = dtrace_module_loaded;
    1474414818        dtrace_modunload = dtrace_module_unloaded;
     
    1476014834        dtrace_arena = vmem_create("dtrace", (void *)1, UINT32_MAX, 1,
    1476114835            NULL, NULL, NULL, 0, VM_SLEEP | VMC_IDENTIFIER);
     14836#ifndef VBOX
    1476214837        dtrace_minor = vmem_create("dtrace_minor", (void *)DTRACEMNRN_CLONE,
    1476314838            UINT32_MAX - DTRACEMNRN_CLONE, 1, NULL, NULL, NULL, 0,
    1476414839            VM_SLEEP | VMC_IDENTIFIER);
    14765 #ifndef VBOX
    1476614840        dtrace_taskq = taskq_create("dtrace_taskq", 1, maxclsyspri,
    1476714841            1, INT_MAX, 0);
     
    1487814952}
    1487914953
     14954#ifdef VBOX
     14955int dtrace_open(dtrace_state_t **ppState, cred_t *cred_p)
     14956#else
    1488014957/*ARGSUSED*/
    1488114958static int
    1488214959dtrace_open(dev_t *devp, int flag, int otyp, cred_t *cred_p)
     14960#endif
    1488314961{
    1488414962        dtrace_state_t *state;
     
    1488714965        zoneid_t zoneid;
    1488814966
     14967#ifndef VBOX
    1488914968        if (getminor(*devp) == DTRACEMNRN_HELPER)
    1489014969                return (0);
     
    1489614975        if (getminor(*devp) != DTRACEMNRN_DTRACE)
    1489714976                return (ENXIO);
     14977#endif /* !VBOX */
    1489814978
    1489914979        /*
     
    1493015010#endif
    1493115011
     15012#ifndef VBOX
    1493215013        state = dtrace_state_create(devp, cred_p);
     15014#else
     15015        state = dtrace_state_create(cred_p);
     15016#endif
    1493315017        mutex_exit(&cpu_lock);
    1493415018
     
    1494415028        mutex_exit(&dtrace_lock);
    1494515029
     15030#ifdef VBOX
     15031        *ppState = state;
     15032#endif
    1494615033        return (0);
    1494715034}
    1494815035
     15036#ifdef VBOX
     15037int dtrace_close(dtrace_state_t *state)
     15038#else
    1494915039/*ARGSUSED*/
    1495015040static int
    1495115041dtrace_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
    14952 {
     15042#endif
     15043{
     15044#ifndef VBOX
    1495315045        minor_t minor = getminor(dev);
    1495415046        dtrace_state_t *state;
     
    1495815050
    1495915051        state = ddi_get_soft_state(dtrace_softstate, minor);
     15052#endif
    1496015053
    1496115054        mutex_enter(&cpu_lock);
     
    1504615139#endif /* !VBOX */
    1504715140
     15141#ifdef VBOX
     15142int dtrace_ioctl(dtrace_state_t *state, int cmd, intptr_t arg, int32_t *rv)
     15143#else
    1504815144/*ARGSUSED*/
    15049 #ifndef VBOX
    1505015145static int
    1505115146dtrace_ioctl(dev_t dev, int cmd, intptr_t arg, int md, cred_t *cr, int *rv)
    15052 #else
    15053 int dtrace_ioctl(dev_t dev, int cmd, intptr_t arg, int md, cred_t *cr, int *rv)
    1505415147#endif
    1505515148{
     15149#ifndef VBOX
    1505615150        minor_t minor = getminor(dev);
    1505715151        dtrace_state_t *state;
     15152#endif
    1505815153        int rval;
    1505915154
     
    1506115156        if (minor == DTRACEMNRN_HELPER)
    1506215157                return (dtrace_ioctl_helper(cmd, arg, rv));
     15158
     15159        state = ddi_get_soft_state(dtrace_softstate, minor);
    1506315160#endif
    15064 
    15065         state = ddi_get_soft_state(dtrace_softstate, minor);
    1506615161
    1506715162        if (state->dts_anon) {
     
    1528115376                dtrace_vstate_t *vstate;
    1528215377                int err = 0;
     15378#ifdef VBOX
     15379                cred_t *cr = CRED();
     15380#endif
    1528315381
    1528415382                *rv = 0;
     
    1537215470                uid_t uid;
    1537315471                zoneid_t zoneid;
     15472#ifdef VBOX
     15473                cred_t *cr = CRED();
     15474#endif
    1537415475
    1537515476                if (copyin((void *)arg, &desc, sizeof (desc)) != 0)
     
    1562915730                ASSERT(!(buf->dtb_flags & DTRACEBUF_NOSWITCH));
    1563015731
     15732#ifndef VBOX
    1563115733                dtrace_xcall(desc.dtbd_cpu,
    1563215734                    (dtrace_xcall_t)dtrace_buffer_switch, buf);
     15735#else
     15736                if ((int32_t)desc.dtbd_cpu == DTRACE_CPUALL)
     15737                    RTMpOnAll(dtrace_buffer_switch_wrapper, buf, NULL);
     15738                else
     15739                    RTMpOnSpecific(desc.dtbd_cpu, dtrace_buffer_switch_wrapper, buf, NULL);
     15740#endif
    1563315741
    1563415742                state->dts_errors += buf->dtb_xamot_errors;
     
    1580915917}
    1581015918
    15811 #ifndef VBOX
     15919#ifdef VBOX
     15920int dtrace_detach(ddi_detach_cmd_t cmd)
     15921#else
    1581215922/*ARGSUSED*/
    1581315923static int
    1581415924dtrace_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
    15815 #else
    15816 int dtrace_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
    1581715925#endif
    1581815926{
     
    1590316011
    1590416012        kmem_cache_destroy(dtrace_state_cache);
     16013#ifndef VBOX
    1590516014        vmem_destroy(dtrace_minor);
     16015#endif
    1590616016        vmem_destroy(dtrace_arena);
    1590716017
     
    1591616026#ifndef VBOX
    1591716027        ddi_remove_minor_node(dtrace_devi, NULL);
     16028        dtrace_devi = NULL;
     16029
     16030        ddi_soft_state_fini(&dtrace_softstate);
    1591816031#endif
    15919         dtrace_devi = NULL;
    15920 
    15921         ddi_soft_state_fini(&dtrace_softstate);
    1592216032
    1592316033        ASSERT(dtrace_vtime_references == 0);
  • trunk/src/VBox/ExtPacks/VBoxDTrace/onnv/uts/common/sys/dtrace_impl.h

    r53642 r53667  
    11021102 */
    11031103struct dtrace_state {
     1104#ifndef VBOX
    11041105        dev_t dts_dev;                          /* device */
     1106#endif
    11051107        int dts_necbs;                          /* total number of ECBs */
    11061108        dtrace_ecb_t **dts_ecbs;                /* array of ECBs */
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette