VirtualBox

Changeset 41117 in vbox


Ignore:
Timestamp:
May 2, 2012 2:22:29 PM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
77725
Message:

SUP,VBoxTpG,++: Initial implementation of generic user module tracepoints. (disabled)

Location:
trunk
Files:
1 added
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/Config.kmk

    r41101 r41117  
    614614# Set this to enable user mode dtrace probes.
    615615if1of ($(KBUILD_TARGET), darwin solaris)
    616  VBOX_WITH_DTRACE_R3 = 1
     616# VBOX_WITH_DTRACE_R3 = 1
    617617endif
    618618# Set this to enable kernel driver dtrace probes.
    619619if1of ($(KBUILD_TARGET), darwin solaris)
    620  VBOX_WITH_DTRACE_R0DRV = 1
     620# VBOX_WITH_DTRACE_R0DRV = 1
    621621endif
    622622# Set this to enable dtrace probes in platform agnostic kernel code.
     
    33163316        -Wl,--rpath-link,$(L4_LIBDIR)
    33173317TEMPLATE_VBOXR3EXE_LDFLAGS.linux       = -Wl,-z,noexecstack $(VBOX_LD_as_needed)
    3318 ifdef VBOX_WITH_DTRACE_R3
    3319  TEMPLATE_VBOXR3EXE_LDFLAGS.linux     += -Wl,--verbose
    3320 endif
    33213318
    33223319 ifeq ($(KBUILD_TARGET),linux)
  • trunk/include/VBox/VBoxTpG.h

    r40986 r41117  
    3434RT_C_DECLS_BEGIN
    3535
     36/**
     37 * 32-bit probe location.
     38 */
     39typedef struct VTGPROBELOC32
     40{
     41    uint32_t    uLine    : 31;
     42    uint32_t    fEnabled : 1;
     43    uint32_t    idProbe;
     44    uint32_t    pszFunction;
     45    uint32_t    pbProbe;
     46} VTGPROBELOC32;
     47AssertCompileSize(VTGPROBELOC32, 16);
     48/** Pointer to a 32-bit probe location. */
     49typedef VTGPROBELOC32 *PVTGPROBELOC32;
     50/** Pointer to a const 32-bit probe location. */
     51typedef VTGPROBELOC32 const *PCVTGPROBELOC32;
     52
     53/**
     54 * 64-bit probe location.
     55 */
     56typedef struct VTGPROBELOC64
     57{
     58    uint32_t    uLine    : 31;
     59    uint32_t    fEnabled : 1;
     60    uint32_t    idProbe;
     61    uint64_t    pszFunction;
     62    uint64_t    pbProbe;
     63    uint64_t    uAlignment;
     64} VTGPROBELOC64;
     65AssertCompileSize(VTGPROBELOC64, 32);
     66/** Pointer to a 64-bit probe location. */
     67typedef VTGPROBELOC64 *PVTGPROBELOC64;
     68/** Pointer to a const 64-bit probe location. */
     69typedef VTGPROBELOC64 const *PCVTGPROBELOC64;
     70
    3671
    3772/**
     
    5287/** Pointer to a probe location. */
    5388typedef VTGPROBELOC *PVTGPROBELOC;
     89/** Pointer to a const probe location. */
     90typedef VTGPROBELOC const *PCVTGPROBELOC;
    5491
    5592/** @def VTG_OBJ_SECT
     
    154191/** Pointer to an argument descriptor. */
    155192typedef VTGDESCARG         *PVTGDESCARG;
     193/** Pointer to a const argument descriptor. */
     194typedef VTGDESCARG const *PCVTGDESCARG;
    156195
    157196
     
    168207/** Pointer to a VTG argument list descriptor. */
    169208typedef VTGDESCARGLIST     *PVTGDESCARGLIST;
     209/** Pointer to a const VTG argument list descriptor. */
     210typedef VTGDESCARGLIST const *PCVTGDESCARGLIST;
    170211
    171212
     
    181222    /** The distance from this structure to the VTG object header. */
    182223    int32_t         offObjHdr;
    183     uint32_t        u32User;
    184     uint32_t        u32User2;
    185224} VTGDESCPROBE;
    186 AssertCompileSize(VTGDESCPROBE, 24);
     225AssertCompileSize(VTGDESCPROBE, 16);
    187226/** Pointer to a VTG probe descriptor. */
    188227typedef VTGDESCPROBE       *PVTGDESCPROBE;
     228/** Pointer to a const VTG probe descriptor. */
     229typedef VTGDESCPROBE const *PCVTGDESCPROBE;
    189230
    190231
     
    253294/** Pointer to a VTG provider descriptor. */
    254295typedef VTGDESCPROVIDER    *PVTGDESCPROVIDER;
     296/** Pointer to a const VTG provider descriptor. */
     297typedef VTGDESCPROVIDER const *PCVTGDESCPROVIDER;
    255298
    256299
     
    260303typedef struct VTGOBJHDR
    261304{
     305    /** Magic value (VTGOBJHDR_MAGIC). */
    262306    char                szMagic[24];
     307    /** The bitness of the structures.
     308     * This only affects the probe location pointers and structures. */
    263309    uint32_t            cBits;
    264     uint32_t            u32Reserved0;
    265     PVTGDESCPROVIDER    paProviders;
    266     uintptr_t           cbProviders;
    267     PVTGDESCPROBE       paProbes;
    268     uintptr_t           cbProbes;
    269     bool               *pafProbeEnabled;
    270     uintptr_t           cbProbeEnabled;
    271     char               *pachStrTab;
    272     uintptr_t           cbStrTab;
    273     PVTGDESCARGLIST     paArgLists;
    274     uintptr_t           cbArgLists;
    275     PVTGPROBELOC        paProbLocs;
    276     PVTGPROBELOC        paProbLocsEnd;
    277     uintptr_t           auReserved1[4];
     310    /** The size of the VTG object. This excludes the probe locations. */
     311    uint32_t            cbObj;
     312
     313    /** @name Area Descriptors
     314     * @remarks The offsets are relative to the header.  The members are
     315     *          ordered by ascending offset (maybe with the exception of the
     316     *          probe locations).  No overlaps, though there might be zero
     317     *          filled gaps between them due to alignment.
     318     * @{ */
     319    /* 32: */
     320    /** Offset of the string table (char) relative to this header. */
     321    uint32_t            offStrTab;
     322    /** The size of the string table, in bytes. */
     323    uint32_t            cbStrTab;
     324    /** Offset of the argument lists (VTGDESCARGLIST - variable size) relative
     325     * to this header. */
     326    uint32_t            offArgLists;
     327    /** The size of the argument lists, in bytes. */
     328    uint32_t            cbArgLists;
     329    /* 48: */
     330    /** Offset of the probe array (VTGDESCPROBE) relative to this header. */
     331    uint32_t            offProbes;
     332    /** The size of the probe array, in bytes. */
     333    uint32_t            cbProbes;
     334    /** Offset of the provider array (VTGDESCPROVIDER) relative to this
     335     * header. */
     336    uint32_t            offProviders;
     337    /** The size of the provider array, in bytes. */
     338    uint32_t            cbProviders;
     339    /* 64: */
     340    /** Offset of the probe-enabled array (uint32_t) relative to this
     341     * header. */
     342    uint32_t            offProbeEnabled;
     343    /** The size of the probe-enabled array, in bytes. */
     344    uint32_t            cbProbeEnabled;
     345    /** Offset of the probe location array (VTGPROBELOC) relative to this
     346     * header.
     347     * @remarks This is filled in by the first VTG user using uProbeLocs. */
     348    int32_t             offProbeLocs;
     349    /** The size of the probe location array, in bytes.
     350     * @remarks This is filled in by the first VTG user using uProbeLocs. */
     351    uint32_t            cbProbeLocs;
     352    /** @}  */
     353    /* 80: */
     354    /**
     355     * The probe location array is generated by C code and lives in a
     356     * different section/subsection/segment than the rest of the data.
     357     *
     358     * The assembler cannot generate offsets across sections for most (if not
     359     * all) object formats, so we have to store pointers here.  The first user
     360     * of the data will convert these two members into offset and size and fill
     361     * in the offProbeLocs and cbProbeLocs members above.
     362     *
     363     * @remarks Converting these members to offset+size and reusing the members
     364     *          to store the converted values isn't possible because of
     365     *          raw-mode context modules having relocations associated with the
     366     *          fields.
     367     */
     368    union
     369    {
     370        PVTGPROBELOC    p;
     371        uintptr_t       uPtr;
     372        uint32_t        u32;
     373        uint64_t        u64;
     374    }
     375    /** Pointer to the probe location array. */
     376                        uProbeLocs,
     377    /** Pointer to the end of the probe location array. */
     378                        uProbeLocsEnd;
     379    /** UUID for making sharing ring-0 structures for the same ring-3
     380     * modules easier. */
     381    RTUUID              Uuid;
     382    /** Reserved / alignment. */
     383    uint32_t            au32Reserved1[4];
    278384} VTGOBJHDR;
     385AssertCompileSize(VTGOBJHDR, 128);
     386AssertCompileMemberAlignment(VTGOBJHDR, uProbeLocs, 8);
     387AssertCompileMemberAlignment(VTGOBJHDR, uProbeLocsEnd, 8);
    279388/** Pointer to a VTG data object header. */
    280389typedef VTGOBJHDR          *PVTGOBJHDR;
     390/** Pointer to a const VTG data object header. */
     391typedef VTGOBJHDR const    *PCVTGOBJHDR;
    281392
    282393/** The current VTGOBJHDR::szMagic value. */
    283 #define VTGOBJHDR_MAGIC     "VTG Object Header v1.4\0"
     394#define VTGOBJHDR_MAGIC     "VTG Object Header v1.5\0"
    284395
    285396/** The name of the VTG data object header symbol in the object file. */
  • trunk/include/VBox/err.h

    r40878 r41117  
    16231623/** Bad VTG bit count value.  */
    16241624#define VERR_SUPDRV_VTG_BITS                        (-3705)
    1625 /** Bad VTG header.  */
    1626 #define VERR_SUPDRV_VTG_BAD_HDR                     (-3706)
    1627 /** Bad VTG header - pointer.  */
    1628 #define VERR_SUPDRV_VTG_BAD_HDR_PTR                 (-3707)
     1625/** Bad VTG header - misc.  */
     1626#define VERR_SUPDRV_VTG_BAD_HDR_MISC                (-3706)
     1627/** Bad VTG header - offset.  */
     1628#define VERR_SUPDRV_VTG_BAD_HDR_OFF                 (-3707)
     1629/** Bad VTG header - offset.  */
     1630#define VERR_SUPDRV_VTG_BAD_HDR_PTR                 (-3708)
    16291631/** Bad VTG header - to low value.  */
    1630 #define VERR_SUPDRV_VTG_BAD_HDR_TOO_FEW             (-3708)
     1632#define VERR_SUPDRV_VTG_BAD_HDR_TOO_FEW             (-3709)
    16311633/** Bad VTG header - to high value.  */
    1632 #define VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH            (-3709)
     1634#define VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH            (-3710)
    16331635/** Bad VTG header - size value is not a multiple of the structure size. */
    1634 #define VERR_SUPDRV_VTG_BAD_HDR_NOT_MULTIPLE        (-3710)
     1636#define VERR_SUPDRV_VTG_BAD_HDR_NOT_MULTIPLE        (-3711)
    16351637/** Bad VTG string table offset. */
    1636 #define VERR_SUPDRV_VTG_STRTAB_OFF                  (-3711)
     1638#define VERR_SUPDRV_VTG_STRTAB_OFF                  (-3712)
    16371639/** Bad VTG string. */
    1638 #define VERR_SUPDRV_VTG_BAD_STRING                  (-3712)
     1640#define VERR_SUPDRV_VTG_BAD_STRING                  (-3713)
    16391641/** VTG string is too long. */
    1640 #define VERR_SUPDRV_VTG_STRING_TOO_LONG             (-3713)
     1642#define VERR_SUPDRV_VTG_STRING_TOO_LONG             (-3714)
    16411643/** Bad VTG attribute value. */
    1642 #define VERR_SUPDRV_VTG_BAD_ATTR                    (-3714)
     1644#define VERR_SUPDRV_VTG_BAD_ATTR                    (-3715)
    16431645/** Bad VTG provider descriptor. */
    1644 #define VERR_SUPDRV_VTG_BAD_PROVIDER                (-3715)
     1646#define VERR_SUPDRV_VTG_BAD_PROVIDER                (-3716)
    16451647/** Bad VTG probe descriptor. */
    1646 #define VERR_SUPDRV_VTG_BAD_PROBE                   (-3716)
     1648#define VERR_SUPDRV_VTG_BAD_PROBE                   (-3717)
    16471649/** Bad VTG argument list descriptor. */
    1648 #define VERR_SUPDRV_VTG_BAD_ARGLIST                 (-3717)
     1650#define VERR_SUPDRV_VTG_BAD_ARGLIST                 (-3718)
    16491651/** Bad VTG probe enabled data. */
    1650 #define VERR_SUPDRV_VTG_BAD_PROBE_ENABLED           (-3718)
     1652#define VERR_SUPDRV_VTG_BAD_PROBE_ENABLED           (-3719)
    16511653/** Bad VTG probe location record. */
    1652 #define VERR_SUPDRV_VTG_BAD_PROBE_LOC               (-3719)
     1654#define VERR_SUPDRV_VTG_BAD_PROBE_LOC               (-3720)
    16531655/** The VTG object for the session or image has already been registered. */
    1654 #define VERR_SUPDRV_VTG_ALREADY_REGISTERED          (-3720)
     1656#define VERR_SUPDRV_VTG_ALREADY_REGISTERED          (-3721)
    16551657/** A driver may only register one VTG object per session. */
    1656 #define VERR_SUPDRV_VTG_ONLY_ONCE_PER_SESSION       (-3721)
     1658#define VERR_SUPDRV_VTG_ONLY_ONCE_PER_SESSION       (-3722)
    16571659/** A tracer has already been registered. */
    1658 #define VERR_SUPDRV_TRACER_ALREADY_REGISTERED       (-3722)
     1660#define VERR_SUPDRV_TRACER_ALREADY_REGISTERED       (-3723)
    16591661/** The session has no tracer associated with it. */
    1660 #define VERR_SUPDRV_TRACER_NOT_REGISTERED           (-3723)
     1662#define VERR_SUPDRV_TRACER_NOT_REGISTERED           (-3724)
    16611663/** The tracer has already been opened in this sesssion. */
    1662 #define VERR_SUPDRV_TRACER_ALREADY_OPENED           (-3724)
     1664#define VERR_SUPDRV_TRACER_ALREADY_OPENED           (-3725)
    16631665/** The tracer has not been opened. */
    1664 #define VERR_SUPDRV_TRACER_NOT_OPENED               (-3725)
     1666#define VERR_SUPDRV_TRACER_NOT_OPENED               (-3726)
    16651667/** There is no tracer present. */
    1666 #define VERR_SUPDRV_TRACER_NOT_PRESENT              (-3726)
     1668#define VERR_SUPDRV_TRACER_NOT_PRESENT              (-3727)
    16671669/** The tracer is unloading. */
    1668 #define VERR_SUPDRV_TRACER_UNLOADING                (-3727)
     1670#define VERR_SUPDRV_TRACER_UNLOADING                (-3728)
    16691671/** Another thread in the session is talking to the tracer.  */
    1670 #define VERR_SUPDRV_TRACER_SESSION_BUSY             (-3728)
     1672#define VERR_SUPDRV_TRACER_SESSION_BUSY             (-3729)
    16711673/** The tracer cannot open it self in the same session. */
    1672 #define VERR_SUPDRV_TRACER_CANNOT_OPEN_SELF         (-3729)
     1674#define VERR_SUPDRV_TRACER_CANNOT_OPEN_SELF         (-3730)
    16731675/** Bad argument flags. */
    1674 #define VERR_SUPDRV_TRACER_BAD_ARG_FLAGS            (-3730)
     1676#define VERR_SUPDRV_TRACER_BAD_ARG_FLAGS            (-3731)
     1677/** The session has reached the max number of (user mode) providers. */
     1678#define VERR_SUPDRV_TRACER_TOO_MANY_PROVIDERS       (-3732)
     1679/** The tracepoint provider object is too large. */
     1680#define VERR_SUPDRV_TRACER_TOO_LARGE                (-3733)
     1681/** The probe location array isn't adjacent to the probe enable array. */
     1682#define VERR_SUPDRV_TRACER_UMOD_NOT_ADJACENT        (-3734)
     1683/** The user mode tracepoint provider has too many probe locations and
     1684 * probes. */
     1685#define VERR_SUPDRV_TRACER_UMOD_TOO_MANY_PROBES     (-3735)
     1686/** The user mode tracepoint provider string table is too large. */
     1687#define VERR_SUPDRV_TRACER_UMOD_STRTAB_TOO_BIG      (-3736)
     1688/** The user mode tracepoint provider string table offset is bad. */
     1689#define VERR_SUPDRV_TRACER_UMOD_STRTAB_OFF_BAD      (-3737)
    16751690/** @} */
    16761691
  • trunk/include/VBox/sup.h

    r40983 r41117  
    9191    SUPPAGINGMODE_AMD64_GLOBAL_NX
    9292} SUPPAGINGMODE;
    93 
    94 
    95 /**
    96  * The CPU state.
    97  */
    98 typedef enum SUPGIPCPUSTATE
    99 {
    100     /** Invalid CPU state / unused CPU entry. */
    101     SUPGIPCPUSTATE_INVALID = 0,
    102     /** The CPU is not present. */
    103     SUPGIPCPUSTATE_ABSENT,
    104     /** The CPU is offline. */
    105     SUPGIPCPUSTATE_OFFLINE,
    106     /** The CPU is online. */
    107     SUPGIPCPUSTATE_ONLINE,
    108     /** Force 32-bit enum type. */
    109     SUPGIPCPUSTATE_32_BIT_HACK = 0x7fffffff
    110 } SUPGIPCPUSTATE;
    111 
    112 /**
    113  * Per CPU data.
    114  */
    115 typedef struct SUPGIPCPU
    116 {
    117     /** Update transaction number.
    118      * This number is incremented at the start and end of each update. It follows
    119      * thusly that odd numbers indicates update in progress, while even numbers
    120      * indicate stable data. Use this to make sure that the data items you fetch
    121      * are consistent. */
    122     volatile uint32_t   u32TransactionId;
    123     /** The interval in TSC ticks between two NanoTS updates.
    124      * This is the average interval over the last 2, 4 or 8 updates + a little slack.
    125      * The slack makes the time go a tiny tiny bit slower and extends the interval enough
    126      * to avoid ending up with too many 1ns increments. */
    127     volatile uint32_t   u32UpdateIntervalTSC;
    128     /** Current nanosecond timestamp. */
    129     volatile uint64_t   u64NanoTS;
    130     /** The TSC at the time of u64NanoTS. */
    131     volatile uint64_t   u64TSC;
    132     /** Current CPU Frequency. */
    133     volatile uint64_t   u64CpuHz;
    134     /** Number of errors during updating.
    135      * Typical errors are under/overflows. */
    136     volatile uint32_t   cErrors;
    137     /** Index of the head item in au32TSCHistory. */
    138     volatile uint32_t   iTSCHistoryHead;
    139     /** Array of recent TSC interval deltas.
    140      * The most recent item is at index iTSCHistoryHead.
    141      * This history is used to calculate u32UpdateIntervalTSC.
    142      */
    143     volatile uint32_t   au32TSCHistory[8];
    144     /** The interval between the last two NanoTS updates. (experiment for now) */
    145     volatile uint32_t   u32PrevUpdateIntervalNS;
    146 
    147     /** Reserved for future per processor data. */
    148     volatile uint32_t   au32Reserved[5+5];
    149 
    150     /** @todo Add topology/NUMA info. */
    151     /** The CPU state. */
    152     SUPGIPCPUSTATE volatile enmState;
    153     /** The host CPU ID of this CPU (the SUPGIPCPU is indexed by APIC ID). */
    154     RTCPUID                 idCpu;
    155     /** The CPU set index of this CPU. */
    156     int16_t                 iCpuSet;
    157     /** The APIC ID of this CPU. */
    158     uint16_t                idApic;
    159 } SUPGIPCPU;
    160 AssertCompileSize(RTCPUID, 4);
    161 AssertCompileSize(SUPGIPCPU, 128);
    162 AssertCompileMemberAlignment(SUPGIPCPU, u64NanoTS, 8);
    163 AssertCompileMemberAlignment(SUPGIPCPU, u64TSC, 8);
    164 
    165 /** Pointer to per cpu data.
    166  * @remark there is no const version of this typedef, see g_pSUPGlobalInfoPage for details. */
    167 typedef SUPGIPCPU *PSUPGIPCPU;
    168 
    169 
    170 
    171 /**
    172  * Global Information Page.
    173  *
    174  * This page contains useful information and can be mapped into any
    175  * process or VM. It can be accessed thru the g_pSUPGlobalInfoPage
    176  * pointer when a session is open.
    177  */
    178 typedef struct SUPGLOBALINFOPAGE
    179 {
    180     /** Magic (SUPGLOBALINFOPAGE_MAGIC). */
    181     uint32_t            u32Magic;
    182     /** The GIP version. */
    183     uint32_t            u32Version;
    184 
    185     /** The GIP update mode, see SUPGIPMODE. */
    186     uint32_t            u32Mode;
    187     /** The number of entries in the CPU table.
    188      * (This can work as RTMpGetArraySize().)  */
    189     uint16_t            cCpus;
    190     /** The size of the GIP in pages. */
    191     uint16_t            cPages;
    192     /** The update frequency of the of the NanoTS. */
    193     volatile uint32_t   u32UpdateHz;
    194     /** The update interval in nanoseconds. (10^9 / u32UpdateHz) */
    195     volatile uint32_t   u32UpdateIntervalNS;
    196     /** The timestamp of the last time we update the update frequency. */
    197     volatile uint64_t   u64NanoTSLastUpdateHz;
    198     /** The set of online CPUs. */
    199     RTCPUSET            OnlineCpuSet;
    200     /** The set of present CPUs. */
    201     RTCPUSET            PresentCpuSet;
    202     /** The set of possible CPUs. */
    203     RTCPUSET            PossibleCpuSet;
    204     /** The number of CPUs that are online. */
    205     volatile uint16_t   cOnlineCpus;
    206     /** The number of CPUs present in the system. */
    207     volatile uint16_t   cPresentCpus;
    208     /** The highest number of CPUs possible. */
    209     uint16_t            cPossibleCpus;
    210     /** The highest number of CPUs possible. */
    211     uint16_t            u16Padding0;
    212     /** The max CPU ID (RTMpGetMaxCpuId). */
    213     RTCPUID             idCpuMax;
    214 
    215     /** Padding / reserved space for future data. */
    216     uint32_t            au32Padding1[29];
    217 
    218     /** Table indexed by the CPU APIC ID to get the CPU table index. */
    219     uint16_t            aiCpuFromApicId[256];
    220     /** CPU set index to CPU table index. */
    221     uint16_t            aiCpuFromCpuSetIdx[RTCPUSET_MAX_CPUS];
    222 
    223     /** Array of per-cpu data.
    224      * This is index by ApicId via the aiCpuFromApicId table.
    225      *
    226      * The clock and frequency information is updated for all CPUs if u32Mode
    227      * is SUPGIPMODE_ASYNC_TSC, otherwise (SUPGIPMODE_SYNC_TSC) only the first
    228      * entry is updated. */
    229     SUPGIPCPU           aCPUs[1];
    230 } SUPGLOBALINFOPAGE;
    231 AssertCompileMemberAlignment(SUPGLOBALINFOPAGE, u64NanoTSLastUpdateHz, 8);
    232 #if defined(RT_ARCH_SPARC) || defined(RT_ARCH_SPARC64)
    233 AssertCompileMemberAlignment(SUPGLOBALINFOPAGE, aCPUs, 32);
    234 #else
    235 AssertCompileMemberAlignment(SUPGLOBALINFOPAGE, aCPUs, 256);
    236 #endif
    237 
    238 /** Pointer to the global info page.
    239  * @remark there is no const version of this typedef, see g_pSUPGlobalInfoPage for details. */
    240 typedef SUPGLOBALINFOPAGE *PSUPGLOBALINFOPAGE;
    241 
    242 
    243 /** The value of the SUPGLOBALINFOPAGE::u32Magic field. (Soryo Fuyumi) */
    244 #define SUPGLOBALINFOPAGE_MAGIC     0x19590106
    245 /** The GIP version.
    246  * Upper 16 bits is the major version. Major version is only changed with
    247  * incompatible changes in the GIP. */
    248 #define SUPGLOBALINFOPAGE_VERSION   0x00030000
    249 
    250 /**
    251  * SUPGLOBALINFOPAGE::u32Mode values.
    252  */
    253 typedef enum SUPGIPMODE
    254 {
    255     /** The usual invalid null entry. */
    256     SUPGIPMODE_INVALID = 0,
    257     /** The TSC of the cores and cpus in the system is in sync. */
    258     SUPGIPMODE_SYNC_TSC,
    259     /** Each core has it's own TSC. */
    260     SUPGIPMODE_ASYNC_TSC,
    261     /** The usual 32-bit hack. */
    262     SUPGIPMODE_32BIT_HACK = 0x7fffffff
    263 } SUPGIPMODE;
    264 
    265 /** Pointer to the Global Information Page.
    266  *
    267  * This pointer is valid as long as SUPLib has a open session. Anyone using
    268  * the page must treat this pointer as highly volatile and not trust it beyond
    269  * one transaction.
    270  *
    271  * @remark  The GIP page is read-only to everyone but the support driver and
    272  *          is actually mapped read only everywhere but in ring-0. However
    273  *          it is not marked 'const' as this might confuse compilers into
    274  *          thinking that values doesn't change even if members are marked
    275  *          as volatile. Thus, there is no PCSUPGLOBALINFOPAGE type.
    276  */
    277 #if defined(IN_SUP_R0) || defined(IN_SUP_R3) || defined(IN_SUP_RC)
    278 extern DECLEXPORT(PSUPGLOBALINFOPAGE)   g_pSUPGlobalInfoPage;
    279 
    280 #elif !defined(IN_RING0) || defined(RT_OS_WINDOWS) || defined(RT_OS_SOLARIS)
    281 extern DECLIMPORT(PSUPGLOBALINFOPAGE)   g_pSUPGlobalInfoPage;
    282 
    283 #else /* IN_RING0 && !RT_OS_WINDOWS */
    284 # if !defined(__GNUC__) || defined(RT_OS_DARWIN) || !defined(RT_ARCH_AMD64)
    285 #  define g_pSUPGlobalInfoPage          (&g_SUPGlobalInfoPage)
    286 # else
    287 #  define g_pSUPGlobalInfoPage          (SUPGetGIPHlp())
    288 /** Workaround for ELF+GCC problem on 64-bit hosts.
    289  * (GCC emits a mov with a R_X86_64_32 reloc, we need R_X86_64_64.) */
    290 DECLINLINE(PSUPGLOBALINFOPAGE) SUPGetGIPHlp(void)
    291 {
    292     PSUPGLOBALINFOPAGE pGIP;
    293     __asm__ __volatile__ ("movabs $g_SUPGlobalInfoPage,%0\n\t"
    294                           : "=a" (pGIP));
    295     return pGIP;
    296 }
    297 # endif
    298 /** The GIP.
    299  * We save a level of indirection by exporting the GIP instead of a variable
    300  * pointing to it. */
    301 extern DECLIMPORT(SUPGLOBALINFOPAGE)    g_SUPGlobalInfoPage;
    302 #endif
    303 
    304 /**
    305  * Gets the GIP pointer.
    306  *
    307  * @returns Pointer to the GIP or NULL.
    308  */
    309 SUPDECL(PSUPGLOBALINFOPAGE)             SUPGetGIP(void);
    310 
    311 #ifdef ___iprt_asm_amd64_x86_h
    312 /**
    313  * Gets the TSC frequency of the calling CPU.
    314  *
    315  * @returns TSC frequency, UINT64_MAX on failure.
    316  * @param   pGip        The GIP pointer.
    317  */
    318 DECLINLINE(uint64_t) SUPGetCpuHzFromGIP(PSUPGLOBALINFOPAGE pGip)
    319 {
    320     unsigned iCpu;
    321 
    322     if (RT_UNLIKELY(!pGip || pGip->u32Magic != SUPGLOBALINFOPAGE_MAGIC))
    323         return UINT64_MAX;
    324 
    325     if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC)
    326         iCpu = 0;
    327     else
    328     {
    329         iCpu = pGip->aiCpuFromApicId[ASMGetApicId()];
    330         if (iCpu >= pGip->cCpus)
    331             return UINT64_MAX;
    332     }
    333 
    334     return pGip->aCPUs[iCpu].u64CpuHz;
    335 }
    336 #endif
    337 
    338 /**
    339  * Request for generic VMMR0Entry calls.
    340  */
    341 typedef struct SUPVMMR0REQHDR
    342 {
    343     /** The magic. (SUPVMMR0REQHDR_MAGIC) */
    344     uint32_t    u32Magic;
    345     /** The size of the request. */
    346     uint32_t    cbReq;
    347 } SUPVMMR0REQHDR;
    348 /** Pointer to a ring-0 request header. */
    349 typedef SUPVMMR0REQHDR *PSUPVMMR0REQHDR;
    350 /** the SUPVMMR0REQHDR::u32Magic value (Ethan Iverson - The Bad Plus). */
    351 #define SUPVMMR0REQHDR_MAGIC        UINT32_C(0x19730211)
    352 
    353 
    354 /** For the fast ioctl path.
    355  * @{
    356  */
    357 /** @see VMMR0_DO_RAW_RUN. */
    358 #define SUP_VMMR0_DO_RAW_RUN    0
    359 /** @see VMMR0_DO_HWACC_RUN. */
    360 #define SUP_VMMR0_DO_HWACC_RUN  1
    361 /** @see VMMR0_DO_NOP */
    362 #define SUP_VMMR0_DO_NOP        2
    363 /** @} */
    364 
    365 /** SUPR3QueryVTCaps capability flags
    366  * @{
    367  */
    368 #define SUPVTCAPS_AMD_V             RT_BIT(0)
    369 #define SUPVTCAPS_VT_X              RT_BIT(1)
    370 #define SUPVTCAPS_NESTED_PAGING     RT_BIT(2)
    371 /** @} */
    372 
    373 /**
    374  * Request for generic FNSUPR0SERVICEREQHANDLER calls.
    375  */
    376 typedef struct SUPR0SERVICEREQHDR
    377 {
    378     /** The magic. (SUPR0SERVICEREQHDR_MAGIC) */
    379     uint32_t    u32Magic;
    380     /** The size of the request. */
    381     uint32_t    cbReq;
    382 } SUPR0SERVICEREQHDR;
    383 /** Pointer to a ring-0 service request header. */
    384 typedef SUPR0SERVICEREQHDR *PSUPR0SERVICEREQHDR;
    385 /** the SUPVMMR0REQHDR::u32Magic value (Esbjoern Svensson - E.S.P.).  */
    386 #define SUPR0SERVICEREQHDR_MAGIC    UINT32_C(0x19640416)
    387 
    388 
    389 /** Event semaphore handle. Ring-0 / ring-3. */
    390 typedef R0PTRTYPE(struct SUPSEMEVENTHANDLE *) SUPSEMEVENT;
    391 /** Pointer to an event semaphore handle. */
    392 typedef SUPSEMEVENT *PSUPSEMEVENT;
    393 /** Nil event semaphore handle. */
    394 #define NIL_SUPSEMEVENT         ((SUPSEMEVENT)0)
    395 
    396 /**
    397  * Creates a single release event semaphore.
    398  *
    399  * @returns VBox status code.
    400  * @param   pSession        The session handle of the caller.
    401  * @param   phEvent         Where to return the handle to the event semaphore.
    402  */
    403 SUPDECL(int) SUPSemEventCreate(PSUPDRVSESSION pSession, PSUPSEMEVENT phEvent);
    404 
    405 /**
    406  * Closes a single release event semaphore handle.
    407  *
    408  * @returns VBox status code.
    409  * @retval  VINF_OBJECT_DESTROYED if the semaphore was destroyed.
    410  * @retval  VINF_SUCCESS if the handle was successfully closed but the semaphore
    411  *          object remained alive because of other references.
    412  *
    413  * @param   pSession            The session handle of the caller.
    414  * @param   hEvent              The handle. Nil is quietly ignored.
    415  */
    416 SUPDECL(int) SUPSemEventClose(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent);
    417 
    418 /**
    419  * Signals a single release event semaphore.
    420  *
    421  * @returns VBox status code.
    422  * @param   pSession            The session handle of the caller.
    423  * @param   hEvent              The semaphore handle.
    424  */
    425 SUPDECL(int) SUPSemEventSignal(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent);
    426 
    427 #ifdef IN_RING0
    428 /**
    429  * Waits on a single release event semaphore, not interruptible.
    430  *
    431  * @returns VBox status code.
    432  * @param   pSession            The session handle of the caller.
    433  * @param   hEvent              The semaphore handle.
    434  * @param   cMillies            The number of milliseconds to wait.
    435  * @remarks Not available in ring-3.
    436  */
    437 SUPDECL(int) SUPSemEventWait(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies);
    438 #endif
    439 
    440 /**
    441  * Waits on a single release event semaphore, interruptible.
    442  *
    443  * @returns VBox status code.
    444  * @param   pSession            The session handle of the caller.
    445  * @param   hEvent              The semaphore handle.
    446  * @param   cMillies            The number of milliseconds to wait.
    447  */
    448 SUPDECL(int) SUPSemEventWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies);
    449 
    450 /**
    451  * Waits on a single release event semaphore, interruptible.
    452  *
    453  * @returns VBox status code.
    454  * @param   pSession            The session handle of the caller.
    455  * @param   hEvent              The semaphore handle.
    456  * @param   uNsTimeout          The deadline given on the RTTimeNanoTS() clock.
    457  */
    458 SUPDECL(int) SUPSemEventWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t uNsTimeout);
    459 
    460 /**
    461  * Waits on a single release event semaphore, interruptible.
    462  *
    463  * @returns VBox status code.
    464  * @param   pSession            The session handle of the caller.
    465  * @param   hEvent              The semaphore handle.
    466  * @param   cNsTimeout          The number of nanoseconds to wait.
    467  */
    468 SUPDECL(int) SUPSemEventWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t cNsTimeout);
    469 
    470 /**
    471  * Gets the best timeout resolution that SUPSemEventWaitNsAbsIntr and
    472  * SUPSemEventWaitNsAbsIntr can do.
    473  *
    474  * @returns The resolution in nanoseconds.
    475  * @param   pSession            The session handle of the caller.
    476  */
    477 SUPDECL(uint32_t) SUPSemEventGetResolution(PSUPDRVSESSION pSession);
    478 
    479 
    480 /** Multiple release event semaphore handle. Ring-0 / ring-3. */
    481 typedef R0PTRTYPE(struct SUPSEMEVENTMULTIHANDLE *)  SUPSEMEVENTMULTI;
    482 /** Pointer to an multiple release event semaphore handle. */
    483 typedef SUPSEMEVENTMULTI                           *PSUPSEMEVENTMULTI;
    484 /** Nil multiple release event semaphore handle. */
    485 #define NIL_SUPSEMEVENTMULTI                        ((SUPSEMEVENTMULTI)0)
    486 
    487 /**
    488  * Creates a multiple release event semaphore.
    489  *
    490  * @returns VBox status code.
    491  * @param   pSession        The session handle of the caller.
    492  * @param   phEventMulti    Where to return the handle to the event semaphore.
    493  */
    494 SUPDECL(int) SUPSemEventMultiCreate(PSUPDRVSESSION pSession, PSUPSEMEVENTMULTI phEventMulti);
    495 
    496 /**
    497  * Closes a multiple release event semaphore handle.
    498  *
    499  * @returns VBox status code.
    500  * @retval  VINF_OBJECT_DESTROYED if the semaphore was destroyed.
    501  * @retval  VINF_SUCCESS if the handle was successfully closed but the semaphore
    502  *          object remained alive because of other references.
    503  *
    504  * @param   pSession            The session handle of the caller.
    505  * @param   hEventMulti         The handle. Nil is quietly ignored.
    506  */
    507 SUPDECL(int) SUPSemEventMultiClose(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti);
    508 
    509 /**
    510  * Signals a multiple release event semaphore.
    511  *
    512  * @returns VBox status code.
    513  * @param   pSession            The session handle of the caller.
    514  * @param   hEventMulti         The semaphore handle.
    515  */
    516 SUPDECL(int) SUPSemEventMultiSignal(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti);
    517 
    518 /**
    519  * Resets a multiple release event semaphore.
    520  *
    521  * @returns VBox status code.
    522  * @param   pSession            The session handle of the caller.
    523  * @param   hEventMulti         The semaphore handle.
    524  */
    525 SUPDECL(int) SUPSemEventMultiReset(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti);
    526 
    527 #ifdef IN_RING0
    528 /**
    529  * Waits on a multiple release event semaphore, not interruptible.
    530  *
    531  * @returns VBox status code.
    532  * @param   pSession            The session handle of the caller.
    533  * @param   hEventMulti         The semaphore handle.
    534  * @param   cMillies            The number of milliseconds to wait.
    535  * @remarks Not available in ring-3.
    536  */
    537 SUPDECL(int) SUPSemEventMultiWait(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies);
    538 #endif
    539 
    540 /**
    541  * Waits on a multiple release event semaphore, interruptible.
    542  *
    543  * @returns VBox status code.
    544  * @param   pSession            The session handle of the caller.
    545  * @param   hEventMulti         The semaphore handle.
    546  * @param   cMillies            The number of milliseconds to wait.
    547  */
    548 SUPDECL(int) SUPSemEventMultiWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies);
    549 
    550 /**
    551  * Waits on a multiple release event semaphore, interruptible.
    552  *
    553  * @returns VBox status code.
    554  * @param   pSession            The session handle of the caller.
    555  * @param   hEventMulti         The semaphore handle.
    556  * @param   uNsTimeout          The deadline given on the RTTimeNanoTS() clock.
    557  */
    558 SUPDECL(int) SUPSemEventMultiWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t uNsTimeout);
    559 
    560 /**
    561  * Waits on a multiple release event semaphore, interruptible.
    562  *
    563  * @returns VBox status code.
    564  * @param   pSession            The session handle of the caller.
    565  * @param   hEventMulti         The semaphore handle.
    566  * @param   cNsTimeout          The number of nanoseconds to wait.
    567  */
    568 SUPDECL(int) SUPSemEventMultiWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t cNsTimeout);
    569 
    570 /**
    571  * Gets the best timeout resolution that SUPSemEventMultiWaitNsAbsIntr and
    572  * SUPSemEventMultiWaitNsRelIntr can do.
    573  *
    574  * @returns The resolution in nanoseconds.
    575  * @param   pSession            The session handle of the caller.
    576  */
    577 SUPDECL(uint32_t) SUPSemEventMultiGetResolution(PSUPDRVSESSION pSession);
    578 
    579 
    580 #ifdef IN_RING3
    581 
    582 /** @defgroup   grp_sup_r3     SUP Host Context Ring-3 API
    583  * @ingroup grp_sup
    584  * @{
    585  */
    586 
    587 /**
    588  * Installs the support library.
    589  *
    590  * @returns VBox status code.
    591  */
    592 SUPR3DECL(int) SUPR3Install(void);
    593 
    594 /**
    595  * Uninstalls the support library.
    596  *
    597  * @returns VBox status code.
    598  */
    599 SUPR3DECL(int) SUPR3Uninstall(void);
    600 
    601 /**
    602  * Trusted main entry point.
    603  *
    604  * This is exported as "TrustedMain" by the dynamic libraries which contains the
    605  * "real" application binary for which the hardened stub is built.  The entry
    606  * point is invoked upon successful initialization of the support library and
    607  * runtime.
    608  *
    609  * @returns main kind of exit code.
    610  * @param   argc            The argument count.
    611  * @param   argv            The argument vector.
    612  * @param   envp            The environment vector.
    613  */
    614 typedef DECLCALLBACK(int) FNSUPTRUSTEDMAIN(int argc, char **argv, char **envp);
    615 /** Pointer to FNSUPTRUSTEDMAIN(). */
    616 typedef FNSUPTRUSTEDMAIN *PFNSUPTRUSTEDMAIN;
    617 
    618 /** Which operation failed. */
    619 typedef enum SUPINITOP
    620 {
    621     /** Invalid. */
    622     kSupInitOp_Invalid = 0,
    623     /** Installation integrity error. */
    624     kSupInitOp_Integrity,
    625     /** Setuid related. */
    626     kSupInitOp_RootCheck,
    627     /** Driver related. */
    628     kSupInitOp_Driver,
    629     /** IPRT init related. */
    630     kSupInitOp_IPRT,
    631     /** Place holder. */
    632     kSupInitOp_End
    633 } SUPINITOP;
    634 
    635 /**
    636  * Trusted error entry point, optional.
    637  *
    638  * This is exported as "TrustedError" by the dynamic libraries which contains
    639  * the "real" application binary for which the hardened stub is built.
    640  *
    641  * @param   pszWhere        Where the error occurred (function name).
    642  * @param   enmWhat         Which operation went wrong.
    643  * @param   rc              The status code.
    644  * @param   pszMsgFmt       Error message format string.
    645  * @param   va              The message format arguments.
    646  */
    647 typedef DECLCALLBACK(void) FNSUPTRUSTEDERROR(const char *pszWhere, SUPINITOP enmWhat, int rc, const char *pszMsgFmt, va_list va);
    648 /** Pointer to FNSUPTRUSTEDERROR. */
    649 typedef FNSUPTRUSTEDERROR *PFNSUPTRUSTEDERROR;
    650 
    651 /**
    652  * Secure main.
    653  *
    654  * This is used for the set-user-ID-on-execute binaries on unixy systems
    655  * and when using the open-vboxdrv-via-root-service setup on Windows.
    656  *
    657  * This function will perform the integrity checks of the VirtualBox
    658  * installation, open the support driver, open the root service (later),
    659  * and load the DLL corresponding to \a pszProgName and execute its main
    660  * function.
    661  *
    662  * @returns Return code appropriate for main().
    663  *
    664  * @param   pszProgName     The program name. This will be used to figure out which
    665  *                          DLL/SO/DYLIB to load and execute.
    666  * @param   fFlags          Flags.
    667  * @param   argc            The argument count.
    668  * @param   argv            The argument vector.
    669  * @param   envp            The environment vector.
    670  */
    671 DECLHIDDEN(int) SUPR3HardenedMain(const char *pszProgName, uint32_t fFlags, int argc, char **argv, char **envp);
    672 
    673 /** @name SUPR3SecureMain flags.
    674  * @{ */
    675 /** Don't open the device. (Intended for VirtualBox without -startvm.) */
    676 #define SUPSECMAIN_FLAGS_DONT_OPEN_DEV      RT_BIT_32(0)
    677 /** @} */
    678 
    679 /**
    680  * Initializes the support library.
    681  * Each successful call to SUPR3Init() must be countered by a
    682  * call to SUPR3Term(false).
    683  *
    684  * @returns VBox status code.
    685  * @param   ppSession       Where to store the session handle. Defaults to NULL.
    686  */
    687 SUPR3DECL(int) SUPR3Init(PSUPDRVSESSION *ppSession);
    688 
    689 /**
    690  * Terminates the support library.
    691  *
    692  * @returns VBox status code.
    693  * @param   fForced     Forced termination. This means to ignore the
    694  *                      init call count and just terminated.
    695  */
    696 #ifdef __cplusplus
    697 SUPR3DECL(int) SUPR3Term(bool fForced = false);
    698 #else
    699 SUPR3DECL(int) SUPR3Term(int fForced);
    700 #endif
    701 
    702 /**
    703  * Sets the ring-0 VM handle for use with fast IOCtls.
    704  *
    705  * @returns VBox status code.
    706  * @param   pVMR0       The ring-0 VM handle.
    707  *                      NIL_RTR0PTR can be used to unset the handle when the
    708  *                      VM is about to be destroyed.
    709  */
    710 SUPR3DECL(int) SUPR3SetVMForFastIOCtl(PVMR0 pVMR0);
    711 
    712 /**
    713  * Calls the HC R0 VMM entry point.
    714  * See VMMR0Entry() for more details.
    715  *
    716  * @returns error code specific to uFunction.
    717  * @param   pVMR0       Pointer to the Ring-0 (Host Context) mapping of the VM structure.
    718  * @param   idCpu       The virtual CPU ID.
    719  * @param   uOperation  Operation to execute.
    720  * @param   pvArg       Argument.
    721  */
    722 SUPR3DECL(int) SUPR3CallVMMR0(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, void *pvArg);
    723 
    724 /**
    725  * Variant of SUPR3CallVMMR0, except that this takes the fast ioclt path
    726  * regardsless of compile-time defaults.
    727  *
    728  * @returns VBox status code.
    729  * @param   pVMR0       The ring-0 VM handle.
    730  * @param   uOperation  The operation; only the SUP_VMMR0_DO_* ones are valid.
    731  * @param   idCpu       The virtual CPU ID.
    732  */
    733 SUPR3DECL(int) SUPR3CallVMMR0Fast(PVMR0 pVMR0, unsigned uOperation, VMCPUID idCpu);
    734 
    735 /**
    736  * Calls the HC R0 VMM entry point, in a safer but slower manner than
    737  * SUPR3CallVMMR0. When entering using this call the R0 components can call
    738  * into the host kernel (i.e. use the SUPR0 and RT APIs).
    739  *
    740  * See VMMR0Entry() for more details.
    741  *
    742  * @returns error code specific to uFunction.
    743  * @param   pVMR0       Pointer to the Ring-0 (Host Context) mapping of the VM structure.
    744  * @param   idCpu       The virtual CPU ID.
    745  * @param   uOperation  Operation to execute.
    746  * @param   u64Arg      Constant argument.
    747  * @param   pReqHdr     Pointer to a request header. Optional.
    748  *                      This will be copied in and out of kernel space. There currently is a size
    749  *                      limit on this, just below 4KB.
    750  */
    751 SUPR3DECL(int) SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr);
    752 
    753 /**
    754  * Calls a ring-0 service.
    755  *
    756  * The operation and the request packet is specific to the service.
    757  *
    758  * @returns error code specific to uFunction.
    759  * @param   pszService  The service name.
    760  * @param   cchService  The length of the service name.
    761  * @param   uReq        The request number.
    762  * @param   u64Arg      Constant argument.
    763  * @param   pReqHdr     Pointer to a request header. Optional.
    764  *                      This will be copied in and out of kernel space. There currently is a size
    765  *                      limit on this, just below 4KB.
    766  */
    767 SUPR3DECL(int) SUPR3CallR0Service(const char *pszService, size_t cchService, uint32_t uOperation, uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr);
    768 
    769 /** Which logger. */
    770 typedef enum SUPLOGGER
    771 {
    772     SUPLOGGER_DEBUG = 1,
    773     SUPLOGGER_RELEASE
    774 } SUPLOGGER;
    775 
    776 /**
    777  * Changes the settings of the specified ring-0 logger.
    778  *
    779  * @returns VBox status code.
    780  * @param   enmWhich    Which logger.
    781  * @param   pszFlags    The flags settings.
    782  * @param   pszGroups   The groups settings.
    783  * @param   pszDest     The destination specificier.
    784  */
    785 SUPR3DECL(int) SUPR3LoggerSettings(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest);
    786 
    787 /**
    788  * Creates a ring-0 logger instance.
    789  *
    790  * @returns VBox status code.
    791  * @param   enmWhich    Which logger to create.
    792  * @param   pszFlags    The flags settings.
    793  * @param   pszGroups   The groups settings.
    794  * @param   pszDest     The destination specificier.
    795  */
    796 SUPR3DECL(int) SUPR3LoggerCreate(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest);
    797 
    798 /**
    799  * Destroys a ring-0 logger instance.
    800  *
    801  * @returns VBox status code.
    802  * @param   enmWhich    Which logger.
    803  */
    804 SUPR3DECL(int) SUPR3LoggerDestroy(SUPLOGGER enmWhich);
    805 
    806 /**
    807  * Queries the paging mode of the host OS.
    808  *
    809  * @returns The paging mode.
    810  */
    811 SUPR3DECL(SUPPAGINGMODE) SUPR3GetPagingMode(void);
    812 
    813 /**
    814  * Allocate zero-filled pages.
    815  *
    816  * Use this to allocate a number of pages suitable for seeding / locking.
    817  * Call SUPR3PageFree() to free the pages once done with them.
    818  *
    819  * @returns VBox status.
    820  * @param   cPages          Number of pages to allocate.
    821  * @param   ppvPages        Where to store the base pointer to the allocated pages.
    822  */
    823 SUPR3DECL(int) SUPR3PageAlloc(size_t cPages, void **ppvPages);
    824 
    825 /**
    826  * Frees pages allocated with SUPR3PageAlloc().
    827  *
    828  * @returns VBox status.
    829  * @param   pvPages         Pointer returned by SUPR3PageAlloc().
    830  * @param   cPages          Number of pages that was allocated.
    831  */
    832 SUPR3DECL(int) SUPR3PageFree(void *pvPages, size_t cPages);
    833 
    834 /**
    835  * Allocate non-zeroed, locked, pages with user and, optionally, kernel
    836  * mappings.
    837  *
    838  * Use SUPR3PageFreeEx() to free memory allocated with this function.
    839  *
    840  * @returns VBox status code.
    841  * @param   cPages          The number of pages to allocate.
    842  * @param   fFlags          Flags, reserved. Must be zero.
    843  * @param   ppvPages        Where to store the address of the user mapping.
    844  * @param   pR0Ptr          Where to store the address of the kernel mapping.
    845  *                          NULL if no kernel mapping is desired.
    846  * @param   paPages         Where to store the physical addresses of each page.
    847  *                          Optional.
    848  */
    849 SUPR3DECL(int) SUPR3PageAllocEx(size_t cPages, uint32_t fFlags, void **ppvPages, PRTR0PTR pR0Ptr, PSUPPAGE paPages);
    850 
    851 /**
    852  * Maps a portion of a ring-3 only allocation into kernel space.
    853  *
    854  * @returns VBox status code.
    855  *
    856  * @param   pvR3            The address SUPR3PageAllocEx return.
    857  * @param   off             Offset to start mapping at. Must be page aligned.
    858  * @param   cb              Number of bytes to map. Must be page aligned.
    859  * @param   fFlags          Flags, must be zero.
    860  * @param   pR0Ptr          Where to store the address on success.
    861  *
    862  */
    863 SUPR3DECL(int) SUPR3PageMapKernel(void *pvR3, uint32_t off, uint32_t cb, uint32_t fFlags, PRTR0PTR pR0Ptr);
    864 
    865 /**
    866  * Changes the protection of
    867  *
    868  * @returns VBox status code.
    869  * @retval  VERR_NOT_SUPPORTED if the OS doesn't allow us to change page level
    870  *          protection. See also RTR0MemObjProtect.
    871  *
    872  * @param   pvR3            The ring-3 address SUPR3PageAllocEx returned.
    873  * @param   R0Ptr           The ring-0 address SUPR3PageAllocEx returned if it
    874  *                          is desired that the corresponding ring-0 page
    875  *                          mappings should change protection as well. Pass
    876  *                          NIL_RTR0PTR if the ring-0 pages should remain
    877  *                          unaffected.
    878  * @param   off             Offset to start at which to start chagning the page
    879  *                          level protection. Must be page aligned.
    880  * @param   cb              Number of bytes to change. Must be page aligned.
    881  * @param   fProt           The new page level protection, either a combination
    882  *                          of RTMEM_PROT_READ, RTMEM_PROT_WRITE and
    883  *                          RTMEM_PROT_EXEC, or just RTMEM_PROT_NONE.
    884  */
    885 SUPR3DECL(int) SUPR3PageProtect(void *pvR3, RTR0PTR R0Ptr, uint32_t off, uint32_t cb, uint32_t fProt);
    886 
    887 /**
    888  * Free pages allocated by SUPR3PageAllocEx.
    889  *
    890  * @returns VBox status code.
    891  * @param   pvPages         The address of the user mapping.
    892  * @param   cPages          The number of pages.
    893  */
    894 SUPR3DECL(int) SUPR3PageFreeEx(void *pvPages, size_t cPages);
    895 
    896 /**
    897  * Allocated memory with page aligned memory with a contiguous and locked physical
    898  * memory backing below 4GB.
    899  *
    900  * @returns Pointer to the allocated memory (virtual address).
    901  *          *pHCPhys is set to the physical address of the memory.
    902  *          If ppvR0 isn't NULL, *ppvR0 is set to the ring-0 mapping.
    903  *          The returned memory must be freed using SUPR3ContFree().
    904  * @returns NULL on failure.
    905  * @param   cPages      Number of pages to allocate.
    906  * @param   pR0Ptr      Where to store the ring-0 mapping of the allocation. (optional)
    907  * @param   pHCPhys     Where to store the physical address of the memory block.
    908  *
    909  * @remark  This 2nd version of this API exists because we're not able to map the
    910  *          ring-3 mapping executable on WIN64. This is a serious problem in regard to
    911  *          the world switchers.
    912  */
    913 SUPR3DECL(void *) SUPR3ContAlloc(size_t cPages, PRTR0PTR pR0Ptr, PRTHCPHYS pHCPhys);
    914 
    915 /**
    916  * Frees memory allocated with SUPR3ContAlloc().
    917  *
    918  * @returns VBox status code.
    919  * @param   pv          Pointer to the memory block which should be freed.
    920  * @param   cPages      Number of pages to be freed.
    921  */
    922 SUPR3DECL(int) SUPR3ContFree(void *pv, size_t cPages);
    923 
    924 /**
    925  * Allocated non contiguous physical memory below 4GB.
    926  *
    927  * The memory isn't zeroed.
    928  *
    929  * @returns VBox status code.
    930  * @returns NULL on failure.
    931  * @param   cPages      Number of pages to allocate.
    932  * @param   ppvPages    Where to store the pointer to the allocated memory.
    933  *                      The pointer stored here on success must be passed to
    934  *                      SUPR3LowFree when the memory should be released.
    935  * @param   ppvPagesR0  Where to store the ring-0 pointer to the allocated memory. optional.
    936  * @param   paPages     Where to store the physical addresses of the individual pages.
    937  */
    938 SUPR3DECL(int) SUPR3LowAlloc(size_t cPages, void **ppvPages, PRTR0PTR ppvPagesR0, PSUPPAGE paPages);
    939 
    940 /**
    941  * Frees memory allocated with SUPR3LowAlloc().
    942  *
    943  * @returns VBox status code.
    944  * @param   pv          Pointer to the memory block which should be freed.
    945  * @param   cPages      Number of pages that was allocated.
    946  */
    947 SUPR3DECL(int) SUPR3LowFree(void *pv, size_t cPages);
    948 
    949 /**
    950  * Load a module into R0 HC.
    951  *
    952  * This will verify the file integrity in a similar manner as
    953  * SUPR3HardenedVerifyFile before loading it.
    954  *
    955  * @returns VBox status code.
    956  * @param   pszFilename     The path to the image file.
    957  * @param   pszModule       The module name. Max 32 bytes.
    958  * @param   ppvImageBase    Where to store the image address.
    959  * @param   pErrInfo        Where to return extended error information.
    960  *                          Optional.
    961  */
    962 SUPR3DECL(int) SUPR3LoadModule(const char *pszFilename, const char *pszModule, void **ppvImageBase, PRTERRINFO pErrInfo);
    963 
    964 /**
    965  * Load a module into R0 HC.
    966  *
    967  * This will verify the file integrity in a similar manner as
    968  * SUPR3HardenedVerifyFile before loading it.
    969  *
    970  * @returns VBox status code.
    971  * @param   pszFilename         The path to the image file.
    972  * @param   pszModule           The module name. Max 32 bytes.
    973  * @param   pszSrvReqHandler    The name of the service request handler entry
    974  *                              point. See FNSUPR0SERVICEREQHANDLER.
    975  * @param   ppvImageBase        Where to store the image address.
    976  */
    977 SUPR3DECL(int) SUPR3LoadServiceModule(const char *pszFilename, const char *pszModule,
    978                                       const char *pszSrvReqHandler, void **ppvImageBase);
    979 
    980 /**
    981  * Frees a R0 HC module.
    982  *
    983  * @returns VBox status code.
    984  * @param   pszModule       The module to free.
    985  * @remark  This will not actually 'free' the module, there are of course usage counting.
    986  */
    987 SUPR3DECL(int) SUPR3FreeModule(void *pvImageBase);
    988 
    989 /**
    990  * Get the address of a symbol in a ring-0 module.
    991  *
    992  * @returns VBox status code.
    993  * @param   pszModule       The module name.
    994  * @param   pszSymbol       Symbol name. If it's value is less than 64k it's treated like a
    995  *                          ordinal value rather than a string pointer.
    996  * @param   ppvValue        Where to store the symbol value.
    997  */
    998 SUPR3DECL(int) SUPR3GetSymbolR0(void *pvImageBase, const char *pszSymbol, void **ppvValue);
    999 
    1000 /**
    1001  * Load R0 HC VMM code.
    1002  *
    1003  * @returns VBox status code.
    1004  * @deprecated  Use SUPR3LoadModule(pszFilename, "VMMR0.r0", &pvImageBase)
    1005  */
    1006 SUPR3DECL(int) SUPR3LoadVMM(const char *pszFilename);
    1007 
    1008 /**
    1009  * Unloads R0 HC VMM code.
    1010  *
    1011  * @returns VBox status code.
    1012  * @deprecated  Use SUPR3FreeModule().
    1013  */
    1014 SUPR3DECL(int) SUPR3UnloadVMM(void);
    1015 
    1016 /**
    1017  * Get the physical address of the GIP.
    1018  *
    1019  * @returns VBox status code.
    1020  * @param   pHCPhys     Where to store the physical address of the GIP.
    1021  */
    1022 SUPR3DECL(int) SUPR3GipGetPhys(PRTHCPHYS pHCPhys);
    1023 
    1024 /**
    1025  * Verifies the integrity of a file, and optionally opens it.
    1026  *
    1027  * The integrity check is for whether the file is suitable for loading into
    1028  * the hypervisor or VM process. The integrity check may include verifying
    1029  * the authenticode/elfsign/whatever signature of the file, which can take
    1030  * a little while.
    1031  *
    1032  * @returns VBox status code. On failure it will have printed a LogRel message.
    1033  *
    1034  * @param   pszFilename     The file.
    1035  * @param   pszWhat         For the LogRel on failure.
    1036  * @param   phFile          Where to store the handle to the opened file. This is optional, pass NULL
    1037  *                          if the file should not be opened.
    1038  * @deprecated Write a new one.
    1039  */
    1040 SUPR3DECL(int) SUPR3HardenedVerifyFile(const char *pszFilename, const char *pszWhat, PRTFILE phFile);
    1041 
    1042 /**
    1043  * Verifies the integrity of a the current process, including the image
    1044  * location and that the invocation was absolute.
    1045  *
    1046  * This must currently be called after initializing the runtime.  The intended
    1047  * audience is set-uid-to-root applications, root services and similar.
    1048  *
    1049  * @returns VBox status code.  On failure
    1050  *          message.
    1051  * @param   pszArgv0        The first argument to main().
    1052  * @param   fInternal       Set this to @c true if this is an internal
    1053  *                          VirtualBox application.  Otherwise pass @c false.
    1054  * @param   pErrInfo        Where to return extended error information.
    1055  */
    1056 SUPR3DECL(int) SUPR3HardenedVerifySelf(const char *pszArgv0, bool fInternal, PRTERRINFO pErrInfo);
    1057 
    1058 /**
    1059  * Verifies the integrity of an installation directory.
    1060  *
    1061  * The integrity check verifies that the directory cannot be tampered with by
    1062  * normal users on the system.  On Unix this translates to root ownership and
    1063  * no symbolic linking.
    1064  *
    1065  * @returns VBox status code. On failure a message will be stored in @a pszErr.
    1066  *
    1067  * @param   pszDirPath      The directory path.
    1068  * @param   fRecursive      Whether the check should be recursive or
    1069  *                          not.  When set, all sub-directores will be checked,
    1070  *                          including files (@a fCheckFiles is ignored).
    1071  * @param   fCheckFiles     Whether to apply the same basic integrity check to
    1072  *                          the files in the directory as the directory itself.
    1073  * @param   pErrInfo        Where to return extended error information.
    1074  *                          Optional.
    1075  */
    1076 SUPR3DECL(int) SUPR3HardenedVerifyDir(const char *pszDirPath, bool fRecursive, bool fCheckFiles, PRTERRINFO pErrInfo);
    1077 
    1078 /**
    1079  * Verifies the integrity of a plug-in module.
    1080  *
    1081  * This is similar to SUPR3HardenedLdrLoad, except it does not load the module
    1082  * and that the module does not have to be shipped with VirtualBox.
    1083  *
    1084  * @returns VBox status code. On failure a message will be stored in @a pszErr.
    1085  *
    1086  * @param   pszFilename     The filename of the plug-in module (nothing can be
    1087  *                          omitted here).
    1088  * @param   pErrInfo        Where to return extended error information.
    1089  *                          Optional.
    1090  */
    1091 SUPR3DECL(int) SUPR3HardenedVerifyPlugIn(const char *pszFilename, PRTERRINFO pErrInfo);
    1092 
    1093 /**
    1094  * Same as RTLdrLoad() but will verify the files it loads (hardened builds).
    1095  *
    1096  * Will add dll suffix if missing and try load the file.
    1097  *
    1098  * @returns iprt status code.
    1099  * @param   pszFilename     Image filename. This must have a path.
    1100  * @param   phLdrMod        Where to store the handle to the loaded module.
    1101  * @param   fFlags          See RTLDRLOAD_FLAGS_XXX.
    1102  * @param   pErrInfo        Where to return extended error information.
    1103  *                          Optional.
    1104  */
    1105 SUPR3DECL(int) SUPR3HardenedLdrLoad(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo);
    1106 
    1107 /**
    1108  * Same as RTLdrLoadAppPriv() but it will verify the files it loads (hardened
    1109  * builds).
    1110  *
    1111  * Will add dll suffix to the file if missing, then look for it in the
    1112  * architecture dependent application directory.
    1113  *
    1114  * @returns iprt status code.
    1115  * @param   pszFilename     Image filename.
    1116  * @param   phLdrMod        Where to store the handle to the loaded module.
    1117  * @param   fFlags          See RTLDRLOAD_FLAGS_XXX.
    1118  * @param   pErrInfo        Where to return extended error information.
    1119  *                          Optional.
    1120  */
    1121 SUPR3DECL(int) SUPR3HardenedLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo);
    1122 
    1123 /**
    1124  * Same as RTLdrLoad() but will verify the files it loads (hardened builds).
    1125  *
    1126  * This differs from SUPR3HardenedLdrLoad() in that it can load modules from
    1127  * extension packs and anything else safely installed on the system, provided
    1128  * they pass the hardening tests.
    1129  *
    1130  * @returns iprt status code.
    1131  * @param   pszFilename     The full path to the module, with extension.
    1132  * @param   phLdrMod        Where to store the handle to the loaded module.
    1133  * @param   pErrInfo        Where to return extended error information.
    1134  *                          Optional.
    1135  */
    1136 SUPR3DECL(int) SUPR3HardenedLdrLoadPlugIn(const char *pszFilename, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo);
    1137 
    1138 /**
    1139  * Check if the host kernel can run in VMX root mode.
    1140  *
    1141  * @returns VINF_SUCCESS if supported, error code indicating why if not.
    1142  */
    1143 SUPR3DECL(int) SUPR3QueryVTxSupported(void);
    1144 
    1145 /**
    1146  * Return VT-x/AMD-V capabilities.
    1147  *
    1148  * @returns VINF_SUCCESS if supported, error code indicating why if not.
    1149  * @param   pfCaps      Pointer to capability dword (out).
    1150  * @todo Intended for main, which means we need to relax the privilege requires
    1151  *       when accessing certain vboxdrv functions.
    1152  */
    1153 SUPR3DECL(int) SUPR3QueryVTCaps(uint32_t *pfCaps);
    1154 
    1155 /**
    1156  * Open the tracer.
    1157  *
    1158  * @returns VBox status code.
    1159  * @param   uCookie         Cookie identifying the tracer we expect to talk to.
    1160  * @param   uArg            Tracer specific open argument.
    1161  */
    1162 SUPR3DECL(int) SUPR3TracerOpen(uint32_t uCookie, uintptr_t uArg);
    1163 
    1164 /**
    1165  * Closes the tracer.
    1166  *
    1167  * @returns VBox status code.
    1168  */
    1169 SUPR3DECL(int) SUPR3TracerClose(void);
    1170 
    1171 /**
    1172  * Perform an I/O request on the tracer.
    1173  *
    1174  * @returns VBox status.
    1175  * @param   uCmd                The tracer command.
    1176  * @param   uArg                The argument.
    1177  * @param   piRetVal            Where to store the tracer return value.
    1178  */
    1179 SUPR3DECL(int) SUPR3TracerIoCtl(uintptr_t uCmd, uintptr_t uArg, int32_t *piRetVal);
    1180 
    1181 /**
    1182  * Registers the user module with the tracer.
    1183  *
    1184  * @returns VBox status code.
    1185  * @param   hModNative          Native module handle.  Pass ~(uintptr_t)0 if not
    1186  *                              at hand.
    1187  * @param   pszModule           The module name.
    1188  * @param   pVtgHdr             The VTG header.
    1189  * @param   fFlags              See SUP_TRACER_UMOD_FLAGS_XXX
    1190  */
    1191 SUPR3DECL(int) SUPR3TracerRegisterModule(uintptr_t hModNative, const char *pszModule, struct VTGOBJHDR *pVtgHdr, uint32_t fFlags);
    1192 
    1193 /**
    1194  * Deregisters the user module.
    1195  *
    1196  * @returns VBox status code.
    1197  * @param   pVtgHdr             The VTG header.
    1198  */
    1199 SUPR3DECL(int) SUPR3TracerDeregisterModule(struct VTGOBJHDR *pVtgHdr);
    1200 
    1201 /**
    1202  * Fire the probe.
    1203  *
    1204  * @param   pVtgProbeLoc        The probe location record.
    1205  * @param   uArg0               Raw probe argument 0.
    1206  * @param   uArg1               Raw probe argument 1.
    1207  * @param   uArg2               Raw probe argument 2.
    1208  * @param   uArg3               Raw probe argument 3.
    1209  * @param   uArg4               Raw probe argument 4.
    1210  */
    1211 SUPDECL(void)  SUPTracerFireProbe(struct VTGPROBELOC *pVtgProbeLoc, uintptr_t uArg0, uintptr_t uArg1, uintptr_t uArg2,
    1212                                   uintptr_t uArg3, uintptr_t uArg4);
    1213 /** @} */
    1214 #endif /* IN_RING3 */
    1215 
    1216 /** @name User mode module flags (SUPR3TracerRegisterModule & SUP_IOCTL_TRACER_UMOD_REG).
    1217  * @{ */
    1218 /** Executable image. */
    1219 #define SUP_TRACER_UMOD_FLAGS_EXE           UINT32_C(1)
    1220 /** Shared library (DLL, DYLIB, SO, etc). */
    1221 #define SUP_TRACER_UMOD_FLAGS_SHARED        UINT32_C(2)
    1222 /** Image type mask. */
    1223 #define SUP_TRACER_UMOD_FLAGS_TYPE_MASK     UINT32_C(3)
    1224 /** @} */
    1225 
    1226 
    1227 #ifdef IN_RING0
    1228 /** @defgroup   grp_sup_r0     SUP Host Context Ring-0 API
    1229  * @ingroup grp_sup
    1230  * @{
    1231  */
    1232 
    1233 /**
    1234  * Security objectype.
    1235  */
    1236 typedef enum SUPDRVOBJTYPE
    1237 {
    1238     /** The usual invalid object. */
    1239     SUPDRVOBJTYPE_INVALID = 0,
    1240     /** A Virtual Machine instance. */
    1241     SUPDRVOBJTYPE_VM,
    1242     /** Internal network. */
    1243     SUPDRVOBJTYPE_INTERNAL_NETWORK,
    1244     /** Internal network interface. */
    1245     SUPDRVOBJTYPE_INTERNAL_NETWORK_INTERFACE,
    1246     /** Single release event semaphore. */
    1247     SUPDRVOBJTYPE_SEM_EVENT,
    1248     /** Multiple release event semaphore. */
    1249     SUPDRVOBJTYPE_SEM_EVENT_MULTI,
    1250     /** Raw PCI device. */
    1251     SUPDRVOBJTYPE_RAW_PCI_DEVICE,
    1252     /** The first invalid object type in this end. */
    1253     SUPDRVOBJTYPE_END,
    1254     /** The usual 32-bit type size hack. */
    1255     SUPDRVOBJTYPE_32_BIT_HACK = 0x7ffffff
    1256 } SUPDRVOBJTYPE;
    1257 
    1258 /**
    1259  * Object destructor callback.
    1260  * This is called for reference counted objectes when the count reaches 0.
    1261  *
    1262  * @param   pvObj       The object pointer.
    1263  * @param   pvUser1     The first user argument.
    1264  * @param   pvUser2     The second user argument.
    1265  */
    1266 typedef DECLCALLBACK(void) FNSUPDRVDESTRUCTOR(void *pvObj, void *pvUser1, void *pvUser2);
    1267 /** Pointer to a FNSUPDRVDESTRUCTOR(). */
    1268 typedef FNSUPDRVDESTRUCTOR *PFNSUPDRVDESTRUCTOR;
    1269 
    1270 SUPR0DECL(void *) SUPR0ObjRegister(PSUPDRVSESSION pSession, SUPDRVOBJTYPE enmType, PFNSUPDRVDESTRUCTOR pfnDestructor, void *pvUser1, void *pvUser2);
    1271 SUPR0DECL(int) SUPR0ObjAddRef(void *pvObj, PSUPDRVSESSION pSession);
    1272 SUPR0DECL(int) SUPR0ObjAddRefEx(void *pvObj, PSUPDRVSESSION pSession, bool fNoBlocking);
    1273 SUPR0DECL(int) SUPR0ObjRelease(void *pvObj, PSUPDRVSESSION pSession);
    1274 SUPR0DECL(int) SUPR0ObjVerifyAccess(void *pvObj, PSUPDRVSESSION pSession, const char *pszObjName);
    1275 
    1276 SUPR0DECL(int) SUPR0LockMem(PSUPDRVSESSION pSession, RTR3PTR pvR3, uint32_t cPages, PRTHCPHYS paPages);
    1277 SUPR0DECL(int) SUPR0UnlockMem(PSUPDRVSESSION pSession, RTR3PTR pvR3);
    1278 SUPR0DECL(int) SUPR0ContAlloc(PSUPDRVSESSION pSession, uint32_t cPages, PRTR0PTR ppvR0, PRTR3PTR ppvR3, PRTHCPHYS pHCPhys);
    1279 SUPR0DECL(int) SUPR0ContFree(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr);
    1280 SUPR0DECL(int) SUPR0LowAlloc(PSUPDRVSESSION pSession, uint32_t cPages, PRTR0PTR ppvR0, PRTR3PTR ppvR3, PRTHCPHYS paPages);
    1281 SUPR0DECL(int) SUPR0LowFree(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr);
    1282 SUPR0DECL(int) SUPR0MemAlloc(PSUPDRVSESSION pSession, uint32_t cb, PRTR0PTR ppvR0, PRTR3PTR ppvR3);
    1283 SUPR0DECL(int) SUPR0MemGetPhys(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr, PSUPPAGE paPages);
    1284 SUPR0DECL(int) SUPR0MemFree(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr);
    1285 SUPR0DECL(int) SUPR0PageAllocEx(PSUPDRVSESSION pSession, uint32_t cPages, uint32_t fFlags, PRTR3PTR ppvR3, PRTR0PTR ppvR0, PRTHCPHYS paPages);
    1286 SUPR0DECL(int) SUPR0PageMapKernel(PSUPDRVSESSION pSession, RTR3PTR pvR3, uint32_t offSub, uint32_t cbSub, uint32_t fFlags, PRTR0PTR ppvR0);
    1287 SUPR0DECL(int) SUPR0PageProtect(PSUPDRVSESSION pSession, RTR3PTR pvR3, RTR0PTR pvR0, uint32_t offSub, uint32_t cbSub, uint32_t fProt);
    1288 SUPR0DECL(int) SUPR0PageFree(PSUPDRVSESSION pSession, RTR3PTR pvR3);
    1289 SUPR0DECL(int) SUPR0GipMap(PSUPDRVSESSION pSession, PRTR3PTR ppGipR3, PRTHCPHYS pHCPhysGip);
    1290 SUPR0DECL(int) SUPR0QueryVTCaps(PSUPDRVSESSION pSession, uint32_t *pfCaps);
    1291 SUPR0DECL(int) SUPR0GipUnmap(PSUPDRVSESSION pSession);
    1292 SUPR0DECL(int) SUPR0Printf(const char *pszFormat, ...);
    1293 SUPR0DECL(SUPPAGINGMODE) SUPR0GetPagingMode(void);
    1294 SUPR0DECL(int) SUPR0EnableVTx(bool fEnable);
    1295 
    1296 /** @name Absolute symbols
    1297  * Take the address of these, don't try call them.
    1298  * @{ */
    1299 SUPR0DECL(void) SUPR0AbsIs64bit(void);
    1300 SUPR0DECL(void) SUPR0Abs64bitKernelCS(void);
    1301 SUPR0DECL(void) SUPR0Abs64bitKernelSS(void);
    1302 SUPR0DECL(void) SUPR0Abs64bitKernelDS(void);
    1303 SUPR0DECL(void) SUPR0AbsKernelCS(void);
    1304 SUPR0DECL(void) SUPR0AbsKernelSS(void);
    1305 SUPR0DECL(void) SUPR0AbsKernelDS(void);
    1306 SUPR0DECL(void) SUPR0AbsKernelES(void);
    1307 SUPR0DECL(void) SUPR0AbsKernelFS(void);
    1308 SUPR0DECL(void) SUPR0AbsKernelGS(void);
    1309 /** @} */
    1310 
    1311 /**
    1312  * Support driver component factory.
    1313  *
    1314  * Component factories are registered by drivers that provides services
    1315  * such as the host network interface filtering and access to the host
    1316  * TCP/IP stack.
    1317  *
    1318  * @remark Module dependencies and making sure that a component doesn't
    1319  *         get unloaded while in use, is the sole responsibility of the
    1320  *         driver/kext/whatever implementing the component.
    1321  */
    1322 typedef struct SUPDRVFACTORY
    1323 {
    1324     /** The (unique) name of the component factory. */
    1325     char szName[56];
    1326     /**
    1327      * Queries a factory interface.
    1328      *
    1329      * The factory interface is specific to each component and will be be
    1330      * found in the header(s) for the component alongside its UUID.
    1331      *
    1332      * @returns Pointer to the factory interfaces on success, NULL on failure.
    1333      *
    1334      * @param   pSupDrvFactory      Pointer to this structure.
    1335      * @param   pSession            The SUPDRV session making the query.
    1336      * @param   pszInterfaceUuid    The UUID of the factory interface.
    1337      */
    1338     DECLR0CALLBACKMEMBER(void *, pfnQueryFactoryInterface,(struct SUPDRVFACTORY const *pSupDrvFactory, PSUPDRVSESSION pSession, const char *pszInterfaceUuid));
    1339 } SUPDRVFACTORY;
    1340 /** Pointer to a support driver factory. */
    1341 typedef SUPDRVFACTORY *PSUPDRVFACTORY;
    1342 /** Pointer to a const support driver factory. */
    1343 typedef SUPDRVFACTORY const *PCSUPDRVFACTORY;
    1344 
    1345 SUPR0DECL(int) SUPR0ComponentRegisterFactory(PSUPDRVSESSION pSession, PCSUPDRVFACTORY pFactory);
    1346 SUPR0DECL(int) SUPR0ComponentDeregisterFactory(PSUPDRVSESSION pSession, PCSUPDRVFACTORY pFactory);
    1347 SUPR0DECL(int) SUPR0ComponentQueryFactory(PSUPDRVSESSION pSession, const char *pszName, const char *pszInterfaceUuid, void **ppvFactoryIf);
    1348 
    1349 
    1350 /** @name Tracing
    1351  * @{ */
    1352 
    1353 /**
    1354  * Tracer data associated with a provider.
    1355  */
    1356 typedef union SUPDRVTRACERDATA
    1357 {
    1358     /** Generic */
    1359     uint64_t                    au64[2];
    1360 
    1361     /** DTrace data. */
    1362     struct
    1363     {
    1364         /** Provider ID. */
    1365         uintptr_t               idProvider;
    1366         /** The number of trace points provided. */
    1367         uint32_t volatile       cProvidedProbes;
    1368         /** Whether we've invalidated this bugger. */
    1369         bool                    fZombie;
    1370     } DTrace;
    1371 } SUPDRVTRACERDATA;
    1372 /** Pointer to the tracer data associated with a provider. */
    1373 typedef SUPDRVTRACERDATA *PSUPDRVTRACERDATA;
    1374 
    1375 /**
    1376  * Support driver tracepoint provider core.
    1377  */
    1378 typedef struct SUPDRVVDTPROVIDERCORE
    1379 {
    1380     /** The tracer data member. */
    1381     SUPDRVTRACERDATA            TracerData;
    1382     /** The provider descriptor. */
    1383     struct VTGDESCPROVIDER     *pDesc;
    1384     /** The VTG header. */
    1385     struct VTGOBJHDR           *pHdr;
    1386     /** Pointer to the provider name (a copy that's always available). */
    1387     const char                 *pszName;
    1388     /** Pointer to the module name. */
    1389     const char                 *pszModName;
    1390 } SUPDRVVDTPROVIDERCORE;
    1391 /** Pointer to a tracepoint provider core structure. */
    1392 typedef SUPDRVVDTPROVIDERCORE *PSUPDRVVDTPROVIDERCORE;
    1393 
    139493
    139594/**
     
    1452151            uint64_t        r13;
    1453152            uint64_t        r14;
     153            uint64_t        r15;
    1454154        } Amd64;
    1455155    } u;
    1456156} SUPDRVTRACERUSRCTX;
    1457157/** Pointer to the usermode probe context information. */
     158typedef SUPDRVTRACERUSRCTX *PSUPDRVTRACERUSRCTX;
     159/** Pointer to the const usermode probe context information. */
    1458160typedef SUPDRVTRACERUSRCTX const *PCSUPDRVTRACERUSRCTX;
    1459161
     162/**
     163 * The CPU state.
     164 */
     165typedef enum SUPGIPCPUSTATE
     166{
     167    /** Invalid CPU state / unused CPU entry. */
     168    SUPGIPCPUSTATE_INVALID = 0,
     169    /** The CPU is not present. */
     170    SUPGIPCPUSTATE_ABSENT,
     171    /** The CPU is offline. */
     172    SUPGIPCPUSTATE_OFFLINE,
     173    /** The CPU is online. */
     174    SUPGIPCPUSTATE_ONLINE,
     175    /** Force 32-bit enum type. */
     176    SUPGIPCPUSTATE_32_BIT_HACK = 0x7fffffff
     177} SUPGIPCPUSTATE;
     178
     179/**
     180 * Per CPU data.
     181 */
     182typedef struct SUPGIPCPU
     183{
     184    /** Update transaction number.
     185     * This number is incremented at the start and end of each update. It follows
     186     * thusly that odd numbers indicates update in progress, while even numbers
     187     * indicate stable data. Use this to make sure that the data items you fetch
     188     * are consistent. */
     189    volatile uint32_t   u32TransactionId;
     190    /** The interval in TSC ticks between two NanoTS updates.
     191     * This is the average interval over the last 2, 4 or 8 updates + a little slack.
     192     * The slack makes the time go a tiny tiny bit slower and extends the interval enough
     193     * to avoid ending up with too many 1ns increments. */
     194    volatile uint32_t   u32UpdateIntervalTSC;
     195    /** Current nanosecond timestamp. */
     196    volatile uint64_t   u64NanoTS;
     197    /** The TSC at the time of u64NanoTS. */
     198    volatile uint64_t   u64TSC;
     199    /** Current CPU Frequency. */
     200    volatile uint64_t   u64CpuHz;
     201    /** Number of errors during updating.
     202     * Typical errors are under/overflows. */
     203    volatile uint32_t   cErrors;
     204    /** Index of the head item in au32TSCHistory. */
     205    volatile uint32_t   iTSCHistoryHead;
     206    /** Array of recent TSC interval deltas.
     207     * The most recent item is at index iTSCHistoryHead.
     208     * This history is used to calculate u32UpdateIntervalTSC.
     209     */
     210    volatile uint32_t   au32TSCHistory[8];
     211    /** The interval between the last two NanoTS updates. (experiment for now) */
     212    volatile uint32_t   u32PrevUpdateIntervalNS;
     213
     214    /** Reserved for future per processor data. */
     215    volatile uint32_t   au32Reserved[5+5];
     216
     217    /** @todo Add topology/NUMA info. */
     218    /** The CPU state. */
     219    SUPGIPCPUSTATE volatile enmState;
     220    /** The host CPU ID of this CPU (the SUPGIPCPU is indexed by APIC ID). */
     221    RTCPUID                 idCpu;
     222    /** The CPU set index of this CPU. */
     223    int16_t                 iCpuSet;
     224    /** The APIC ID of this CPU. */
     225    uint16_t                idApic;
     226} SUPGIPCPU;
     227AssertCompileSize(RTCPUID, 4);
     228AssertCompileSize(SUPGIPCPU, 128);
     229AssertCompileMemberAlignment(SUPGIPCPU, u64NanoTS, 8);
     230AssertCompileMemberAlignment(SUPGIPCPU, u64TSC, 8);
     231
     232/** Pointer to per cpu data.
     233 * @remark there is no const version of this typedef, see g_pSUPGlobalInfoPage for details. */
     234typedef SUPGIPCPU *PSUPGIPCPU;
     235
     236
     237
     238/**
     239 * Global Information Page.
     240 *
     241 * This page contains useful information and can be mapped into any
     242 * process or VM. It can be accessed thru the g_pSUPGlobalInfoPage
     243 * pointer when a session is open.
     244 */
     245typedef struct SUPGLOBALINFOPAGE
     246{
     247    /** Magic (SUPGLOBALINFOPAGE_MAGIC). */
     248    uint32_t            u32Magic;
     249    /** The GIP version. */
     250    uint32_t            u32Version;
     251
     252    /** The GIP update mode, see SUPGIPMODE. */
     253    uint32_t            u32Mode;
     254    /** The number of entries in the CPU table.
     255     * (This can work as RTMpGetArraySize().)  */
     256    uint16_t            cCpus;
     257    /** The size of the GIP in pages. */
     258    uint16_t            cPages;
     259    /** The update frequency of the of the NanoTS. */
     260    volatile uint32_t   u32UpdateHz;
     261    /** The update interval in nanoseconds. (10^9 / u32UpdateHz) */
     262    volatile uint32_t   u32UpdateIntervalNS;
     263    /** The timestamp of the last time we update the update frequency. */
     264    volatile uint64_t   u64NanoTSLastUpdateHz;
     265    /** The set of online CPUs. */
     266    RTCPUSET            OnlineCpuSet;
     267    /** The set of present CPUs. */
     268    RTCPUSET            PresentCpuSet;
     269    /** The set of possible CPUs. */
     270    RTCPUSET            PossibleCpuSet;
     271    /** The number of CPUs that are online. */
     272    volatile uint16_t   cOnlineCpus;
     273    /** The number of CPUs present in the system. */
     274    volatile uint16_t   cPresentCpus;
     275    /** The highest number of CPUs possible. */
     276    uint16_t            cPossibleCpus;
     277    /** The highest number of CPUs possible. */
     278    uint16_t            u16Padding0;
     279    /** The max CPU ID (RTMpGetMaxCpuId). */
     280    RTCPUID             idCpuMax;
     281
     282    /** Padding / reserved space for future data. */
     283    uint32_t            au32Padding1[29];
     284
     285    /** Table indexed by the CPU APIC ID to get the CPU table index. */
     286    uint16_t            aiCpuFromApicId[256];
     287    /** CPU set index to CPU table index. */
     288    uint16_t            aiCpuFromCpuSetIdx[RTCPUSET_MAX_CPUS];
     289
     290    /** Array of per-cpu data.
     291     * This is index by ApicId via the aiCpuFromApicId table.
     292     *
     293     * The clock and frequency information is updated for all CPUs if u32Mode
     294     * is SUPGIPMODE_ASYNC_TSC, otherwise (SUPGIPMODE_SYNC_TSC) only the first
     295     * entry is updated. */
     296    SUPGIPCPU           aCPUs[1];
     297} SUPGLOBALINFOPAGE;
     298AssertCompileMemberAlignment(SUPGLOBALINFOPAGE, u64NanoTSLastUpdateHz, 8);
     299#if defined(RT_ARCH_SPARC) || defined(RT_ARCH_SPARC64)
     300AssertCompileMemberAlignment(SUPGLOBALINFOPAGE, aCPUs, 32);
     301#else
     302AssertCompileMemberAlignment(SUPGLOBALINFOPAGE, aCPUs, 256);
     303#endif
     304
     305/** Pointer to the global info page.
     306 * @remark there is no const version of this typedef, see g_pSUPGlobalInfoPage for details. */
     307typedef SUPGLOBALINFOPAGE *PSUPGLOBALINFOPAGE;
     308
     309
     310/** The value of the SUPGLOBALINFOPAGE::u32Magic field. (Soryo Fuyumi) */
     311#define SUPGLOBALINFOPAGE_MAGIC     0x19590106
     312/** The GIP version.
     313 * Upper 16 bits is the major version. Major version is only changed with
     314 * incompatible changes in the GIP. */
     315#define SUPGLOBALINFOPAGE_VERSION   0x00030000
     316
     317/**
     318 * SUPGLOBALINFOPAGE::u32Mode values.
     319 */
     320typedef enum SUPGIPMODE
     321{
     322    /** The usual invalid null entry. */
     323    SUPGIPMODE_INVALID = 0,
     324    /** The TSC of the cores and cpus in the system is in sync. */
     325    SUPGIPMODE_SYNC_TSC,
     326    /** Each core has it's own TSC. */
     327    SUPGIPMODE_ASYNC_TSC,
     328    /** The usual 32-bit hack. */
     329    SUPGIPMODE_32BIT_HACK = 0x7fffffff
     330} SUPGIPMODE;
     331
     332/** Pointer to the Global Information Page.
     333 *
     334 * This pointer is valid as long as SUPLib has a open session. Anyone using
     335 * the page must treat this pointer as highly volatile and not trust it beyond
     336 * one transaction.
     337 *
     338 * @remark  The GIP page is read-only to everyone but the support driver and
     339 *          is actually mapped read only everywhere but in ring-0. However
     340 *          it is not marked 'const' as this might confuse compilers into
     341 *          thinking that values doesn't change even if members are marked
     342 *          as volatile. Thus, there is no PCSUPGLOBALINFOPAGE type.
     343 */
     344#if defined(IN_SUP_R0) || defined(IN_SUP_R3) || defined(IN_SUP_RC)
     345extern DECLEXPORT(PSUPGLOBALINFOPAGE)   g_pSUPGlobalInfoPage;
     346
     347#elif !defined(IN_RING0) || defined(RT_OS_WINDOWS) || defined(RT_OS_SOLARIS)
     348extern DECLIMPORT(PSUPGLOBALINFOPAGE)   g_pSUPGlobalInfoPage;
     349
     350#else /* IN_RING0 && !RT_OS_WINDOWS */
     351# if !defined(__GNUC__) || defined(RT_OS_DARWIN) || !defined(RT_ARCH_AMD64)
     352#  define g_pSUPGlobalInfoPage          (&g_SUPGlobalInfoPage)
     353# else
     354#  define g_pSUPGlobalInfoPage          (SUPGetGIPHlp())
     355/** Workaround for ELF+GCC problem on 64-bit hosts.
     356 * (GCC emits a mov with a R_X86_64_32 reloc, we need R_X86_64_64.) */
     357DECLINLINE(PSUPGLOBALINFOPAGE) SUPGetGIPHlp(void)
     358{
     359    PSUPGLOBALINFOPAGE pGIP;
     360    __asm__ __volatile__ ("movabs $g_SUPGlobalInfoPage,%0\n\t"
     361                          : "=a" (pGIP));
     362    return pGIP;
     363}
     364# endif
     365/** The GIP.
     366 * We save a level of indirection by exporting the GIP instead of a variable
     367 * pointing to it. */
     368extern DECLIMPORT(SUPGLOBALINFOPAGE)    g_SUPGlobalInfoPage;
     369#endif
     370
     371/**
     372 * Gets the GIP pointer.
     373 *
     374 * @returns Pointer to the GIP or NULL.
     375 */
     376SUPDECL(PSUPGLOBALINFOPAGE)             SUPGetGIP(void);
     377
     378#ifdef ___iprt_asm_amd64_x86_h
     379/**
     380 * Gets the TSC frequency of the calling CPU.
     381 *
     382 * @returns TSC frequency, UINT64_MAX on failure.
     383 * @param   pGip        The GIP pointer.
     384 */
     385DECLINLINE(uint64_t) SUPGetCpuHzFromGIP(PSUPGLOBALINFOPAGE pGip)
     386{
     387    unsigned iCpu;
     388
     389    if (RT_UNLIKELY(!pGip || pGip->u32Magic != SUPGLOBALINFOPAGE_MAGIC))
     390        return UINT64_MAX;
     391
     392    if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC)
     393        iCpu = 0;
     394    else
     395    {
     396        iCpu = pGip->aiCpuFromApicId[ASMGetApicId()];
     397        if (iCpu >= pGip->cCpus)
     398            return UINT64_MAX;
     399    }
     400
     401    return pGip->aCPUs[iCpu].u64CpuHz;
     402}
     403#endif
     404
     405/**
     406 * Request for generic VMMR0Entry calls.
     407 */
     408typedef struct SUPVMMR0REQHDR
     409{
     410    /** The magic. (SUPVMMR0REQHDR_MAGIC) */
     411    uint32_t    u32Magic;
     412    /** The size of the request. */
     413    uint32_t    cbReq;
     414} SUPVMMR0REQHDR;
     415/** Pointer to a ring-0 request header. */
     416typedef SUPVMMR0REQHDR *PSUPVMMR0REQHDR;
     417/** the SUPVMMR0REQHDR::u32Magic value (Ethan Iverson - The Bad Plus). */
     418#define SUPVMMR0REQHDR_MAGIC        UINT32_C(0x19730211)
     419
     420
     421/** For the fast ioctl path.
     422 * @{
     423 */
     424/** @see VMMR0_DO_RAW_RUN. */
     425#define SUP_VMMR0_DO_RAW_RUN    0
     426/** @see VMMR0_DO_HWACC_RUN. */
     427#define SUP_VMMR0_DO_HWACC_RUN  1
     428/** @see VMMR0_DO_NOP */
     429#define SUP_VMMR0_DO_NOP        2
     430/** @} */
     431
     432/** SUPR3QueryVTCaps capability flags
     433 * @{
     434 */
     435#define SUPVTCAPS_AMD_V             RT_BIT(0)
     436#define SUPVTCAPS_VT_X              RT_BIT(1)
     437#define SUPVTCAPS_NESTED_PAGING     RT_BIT(2)
     438/** @} */
     439
     440/**
     441 * Request for generic FNSUPR0SERVICEREQHANDLER calls.
     442 */
     443typedef struct SUPR0SERVICEREQHDR
     444{
     445    /** The magic. (SUPR0SERVICEREQHDR_MAGIC) */
     446    uint32_t    u32Magic;
     447    /** The size of the request. */
     448    uint32_t    cbReq;
     449} SUPR0SERVICEREQHDR;
     450/** Pointer to a ring-0 service request header. */
     451typedef SUPR0SERVICEREQHDR *PSUPR0SERVICEREQHDR;
     452/** the SUPVMMR0REQHDR::u32Magic value (Esbjoern Svensson - E.S.P.).  */
     453#define SUPR0SERVICEREQHDR_MAGIC    UINT32_C(0x19640416)
     454
     455
     456/** Event semaphore handle. Ring-0 / ring-3. */
     457typedef R0PTRTYPE(struct SUPSEMEVENTHANDLE *) SUPSEMEVENT;
     458/** Pointer to an event semaphore handle. */
     459typedef SUPSEMEVENT *PSUPSEMEVENT;
     460/** Nil event semaphore handle. */
     461#define NIL_SUPSEMEVENT         ((SUPSEMEVENT)0)
     462
     463/**
     464 * Creates a single release event semaphore.
     465 *
     466 * @returns VBox status code.
     467 * @param   pSession        The session handle of the caller.
     468 * @param   phEvent         Where to return the handle to the event semaphore.
     469 */
     470SUPDECL(int) SUPSemEventCreate(PSUPDRVSESSION pSession, PSUPSEMEVENT phEvent);
     471
     472/**
     473 * Closes a single release event semaphore handle.
     474 *
     475 * @returns VBox status code.
     476 * @retval  VINF_OBJECT_DESTROYED if the semaphore was destroyed.
     477 * @retval  VINF_SUCCESS if the handle was successfully closed but the semaphore
     478 *          object remained alive because of other references.
     479 *
     480 * @param   pSession            The session handle of the caller.
     481 * @param   hEvent              The handle. Nil is quietly ignored.
     482 */
     483SUPDECL(int) SUPSemEventClose(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent);
     484
     485/**
     486 * Signals a single release event semaphore.
     487 *
     488 * @returns VBox status code.
     489 * @param   pSession            The session handle of the caller.
     490 * @param   hEvent              The semaphore handle.
     491 */
     492SUPDECL(int) SUPSemEventSignal(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent);
     493
     494#ifdef IN_RING0
     495/**
     496 * Waits on a single release event semaphore, not interruptible.
     497 *
     498 * @returns VBox status code.
     499 * @param   pSession            The session handle of the caller.
     500 * @param   hEvent              The semaphore handle.
     501 * @param   cMillies            The number of milliseconds to wait.
     502 * @remarks Not available in ring-3.
     503 */
     504SUPDECL(int) SUPSemEventWait(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies);
     505#endif
     506
     507/**
     508 * Waits on a single release event semaphore, interruptible.
     509 *
     510 * @returns VBox status code.
     511 * @param   pSession            The session handle of the caller.
     512 * @param   hEvent              The semaphore handle.
     513 * @param   cMillies            The number of milliseconds to wait.
     514 */
     515SUPDECL(int) SUPSemEventWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies);
     516
     517/**
     518 * Waits on a single release event semaphore, interruptible.
     519 *
     520 * @returns VBox status code.
     521 * @param   pSession            The session handle of the caller.
     522 * @param   hEvent              The semaphore handle.
     523 * @param   uNsTimeout          The deadline given on the RTTimeNanoTS() clock.
     524 */
     525SUPDECL(int) SUPSemEventWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t uNsTimeout);
     526
     527/**
     528 * Waits on a single release event semaphore, interruptible.
     529 *
     530 * @returns VBox status code.
     531 * @param   pSession            The session handle of the caller.
     532 * @param   hEvent              The semaphore handle.
     533 * @param   cNsTimeout          The number of nanoseconds to wait.
     534 */
     535SUPDECL(int) SUPSemEventWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t cNsTimeout);
     536
     537/**
     538 * Gets the best timeout resolution that SUPSemEventWaitNsAbsIntr and
     539 * SUPSemEventWaitNsAbsIntr can do.
     540 *
     541 * @returns The resolution in nanoseconds.
     542 * @param   pSession            The session handle of the caller.
     543 */
     544SUPDECL(uint32_t) SUPSemEventGetResolution(PSUPDRVSESSION pSession);
     545
     546
     547/** Multiple release event semaphore handle. Ring-0 / ring-3. */
     548typedef R0PTRTYPE(struct SUPSEMEVENTMULTIHANDLE *)  SUPSEMEVENTMULTI;
     549/** Pointer to an multiple release event semaphore handle. */
     550typedef SUPSEMEVENTMULTI                           *PSUPSEMEVENTMULTI;
     551/** Nil multiple release event semaphore handle. */
     552#define NIL_SUPSEMEVENTMULTI                        ((SUPSEMEVENTMULTI)0)
     553
     554/**
     555 * Creates a multiple release event semaphore.
     556 *
     557 * @returns VBox status code.
     558 * @param   pSession        The session handle of the caller.
     559 * @param   phEventMulti    Where to return the handle to the event semaphore.
     560 */
     561SUPDECL(int) SUPSemEventMultiCreate(PSUPDRVSESSION pSession, PSUPSEMEVENTMULTI phEventMulti);
     562
     563/**
     564 * Closes a multiple release event semaphore handle.
     565 *
     566 * @returns VBox status code.
     567 * @retval  VINF_OBJECT_DESTROYED if the semaphore was destroyed.
     568 * @retval  VINF_SUCCESS if the handle was successfully closed but the semaphore
     569 *          object remained alive because of other references.
     570 *
     571 * @param   pSession            The session handle of the caller.
     572 * @param   hEventMulti         The handle. Nil is quietly ignored.
     573 */
     574SUPDECL(int) SUPSemEventMultiClose(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti);
     575
     576/**
     577 * Signals a multiple release event semaphore.
     578 *
     579 * @returns VBox status code.
     580 * @param   pSession            The session handle of the caller.
     581 * @param   hEventMulti         The semaphore handle.
     582 */
     583SUPDECL(int) SUPSemEventMultiSignal(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti);
     584
     585/**
     586 * Resets a multiple release event semaphore.
     587 *
     588 * @returns VBox status code.
     589 * @param   pSession            The session handle of the caller.
     590 * @param   hEventMulti         The semaphore handle.
     591 */
     592SUPDECL(int) SUPSemEventMultiReset(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti);
     593
     594#ifdef IN_RING0
     595/**
     596 * Waits on a multiple release event semaphore, not interruptible.
     597 *
     598 * @returns VBox status code.
     599 * @param   pSession            The session handle of the caller.
     600 * @param   hEventMulti         The semaphore handle.
     601 * @param   cMillies            The number of milliseconds to wait.
     602 * @remarks Not available in ring-3.
     603 */
     604SUPDECL(int) SUPSemEventMultiWait(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies);
     605#endif
     606
     607/**
     608 * Waits on a multiple release event semaphore, interruptible.
     609 *
     610 * @returns VBox status code.
     611 * @param   pSession            The session handle of the caller.
     612 * @param   hEventMulti         The semaphore handle.
     613 * @param   cMillies            The number of milliseconds to wait.
     614 */
     615SUPDECL(int) SUPSemEventMultiWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies);
     616
     617/**
     618 * Waits on a multiple release event semaphore, interruptible.
     619 *
     620 * @returns VBox status code.
     621 * @param   pSession            The session handle of the caller.
     622 * @param   hEventMulti         The semaphore handle.
     623 * @param   uNsTimeout          The deadline given on the RTTimeNanoTS() clock.
     624 */
     625SUPDECL(int) SUPSemEventMultiWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t uNsTimeout);
     626
     627/**
     628 * Waits on a multiple release event semaphore, interruptible.
     629 *
     630 * @returns VBox status code.
     631 * @param   pSession            The session handle of the caller.
     632 * @param   hEventMulti         The semaphore handle.
     633 * @param   cNsTimeout          The number of nanoseconds to wait.
     634 */
     635SUPDECL(int) SUPSemEventMultiWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t cNsTimeout);
     636
     637/**
     638 * Gets the best timeout resolution that SUPSemEventMultiWaitNsAbsIntr and
     639 * SUPSemEventMultiWaitNsRelIntr can do.
     640 *
     641 * @returns The resolution in nanoseconds.
     642 * @param   pSession            The session handle of the caller.
     643 */
     644SUPDECL(uint32_t) SUPSemEventMultiGetResolution(PSUPDRVSESSION pSession);
     645
     646
     647#ifdef IN_RING3
     648
     649/** @defgroup   grp_sup_r3     SUP Host Context Ring-3 API
     650 * @ingroup grp_sup
     651 * @{
     652 */
     653
     654/**
     655 * Installs the support library.
     656 *
     657 * @returns VBox status code.
     658 */
     659SUPR3DECL(int) SUPR3Install(void);
     660
     661/**
     662 * Uninstalls the support library.
     663 *
     664 * @returns VBox status code.
     665 */
     666SUPR3DECL(int) SUPR3Uninstall(void);
     667
     668/**
     669 * Trusted main entry point.
     670 *
     671 * This is exported as "TrustedMain" by the dynamic libraries which contains the
     672 * "real" application binary for which the hardened stub is built.  The entry
     673 * point is invoked upon successful initialization of the support library and
     674 * runtime.
     675 *
     676 * @returns main kind of exit code.
     677 * @param   argc            The argument count.
     678 * @param   argv            The argument vector.
     679 * @param   envp            The environment vector.
     680 */
     681typedef DECLCALLBACK(int) FNSUPTRUSTEDMAIN(int argc, char **argv, char **envp);
     682/** Pointer to FNSUPTRUSTEDMAIN(). */
     683typedef FNSUPTRUSTEDMAIN *PFNSUPTRUSTEDMAIN;
     684
     685/** Which operation failed. */
     686typedef enum SUPINITOP
     687{
     688    /** Invalid. */
     689    kSupInitOp_Invalid = 0,
     690    /** Installation integrity error. */
     691    kSupInitOp_Integrity,
     692    /** Setuid related. */
     693    kSupInitOp_RootCheck,
     694    /** Driver related. */
     695    kSupInitOp_Driver,
     696    /** IPRT init related. */
     697    kSupInitOp_IPRT,
     698    /** Place holder. */
     699    kSupInitOp_End
     700} SUPINITOP;
     701
     702/**
     703 * Trusted error entry point, optional.
     704 *
     705 * This is exported as "TrustedError" by the dynamic libraries which contains
     706 * the "real" application binary for which the hardened stub is built.
     707 *
     708 * @param   pszWhere        Where the error occurred (function name).
     709 * @param   enmWhat         Which operation went wrong.
     710 * @param   rc              The status code.
     711 * @param   pszMsgFmt       Error message format string.
     712 * @param   va              The message format arguments.
     713 */
     714typedef DECLCALLBACK(void) FNSUPTRUSTEDERROR(const char *pszWhere, SUPINITOP enmWhat, int rc, const char *pszMsgFmt, va_list va);
     715/** Pointer to FNSUPTRUSTEDERROR. */
     716typedef FNSUPTRUSTEDERROR *PFNSUPTRUSTEDERROR;
     717
     718/**
     719 * Secure main.
     720 *
     721 * This is used for the set-user-ID-on-execute binaries on unixy systems
     722 * and when using the open-vboxdrv-via-root-service setup on Windows.
     723 *
     724 * This function will perform the integrity checks of the VirtualBox
     725 * installation, open the support driver, open the root service (later),
     726 * and load the DLL corresponding to \a pszProgName and execute its main
     727 * function.
     728 *
     729 * @returns Return code appropriate for main().
     730 *
     731 * @param   pszProgName     The program name. This will be used to figure out which
     732 *                          DLL/SO/DYLIB to load and execute.
     733 * @param   fFlags          Flags.
     734 * @param   argc            The argument count.
     735 * @param   argv            The argument vector.
     736 * @param   envp            The environment vector.
     737 */
     738DECLHIDDEN(int) SUPR3HardenedMain(const char *pszProgName, uint32_t fFlags, int argc, char **argv, char **envp);
     739
     740/** @name SUPR3SecureMain flags.
     741 * @{ */
     742/** Don't open the device. (Intended for VirtualBox without -startvm.) */
     743#define SUPSECMAIN_FLAGS_DONT_OPEN_DEV      RT_BIT_32(0)
     744/** @} */
     745
     746/**
     747 * Initializes the support library.
     748 * Each successful call to SUPR3Init() must be countered by a
     749 * call to SUPR3Term(false).
     750 *
     751 * @returns VBox status code.
     752 * @param   ppSession       Where to store the session handle. Defaults to NULL.
     753 */
     754SUPR3DECL(int) SUPR3Init(PSUPDRVSESSION *ppSession);
     755
     756/**
     757 * Terminates the support library.
     758 *
     759 * @returns VBox status code.
     760 * @param   fForced     Forced termination. This means to ignore the
     761 *                      init call count and just terminated.
     762 */
     763#ifdef __cplusplus
     764SUPR3DECL(int) SUPR3Term(bool fForced = false);
     765#else
     766SUPR3DECL(int) SUPR3Term(int fForced);
     767#endif
     768
     769/**
     770 * Sets the ring-0 VM handle for use with fast IOCtls.
     771 *
     772 * @returns VBox status code.
     773 * @param   pVMR0       The ring-0 VM handle.
     774 *                      NIL_RTR0PTR can be used to unset the handle when the
     775 *                      VM is about to be destroyed.
     776 */
     777SUPR3DECL(int) SUPR3SetVMForFastIOCtl(PVMR0 pVMR0);
     778
     779/**
     780 * Calls the HC R0 VMM entry point.
     781 * See VMMR0Entry() for more details.
     782 *
     783 * @returns error code specific to uFunction.
     784 * @param   pVMR0       Pointer to the Ring-0 (Host Context) mapping of the VM structure.
     785 * @param   idCpu       The virtual CPU ID.
     786 * @param   uOperation  Operation to execute.
     787 * @param   pvArg       Argument.
     788 */
     789SUPR3DECL(int) SUPR3CallVMMR0(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, void *pvArg);
     790
     791/**
     792 * Variant of SUPR3CallVMMR0, except that this takes the fast ioclt path
     793 * regardsless of compile-time defaults.
     794 *
     795 * @returns VBox status code.
     796 * @param   pVMR0       The ring-0 VM handle.
     797 * @param   uOperation  The operation; only the SUP_VMMR0_DO_* ones are valid.
     798 * @param   idCpu       The virtual CPU ID.
     799 */
     800SUPR3DECL(int) SUPR3CallVMMR0Fast(PVMR0 pVMR0, unsigned uOperation, VMCPUID idCpu);
     801
     802/**
     803 * Calls the HC R0 VMM entry point, in a safer but slower manner than
     804 * SUPR3CallVMMR0. When entering using this call the R0 components can call
     805 * into the host kernel (i.e. use the SUPR0 and RT APIs).
     806 *
     807 * See VMMR0Entry() for more details.
     808 *
     809 * @returns error code specific to uFunction.
     810 * @param   pVMR0       Pointer to the Ring-0 (Host Context) mapping of the VM structure.
     811 * @param   idCpu       The virtual CPU ID.
     812 * @param   uOperation  Operation to execute.
     813 * @param   u64Arg      Constant argument.
     814 * @param   pReqHdr     Pointer to a request header. Optional.
     815 *                      This will be copied in and out of kernel space. There currently is a size
     816 *                      limit on this, just below 4KB.
     817 */
     818SUPR3DECL(int) SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr);
     819
     820/**
     821 * Calls a ring-0 service.
     822 *
     823 * The operation and the request packet is specific to the service.
     824 *
     825 * @returns error code specific to uFunction.
     826 * @param   pszService  The service name.
     827 * @param   cchService  The length of the service name.
     828 * @param   uReq        The request number.
     829 * @param   u64Arg      Constant argument.
     830 * @param   pReqHdr     Pointer to a request header. Optional.
     831 *                      This will be copied in and out of kernel space. There currently is a size
     832 *                      limit on this, just below 4KB.
     833 */
     834SUPR3DECL(int) SUPR3CallR0Service(const char *pszService, size_t cchService, uint32_t uOperation, uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr);
     835
     836/** Which logger. */
     837typedef enum SUPLOGGER
     838{
     839    SUPLOGGER_DEBUG = 1,
     840    SUPLOGGER_RELEASE
     841} SUPLOGGER;
     842
     843/**
     844 * Changes the settings of the specified ring-0 logger.
     845 *
     846 * @returns VBox status code.
     847 * @param   enmWhich    Which logger.
     848 * @param   pszFlags    The flags settings.
     849 * @param   pszGroups   The groups settings.
     850 * @param   pszDest     The destination specificier.
     851 */
     852SUPR3DECL(int) SUPR3LoggerSettings(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest);
     853
     854/**
     855 * Creates a ring-0 logger instance.
     856 *
     857 * @returns VBox status code.
     858 * @param   enmWhich    Which logger to create.
     859 * @param   pszFlags    The flags settings.
     860 * @param   pszGroups   The groups settings.
     861 * @param   pszDest     The destination specificier.
     862 */
     863SUPR3DECL(int) SUPR3LoggerCreate(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest);
     864
     865/**
     866 * Destroys a ring-0 logger instance.
     867 *
     868 * @returns VBox status code.
     869 * @param   enmWhich    Which logger.
     870 */
     871SUPR3DECL(int) SUPR3LoggerDestroy(SUPLOGGER enmWhich);
     872
     873/**
     874 * Queries the paging mode of the host OS.
     875 *
     876 * @returns The paging mode.
     877 */
     878SUPR3DECL(SUPPAGINGMODE) SUPR3GetPagingMode(void);
     879
     880/**
     881 * Allocate zero-filled pages.
     882 *
     883 * Use this to allocate a number of pages suitable for seeding / locking.
     884 * Call SUPR3PageFree() to free the pages once done with them.
     885 *
     886 * @returns VBox status.
     887 * @param   cPages          Number of pages to allocate.
     888 * @param   ppvPages        Where to store the base pointer to the allocated pages.
     889 */
     890SUPR3DECL(int) SUPR3PageAlloc(size_t cPages, void **ppvPages);
     891
     892/**
     893 * Frees pages allocated with SUPR3PageAlloc().
     894 *
     895 * @returns VBox status.
     896 * @param   pvPages         Pointer returned by SUPR3PageAlloc().
     897 * @param   cPages          Number of pages that was allocated.
     898 */
     899SUPR3DECL(int) SUPR3PageFree(void *pvPages, size_t cPages);
     900
     901/**
     902 * Allocate non-zeroed, locked, pages with user and, optionally, kernel
     903 * mappings.
     904 *
     905 * Use SUPR3PageFreeEx() to free memory allocated with this function.
     906 *
     907 * @returns VBox status code.
     908 * @param   cPages          The number of pages to allocate.
     909 * @param   fFlags          Flags, reserved. Must be zero.
     910 * @param   ppvPages        Where to store the address of the user mapping.
     911 * @param   pR0Ptr          Where to store the address of the kernel mapping.
     912 *                          NULL if no kernel mapping is desired.
     913 * @param   paPages         Where to store the physical addresses of each page.
     914 *                          Optional.
     915 */
     916SUPR3DECL(int) SUPR3PageAllocEx(size_t cPages, uint32_t fFlags, void **ppvPages, PRTR0PTR pR0Ptr, PSUPPAGE paPages);
     917
     918/**
     919 * Maps a portion of a ring-3 only allocation into kernel space.
     920 *
     921 * @returns VBox status code.
     922 *
     923 * @param   pvR3            The address SUPR3PageAllocEx return.
     924 * @param   off             Offset to start mapping at. Must be page aligned.
     925 * @param   cb              Number of bytes to map. Must be page aligned.
     926 * @param   fFlags          Flags, must be zero.
     927 * @param   pR0Ptr          Where to store the address on success.
     928 *
     929 */
     930SUPR3DECL(int) SUPR3PageMapKernel(void *pvR3, uint32_t off, uint32_t cb, uint32_t fFlags, PRTR0PTR pR0Ptr);
     931
     932/**
     933 * Changes the protection of
     934 *
     935 * @returns VBox status code.
     936 * @retval  VERR_NOT_SUPPORTED if the OS doesn't allow us to change page level
     937 *          protection. See also RTR0MemObjProtect.
     938 *
     939 * @param   pvR3            The ring-3 address SUPR3PageAllocEx returned.
     940 * @param   R0Ptr           The ring-0 address SUPR3PageAllocEx returned if it
     941 *                          is desired that the corresponding ring-0 page
     942 *                          mappings should change protection as well. Pass
     943 *                          NIL_RTR0PTR if the ring-0 pages should remain
     944 *                          unaffected.
     945 * @param   off             Offset to start at which to start chagning the page
     946 *                          level protection. Must be page aligned.
     947 * @param   cb              Number of bytes to change. Must be page aligned.
     948 * @param   fProt           The new page level protection, either a combination
     949 *                          of RTMEM_PROT_READ, RTMEM_PROT_WRITE and
     950 *                          RTMEM_PROT_EXEC, or just RTMEM_PROT_NONE.
     951 */
     952SUPR3DECL(int) SUPR3PageProtect(void *pvR3, RTR0PTR R0Ptr, uint32_t off, uint32_t cb, uint32_t fProt);
     953
     954/**
     955 * Free pages allocated by SUPR3PageAllocEx.
     956 *
     957 * @returns VBox status code.
     958 * @param   pvPages         The address of the user mapping.
     959 * @param   cPages          The number of pages.
     960 */
     961SUPR3DECL(int) SUPR3PageFreeEx(void *pvPages, size_t cPages);
     962
     963/**
     964 * Allocated memory with page aligned memory with a contiguous and locked physical
     965 * memory backing below 4GB.
     966 *
     967 * @returns Pointer to the allocated memory (virtual address).
     968 *          *pHCPhys is set to the physical address of the memory.
     969 *          If ppvR0 isn't NULL, *ppvR0 is set to the ring-0 mapping.
     970 *          The returned memory must be freed using SUPR3ContFree().
     971 * @returns NULL on failure.
     972 * @param   cPages      Number of pages to allocate.
     973 * @param   pR0Ptr      Where to store the ring-0 mapping of the allocation. (optional)
     974 * @param   pHCPhys     Where to store the physical address of the memory block.
     975 *
     976 * @remark  This 2nd version of this API exists because we're not able to map the
     977 *          ring-3 mapping executable on WIN64. This is a serious problem in regard to
     978 *          the world switchers.
     979 */
     980SUPR3DECL(void *) SUPR3ContAlloc(size_t cPages, PRTR0PTR pR0Ptr, PRTHCPHYS pHCPhys);
     981
     982/**
     983 * Frees memory allocated with SUPR3ContAlloc().
     984 *
     985 * @returns VBox status code.
     986 * @param   pv          Pointer to the memory block which should be freed.
     987 * @param   cPages      Number of pages to be freed.
     988 */
     989SUPR3DECL(int) SUPR3ContFree(void *pv, size_t cPages);
     990
     991/**
     992 * Allocated non contiguous physical memory below 4GB.
     993 *
     994 * The memory isn't zeroed.
     995 *
     996 * @returns VBox status code.
     997 * @returns NULL on failure.
     998 * @param   cPages      Number of pages to allocate.
     999 * @param   ppvPages    Where to store the pointer to the allocated memory.
     1000 *                      The pointer stored here on success must be passed to
     1001 *                      SUPR3LowFree when the memory should be released.
     1002 * @param   ppvPagesR0  Where to store the ring-0 pointer to the allocated memory. optional.
     1003 * @param   paPages     Where to store the physical addresses of the individual pages.
     1004 */
     1005SUPR3DECL(int) SUPR3LowAlloc(size_t cPages, void **ppvPages, PRTR0PTR ppvPagesR0, PSUPPAGE paPages);
     1006
     1007/**
     1008 * Frees memory allocated with SUPR3LowAlloc().
     1009 *
     1010 * @returns VBox status code.
     1011 * @param   pv          Pointer to the memory block which should be freed.
     1012 * @param   cPages      Number of pages that was allocated.
     1013 */
     1014SUPR3DECL(int) SUPR3LowFree(void *pv, size_t cPages);
     1015
     1016/**
     1017 * Load a module into R0 HC.
     1018 *
     1019 * This will verify the file integrity in a similar manner as
     1020 * SUPR3HardenedVerifyFile before loading it.
     1021 *
     1022 * @returns VBox status code.
     1023 * @param   pszFilename     The path to the image file.
     1024 * @param   pszModule       The module name. Max 32 bytes.
     1025 * @param   ppvImageBase    Where to store the image address.
     1026 * @param   pErrInfo        Where to return extended error information.
     1027 *                          Optional.
     1028 */
     1029SUPR3DECL(int) SUPR3LoadModule(const char *pszFilename, const char *pszModule, void **ppvImageBase, PRTERRINFO pErrInfo);
     1030
     1031/**
     1032 * Load a module into R0 HC.
     1033 *
     1034 * This will verify the file integrity in a similar manner as
     1035 * SUPR3HardenedVerifyFile before loading it.
     1036 *
     1037 * @returns VBox status code.
     1038 * @param   pszFilename         The path to the image file.
     1039 * @param   pszModule           The module name. Max 32 bytes.
     1040 * @param   pszSrvReqHandler    The name of the service request handler entry
     1041 *                              point. See FNSUPR0SERVICEREQHANDLER.
     1042 * @param   ppvImageBase        Where to store the image address.
     1043 */
     1044SUPR3DECL(int) SUPR3LoadServiceModule(const char *pszFilename, const char *pszModule,
     1045                                      const char *pszSrvReqHandler, void **ppvImageBase);
     1046
     1047/**
     1048 * Frees a R0 HC module.
     1049 *
     1050 * @returns VBox status code.
     1051 * @param   pszModule       The module to free.
     1052 * @remark  This will not actually 'free' the module, there are of course usage counting.
     1053 */
     1054SUPR3DECL(int) SUPR3FreeModule(void *pvImageBase);
     1055
     1056/**
     1057 * Get the address of a symbol in a ring-0 module.
     1058 *
     1059 * @returns VBox status code.
     1060 * @param   pszModule       The module name.
     1061 * @param   pszSymbol       Symbol name. If it's value is less than 64k it's treated like a
     1062 *                          ordinal value rather than a string pointer.
     1063 * @param   ppvValue        Where to store the symbol value.
     1064 */
     1065SUPR3DECL(int) SUPR3GetSymbolR0(void *pvImageBase, const char *pszSymbol, void **ppvValue);
     1066
     1067/**
     1068 * Load R0 HC VMM code.
     1069 *
     1070 * @returns VBox status code.
     1071 * @deprecated  Use SUPR3LoadModule(pszFilename, "VMMR0.r0", &pvImageBase)
     1072 */
     1073SUPR3DECL(int) SUPR3LoadVMM(const char *pszFilename);
     1074
     1075/**
     1076 * Unloads R0 HC VMM code.
     1077 *
     1078 * @returns VBox status code.
     1079 * @deprecated  Use SUPR3FreeModule().
     1080 */
     1081SUPR3DECL(int) SUPR3UnloadVMM(void);
     1082
     1083/**
     1084 * Get the physical address of the GIP.
     1085 *
     1086 * @returns VBox status code.
     1087 * @param   pHCPhys     Where to store the physical address of the GIP.
     1088 */
     1089SUPR3DECL(int) SUPR3GipGetPhys(PRTHCPHYS pHCPhys);
     1090
     1091/**
     1092 * Verifies the integrity of a file, and optionally opens it.
     1093 *
     1094 * The integrity check is for whether the file is suitable for loading into
     1095 * the hypervisor or VM process. The integrity check may include verifying
     1096 * the authenticode/elfsign/whatever signature of the file, which can take
     1097 * a little while.
     1098 *
     1099 * @returns VBox status code. On failure it will have printed a LogRel message.
     1100 *
     1101 * @param   pszFilename     The file.
     1102 * @param   pszWhat         For the LogRel on failure.
     1103 * @param   phFile          Where to store the handle to the opened file. This is optional, pass NULL
     1104 *                          if the file should not be opened.
     1105 * @deprecated Write a new one.
     1106 */
     1107SUPR3DECL(int) SUPR3HardenedVerifyFile(const char *pszFilename, const char *pszWhat, PRTFILE phFile);
     1108
     1109/**
     1110 * Verifies the integrity of a the current process, including the image
     1111 * location and that the invocation was absolute.
     1112 *
     1113 * This must currently be called after initializing the runtime.  The intended
     1114 * audience is set-uid-to-root applications, root services and similar.
     1115 *
     1116 * @returns VBox status code.  On failure
     1117 *          message.
     1118 * @param   pszArgv0        The first argument to main().
     1119 * @param   fInternal       Set this to @c true if this is an internal
     1120 *                          VirtualBox application.  Otherwise pass @c false.
     1121 * @param   pErrInfo        Where to return extended error information.
     1122 */
     1123SUPR3DECL(int) SUPR3HardenedVerifySelf(const char *pszArgv0, bool fInternal, PRTERRINFO pErrInfo);
     1124
     1125/**
     1126 * Verifies the integrity of an installation directory.
     1127 *
     1128 * The integrity check verifies that the directory cannot be tampered with by
     1129 * normal users on the system.  On Unix this translates to root ownership and
     1130 * no symbolic linking.
     1131 *
     1132 * @returns VBox status code. On failure a message will be stored in @a pszErr.
     1133 *
     1134 * @param   pszDirPath      The directory path.
     1135 * @param   fRecursive      Whether the check should be recursive or
     1136 *                          not.  When set, all sub-directores will be checked,
     1137 *                          including files (@a fCheckFiles is ignored).
     1138 * @param   fCheckFiles     Whether to apply the same basic integrity check to
     1139 *                          the files in the directory as the directory itself.
     1140 * @param   pErrInfo        Where to return extended error information.
     1141 *                          Optional.
     1142 */
     1143SUPR3DECL(int) SUPR3HardenedVerifyDir(const char *pszDirPath, bool fRecursive, bool fCheckFiles, PRTERRINFO pErrInfo);
     1144
     1145/**
     1146 * Verifies the integrity of a plug-in module.
     1147 *
     1148 * This is similar to SUPR3HardenedLdrLoad, except it does not load the module
     1149 * and that the module does not have to be shipped with VirtualBox.
     1150 *
     1151 * @returns VBox status code. On failure a message will be stored in @a pszErr.
     1152 *
     1153 * @param   pszFilename     The filename of the plug-in module (nothing can be
     1154 *                          omitted here).
     1155 * @param   pErrInfo        Where to return extended error information.
     1156 *                          Optional.
     1157 */
     1158SUPR3DECL(int) SUPR3HardenedVerifyPlugIn(const char *pszFilename, PRTERRINFO pErrInfo);
     1159
     1160/**
     1161 * Same as RTLdrLoad() but will verify the files it loads (hardened builds).
     1162 *
     1163 * Will add dll suffix if missing and try load the file.
     1164 *
     1165 * @returns iprt status code.
     1166 * @param   pszFilename     Image filename. This must have a path.
     1167 * @param   phLdrMod        Where to store the handle to the loaded module.
     1168 * @param   fFlags          See RTLDRLOAD_FLAGS_XXX.
     1169 * @param   pErrInfo        Where to return extended error information.
     1170 *                          Optional.
     1171 */
     1172SUPR3DECL(int) SUPR3HardenedLdrLoad(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo);
     1173
     1174/**
     1175 * Same as RTLdrLoadAppPriv() but it will verify the files it loads (hardened
     1176 * builds).
     1177 *
     1178 * Will add dll suffix to the file if missing, then look for it in the
     1179 * architecture dependent application directory.
     1180 *
     1181 * @returns iprt status code.
     1182 * @param   pszFilename     Image filename.
     1183 * @param   phLdrMod        Where to store the handle to the loaded module.
     1184 * @param   fFlags          See RTLDRLOAD_FLAGS_XXX.
     1185 * @param   pErrInfo        Where to return extended error information.
     1186 *                          Optional.
     1187 */
     1188SUPR3DECL(int) SUPR3HardenedLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo);
     1189
     1190/**
     1191 * Same as RTLdrLoad() but will verify the files it loads (hardened builds).
     1192 *
     1193 * This differs from SUPR3HardenedLdrLoad() in that it can load modules from
     1194 * extension packs and anything else safely installed on the system, provided
     1195 * they pass the hardening tests.
     1196 *
     1197 * @returns iprt status code.
     1198 * @param   pszFilename     The full path to the module, with extension.
     1199 * @param   phLdrMod        Where to store the handle to the loaded module.
     1200 * @param   pErrInfo        Where to return extended error information.
     1201 *                          Optional.
     1202 */
     1203SUPR3DECL(int) SUPR3HardenedLdrLoadPlugIn(const char *pszFilename, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo);
     1204
     1205/**
     1206 * Check if the host kernel can run in VMX root mode.
     1207 *
     1208 * @returns VINF_SUCCESS if supported, error code indicating why if not.
     1209 */
     1210SUPR3DECL(int) SUPR3QueryVTxSupported(void);
     1211
     1212/**
     1213 * Return VT-x/AMD-V capabilities.
     1214 *
     1215 * @returns VINF_SUCCESS if supported, error code indicating why if not.
     1216 * @param   pfCaps      Pointer to capability dword (out).
     1217 * @todo Intended for main, which means we need to relax the privilege requires
     1218 *       when accessing certain vboxdrv functions.
     1219 */
     1220SUPR3DECL(int) SUPR3QueryVTCaps(uint32_t *pfCaps);
     1221
     1222/**
     1223 * Open the tracer.
     1224 *
     1225 * @returns VBox status code.
     1226 * @param   uCookie         Cookie identifying the tracer we expect to talk to.
     1227 * @param   uArg            Tracer specific open argument.
     1228 */
     1229SUPR3DECL(int) SUPR3TracerOpen(uint32_t uCookie, uintptr_t uArg);
     1230
     1231/**
     1232 * Closes the tracer.
     1233 *
     1234 * @returns VBox status code.
     1235 */
     1236SUPR3DECL(int) SUPR3TracerClose(void);
     1237
     1238/**
     1239 * Perform an I/O request on the tracer.
     1240 *
     1241 * @returns VBox status.
     1242 * @param   uCmd                The tracer command.
     1243 * @param   uArg                The argument.
     1244 * @param   piRetVal            Where to store the tracer return value.
     1245 */
     1246SUPR3DECL(int) SUPR3TracerIoCtl(uintptr_t uCmd, uintptr_t uArg, int32_t *piRetVal);
     1247
     1248/**
     1249 * Registers the user module with the tracer.
     1250 *
     1251 * @returns VBox status code.
     1252 * @param   hModNative          Native module handle.  Pass ~(uintptr_t)0 if not
     1253 *                              at hand.
     1254 * @param   pszModule           The module name.
     1255 * @param   pVtgHdr             The VTG header.
     1256 * @param   uVtgHdrAddr         The address to which the VTG header is loaded
     1257 *                              in the relevant execution context.
     1258 * @param   fFlags              See SUP_TRACER_UMOD_FLAGS_XXX
     1259 */
     1260SUPR3DECL(int) SUPR3TracerRegisterModule(uintptr_t hModNative, const char *pszModule, struct VTGOBJHDR *pVtgHdr,
     1261                                         RTUINTPTR uVtgHdrAddr, uint32_t fFlags);
     1262
     1263/**
     1264 * Deregisters the user module.
     1265 *
     1266 * @returns VBox status code.
     1267 * @param   pVtgHdr             The VTG header.
     1268 */
     1269SUPR3DECL(int) SUPR3TracerDeregisterModule(struct VTGOBJHDR *pVtgHdr);
     1270
     1271/**
     1272 * Fire the probe.
     1273 *
     1274 * @param   pVtgProbeLoc        The probe location record.
     1275 * @param   uArg0               Raw probe argument 0.
     1276 * @param   uArg1               Raw probe argument 1.
     1277 * @param   uArg2               Raw probe argument 2.
     1278 * @param   uArg3               Raw probe argument 3.
     1279 * @param   uArg4               Raw probe argument 4.
     1280 */
     1281SUPDECL(void)  SUPTracerFireProbe(struct VTGPROBELOC *pVtgProbeLoc, uintptr_t uArg0, uintptr_t uArg1, uintptr_t uArg2,
     1282                                  uintptr_t uArg3, uintptr_t uArg4);
     1283/** @} */
     1284#endif /* IN_RING3 */
     1285
     1286/** @name User mode module flags (SUPR3TracerRegisterModule & SUP_IOCTL_TRACER_UMOD_REG).
     1287 * @{ */
     1288/** Executable image. */
     1289#define SUP_TRACER_UMOD_FLAGS_EXE           UINT32_C(1)
     1290/** Shared library (DLL, DYLIB, SO, etc). */
     1291#define SUP_TRACER_UMOD_FLAGS_SHARED        UINT32_C(2)
     1292/** Image type mask. */
     1293#define SUP_TRACER_UMOD_FLAGS_TYPE_MASK     UINT32_C(3)
     1294/** @} */
     1295
     1296
     1297#ifdef IN_RING0
     1298/** @defgroup   grp_sup_r0     SUP Host Context Ring-0 API
     1299 * @ingroup grp_sup
     1300 * @{
     1301 */
     1302
     1303/**
     1304 * Security objectype.
     1305 */
     1306typedef enum SUPDRVOBJTYPE
     1307{
     1308    /** The usual invalid object. */
     1309    SUPDRVOBJTYPE_INVALID = 0,
     1310    /** A Virtual Machine instance. */
     1311    SUPDRVOBJTYPE_VM,
     1312    /** Internal network. */
     1313    SUPDRVOBJTYPE_INTERNAL_NETWORK,
     1314    /** Internal network interface. */
     1315    SUPDRVOBJTYPE_INTERNAL_NETWORK_INTERFACE,
     1316    /** Single release event semaphore. */
     1317    SUPDRVOBJTYPE_SEM_EVENT,
     1318    /** Multiple release event semaphore. */
     1319    SUPDRVOBJTYPE_SEM_EVENT_MULTI,
     1320    /** Raw PCI device. */
     1321    SUPDRVOBJTYPE_RAW_PCI_DEVICE,
     1322    /** The first invalid object type in this end. */
     1323    SUPDRVOBJTYPE_END,
     1324    /** The usual 32-bit type size hack. */
     1325    SUPDRVOBJTYPE_32_BIT_HACK = 0x7ffffff
     1326} SUPDRVOBJTYPE;
     1327
     1328/**
     1329 * Object destructor callback.
     1330 * This is called for reference counted objectes when the count reaches 0.
     1331 *
     1332 * @param   pvObj       The object pointer.
     1333 * @param   pvUser1     The first user argument.
     1334 * @param   pvUser2     The second user argument.
     1335 */
     1336typedef DECLCALLBACK(void) FNSUPDRVDESTRUCTOR(void *pvObj, void *pvUser1, void *pvUser2);
     1337/** Pointer to a FNSUPDRVDESTRUCTOR(). */
     1338typedef FNSUPDRVDESTRUCTOR *PFNSUPDRVDESTRUCTOR;
     1339
     1340SUPR0DECL(void *) SUPR0ObjRegister(PSUPDRVSESSION pSession, SUPDRVOBJTYPE enmType, PFNSUPDRVDESTRUCTOR pfnDestructor, void *pvUser1, void *pvUser2);
     1341SUPR0DECL(int) SUPR0ObjAddRef(void *pvObj, PSUPDRVSESSION pSession);
     1342SUPR0DECL(int) SUPR0ObjAddRefEx(void *pvObj, PSUPDRVSESSION pSession, bool fNoBlocking);
     1343SUPR0DECL(int) SUPR0ObjRelease(void *pvObj, PSUPDRVSESSION pSession);
     1344SUPR0DECL(int) SUPR0ObjVerifyAccess(void *pvObj, PSUPDRVSESSION pSession, const char *pszObjName);
     1345
     1346SUPR0DECL(int) SUPR0LockMem(PSUPDRVSESSION pSession, RTR3PTR pvR3, uint32_t cPages, PRTHCPHYS paPages);
     1347SUPR0DECL(int) SUPR0UnlockMem(PSUPDRVSESSION pSession, RTR3PTR pvR3);
     1348SUPR0DECL(int) SUPR0ContAlloc(PSUPDRVSESSION pSession, uint32_t cPages, PRTR0PTR ppvR0, PRTR3PTR ppvR3, PRTHCPHYS pHCPhys);
     1349SUPR0DECL(int) SUPR0ContFree(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr);
     1350SUPR0DECL(int) SUPR0LowAlloc(PSUPDRVSESSION pSession, uint32_t cPages, PRTR0PTR ppvR0, PRTR3PTR ppvR3, PRTHCPHYS paPages);
     1351SUPR0DECL(int) SUPR0LowFree(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr);
     1352SUPR0DECL(int) SUPR0MemAlloc(PSUPDRVSESSION pSession, uint32_t cb, PRTR0PTR ppvR0, PRTR3PTR ppvR3);
     1353SUPR0DECL(int) SUPR0MemGetPhys(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr, PSUPPAGE paPages);
     1354SUPR0DECL(int) SUPR0MemFree(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr);
     1355SUPR0DECL(int) SUPR0PageAllocEx(PSUPDRVSESSION pSession, uint32_t cPages, uint32_t fFlags, PRTR3PTR ppvR3, PRTR0PTR ppvR0, PRTHCPHYS paPages);
     1356SUPR0DECL(int) SUPR0PageMapKernel(PSUPDRVSESSION pSession, RTR3PTR pvR3, uint32_t offSub, uint32_t cbSub, uint32_t fFlags, PRTR0PTR ppvR0);
     1357SUPR0DECL(int) SUPR0PageProtect(PSUPDRVSESSION pSession, RTR3PTR pvR3, RTR0PTR pvR0, uint32_t offSub, uint32_t cbSub, uint32_t fProt);
     1358SUPR0DECL(int) SUPR0PageFree(PSUPDRVSESSION pSession, RTR3PTR pvR3);
     1359SUPR0DECL(int) SUPR0GipMap(PSUPDRVSESSION pSession, PRTR3PTR ppGipR3, PRTHCPHYS pHCPhysGip);
     1360SUPR0DECL(int) SUPR0QueryVTCaps(PSUPDRVSESSION pSession, uint32_t *pfCaps);
     1361SUPR0DECL(int) SUPR0GipUnmap(PSUPDRVSESSION pSession);
     1362SUPR0DECL(int) SUPR0Printf(const char *pszFormat, ...);
     1363SUPR0DECL(SUPPAGINGMODE) SUPR0GetPagingMode(void);
     1364SUPR0DECL(int) SUPR0EnableVTx(bool fEnable);
     1365
     1366/** @name Absolute symbols
     1367 * Take the address of these, don't try call them.
     1368 * @{ */
     1369SUPR0DECL(void) SUPR0AbsIs64bit(void);
     1370SUPR0DECL(void) SUPR0Abs64bitKernelCS(void);
     1371SUPR0DECL(void) SUPR0Abs64bitKernelSS(void);
     1372SUPR0DECL(void) SUPR0Abs64bitKernelDS(void);
     1373SUPR0DECL(void) SUPR0AbsKernelCS(void);
     1374SUPR0DECL(void) SUPR0AbsKernelSS(void);
     1375SUPR0DECL(void) SUPR0AbsKernelDS(void);
     1376SUPR0DECL(void) SUPR0AbsKernelES(void);
     1377SUPR0DECL(void) SUPR0AbsKernelFS(void);
     1378SUPR0DECL(void) SUPR0AbsKernelGS(void);
     1379/** @} */
     1380
     1381/**
     1382 * Support driver component factory.
     1383 *
     1384 * Component factories are registered by drivers that provides services
     1385 * such as the host network interface filtering and access to the host
     1386 * TCP/IP stack.
     1387 *
     1388 * @remark Module dependencies and making sure that a component doesn't
     1389 *         get unloaded while in use, is the sole responsibility of the
     1390 *         driver/kext/whatever implementing the component.
     1391 */
     1392typedef struct SUPDRVFACTORY
     1393{
     1394    /** The (unique) name of the component factory. */
     1395    char szName[56];
     1396    /**
     1397     * Queries a factory interface.
     1398     *
     1399     * The factory interface is specific to each component and will be be
     1400     * found in the header(s) for the component alongside its UUID.
     1401     *
     1402     * @returns Pointer to the factory interfaces on success, NULL on failure.
     1403     *
     1404     * @param   pSupDrvFactory      Pointer to this structure.
     1405     * @param   pSession            The SUPDRV session making the query.
     1406     * @param   pszInterfaceUuid    The UUID of the factory interface.
     1407     */
     1408    DECLR0CALLBACKMEMBER(void *, pfnQueryFactoryInterface,(struct SUPDRVFACTORY const *pSupDrvFactory, PSUPDRVSESSION pSession, const char *pszInterfaceUuid));
     1409} SUPDRVFACTORY;
     1410/** Pointer to a support driver factory. */
     1411typedef SUPDRVFACTORY *PSUPDRVFACTORY;
     1412/** Pointer to a const support driver factory. */
     1413typedef SUPDRVFACTORY const *PCSUPDRVFACTORY;
     1414
     1415SUPR0DECL(int) SUPR0ComponentRegisterFactory(PSUPDRVSESSION pSession, PCSUPDRVFACTORY pFactory);
     1416SUPR0DECL(int) SUPR0ComponentDeregisterFactory(PSUPDRVSESSION pSession, PCSUPDRVFACTORY pFactory);
     1417SUPR0DECL(int) SUPR0ComponentQueryFactory(PSUPDRVSESSION pSession, const char *pszName, const char *pszInterfaceUuid, void **ppvFactoryIf);
     1418
     1419
     1420/** @name Tracing
     1421 * @{ */
     1422
     1423/**
     1424 * Tracer data associated with a provider.
     1425 */
     1426typedef union SUPDRVTRACERDATA
     1427{
     1428    /** Generic */
     1429    uint64_t                    au64[2];
     1430
     1431    /** DTrace data. */
     1432    struct
     1433    {
     1434        /** Provider ID. */
     1435        uintptr_t               idProvider;
     1436        /** The number of trace points provided. */
     1437        uint32_t volatile       cProvidedProbes;
     1438        /** Whether we've invalidated this bugger. */
     1439        bool                    fZombie;
     1440    } DTrace;
     1441} SUPDRVTRACERDATA;
     1442/** Pointer to the tracer data associated with a provider. */
     1443typedef SUPDRVTRACERDATA *PSUPDRVTRACERDATA;
     1444
     1445/**
     1446 * Probe location info for ring-0.
     1447 *
     1448 * Since we cannot trust user tracepoint modules, we need to duplicate the probe
     1449 * ID and enabled flag in ring-0.
     1450 */
     1451typedef struct SUPDRVPROBELOC
     1452{
     1453    /** The probe ID. */
     1454    uint32_t                idProbe;
     1455    /** Whether it's enabled or not. */
     1456    bool                    fEnabled;
     1457} SUPDRVPROBELOC;
     1458/** Pointer to a ring-0 probe location record. */
     1459typedef SUPDRVPROBELOC *PSUPDRVPROBELOC;
     1460
     1461/**
     1462 * Probe info for ring-0.
     1463 *
     1464 * Since we cannot trust user tracepoint modules, we need to duplicate the
     1465 * probe enable count.
     1466 */
     1467typedef struct SUPDRVPROBEINFO
     1468{
     1469    /** The number of times this probe has been enabled. */
     1470    uint32_t volatile           cEnabled;
     1471} SUPDRVPROBEINFO;
     1472/** Pointer to a ring-0 probe info record. */
     1473typedef SUPDRVPROBEINFO *PSUPDRVPROBEINFO;
     1474
     1475/**
     1476 * Support driver tracepoint provider core.
     1477 */
     1478typedef struct SUPDRVVDTPROVIDERCORE
     1479{
     1480    /** The tracer data member. */
     1481    SUPDRVTRACERDATA            TracerData;
     1482    /** Pointer to the provider name (a copy that's always available). */
     1483    const char                 *pszName;
     1484    /** Pointer to the module name (a copy that's always available). */
     1485    const char                 *pszModName;
     1486
     1487    /** The provider descriptor. */
     1488    struct VTGDESCPROVIDER     *pDesc;
     1489    /** The VTG header. */
     1490    struct VTGOBJHDR           *pHdr;
     1491
     1492    /** The size of the entries in the pvProbeLocsEn table. */
     1493    uint8_t                     cbProbeLocsEn;
     1494    /** The actual module bit count (corresponds to cbProbeLocsEn). */
     1495    uint8_t                     cBits;
     1496    /** Set if this is a Umod, otherwise clear.. */
     1497    bool                        fUmod;
     1498    /** Explicit alignment padding (paranoia). */
     1499    uint8_t                     abAlignment[ARCH_BITS == 32 ? 1 : 5];
     1500
     1501    /** The probe locations used for descriptive purposes. */
     1502    struct VTGPROBELOC const   *paProbeLocsRO;
     1503    /** Pointer to the probe location array where the enable flag needs
     1504     * flipping. For kernel providers, this will always be SUPDRVPROBELOC,
     1505     * while user providers can either be 32-bit or 64-bit.  Use
     1506     * cbProbeLocsEn to calculate the address of an entry. */
     1507    void                       *pvProbeLocsEn;
     1508    /** Pointer to the probe array containing the enabled counts. */
     1509    uint32_t                   *pacProbeEnabled;
     1510
     1511    /** The ring-0 probe location info for user tracepoint modules.
     1512     * This is NULL if fUmod is false. */
     1513    PSUPDRVPROBELOC             paR0ProbeLocs;
     1514    /** The ring-0 probe info for user tracepoint modules.
     1515     * This is NULL if fUmod is false. */
     1516    PSUPDRVPROBEINFO            paR0Probes;
     1517
     1518} SUPDRVVDTPROVIDERCORE;
     1519/** Pointer to a tracepoint provider core structure. */
     1520typedef SUPDRVVDTPROVIDERCORE *PSUPDRVVDTPROVIDERCORE;
    14601521
    14611522/** Pointer to a tracer registration record. */
  • trunk/src/VBox/HostDrivers/Support/Makefile.kmk

    r41092 r41117  
    8787        SUPLib.cpp \
    8888        SUPLibSem.cpp \
     89        SUPLibTracerA.asm \
    8990        SUPR3HardenedIPRT.cpp \
    9091        SUPR3HardenedVerify.cpp \
  • trunk/src/VBox/HostDrivers/Support/SUPDrv.c

    r41068 r41117  
    697697                /*pSession->uTracerData       = 0;*/
    698698                pSession->hTracerCaller     = NIL_RTNATIVETHREAD;
     699                RTListInit(&pSession->TpProviders);
     700                /*pSession->cTpProviders      = 0;*/
     701                /*pSession->cTpProbesFiring   = 0;*/
     702                RTListInit(&pSession->TpUmods);
     703                /*RT_ZERO(pSession->apTpLookupTable);*/
    699704
    700705                VBOXDRV_SESSION_CREATE(pSession, fUser);
     
    17941799            PSUPTRACERUMODREG pReq = (PSUPTRACERUMODREG)pReqHdr;
    17951800            REQ_CHECK_SIZES(SUP_IOCTL_TRACER_UMOD_REG);
     1801            if (!RTStrEnd(pReq->u.In.szName, sizeof(pReq->u.In.szName)))
     1802                return VERR_INVALID_PARAMETER;
    17961803
    17971804            /* execute */
    1798             pReqHdr->rc = supdrvIOCtl_TracerUmodRegister(pDevExt, pSession, pReq->u.In.pVtgHdr, pReq->u.In.szName, pReq->u.In.fFlags);
     1805            pReqHdr->rc = supdrvIOCtl_TracerUmodRegister(pDevExt, pSession,
     1806                                                         pReq->u.In.R3PtrVtgHdr, pReq->u.In.uVtgHdrAddr,
     1807                                                         pReq->u.In.R3PtrStrTab, pReq->u.In.cbStrTab,
     1808                                                         pReq->u.In.szName, pReq->u.In.fFlags);
    17991809            return 0;
    18001810        }
     
    18081818            /* execute */
    18091819            pReqHdr->rc = supdrvIOCtl_TracerUmodDeregister(pDevExt, pSession, pReq->u.In.pVtgHdr);
     1820            return 0;
     1821        }
     1822
     1823        case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_TRACER_UMOD_FIRE_PROBE):
     1824        {
     1825            /* validate */
     1826            PSUPTRACERUMODFIREPROBE pReq = (PSUPTRACERUMODFIREPROBE)pReqHdr;
     1827            REQ_CHECK_SIZES(SUP_IOCTL_TRACER_UMOD_FIRE_PROBE);
     1828
     1829            supdrvIOCtl_TracerUmodProbeFire(pDevExt, pSession, &pReq->u.In);
     1830            pReqHdr->rc = VINF_SUCCESS;
    18101831            return 0;
    18111832        }
  • trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h

    r40982 r41117  
    3232 */
    3333#include <iprt/types.h>
     34#include <VBox/sup.h>
    3435
    3536/*
     
    193194 *          - Remove RTSpinlockReleaseNoInts.
    194195 */
    195 #define SUPDRV_IOC_VERSION                              0x001a0001
     196#define SUPDRV_IOC_VERSION                              0x001a0002
    196197
    197198/** SUP_IOCTL_COOKIE. */
     
    12661267        struct
    12671268        {
    1268             /** Pointer to the VTG header. */
    1269             RTR3PTR         pVtgHdr;
     1269            /** The address at which the VTG header actually resides.
     1270             * This will differ from R3PtrVtgHdr for raw-mode context
     1271             * modules. */
     1272            RTUINTPTR       uVtgHdrAddr;
     1273            /** The ring-3 pointer of the VTG header. */
     1274            RTR3PTR         R3PtrVtgHdr;
     1275            /** The ring-3 pointer of the probe location string table. */
     1276            RTR3PTR         R3PtrStrTab;
     1277            /** The size of the string table. */
     1278            uint32_t        cbStrTab;
    12701279            /** Future flags, MBZ.  */
    12711280            uint32_t        fFlags;
     
    13031312
    13041313
     1314/** @name SUP_IOCTL_TRACER_UMOD_FIRE_PROBE
     1315 * Fire a probe in a user tracepoint module.
     1316 *
     1317 * @{
     1318 */
     1319#define SUP_IOCTL_TRACER_UMOD_FIRE_PROBE            SUP_CTL_CODE_SIZE(33, SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE)
     1320#define SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE       sizeof(SUPTRACERUMODFIREPROBE)
     1321#define SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE_IN    sizeof(SUPTRACERUMODFIREPROBE)
     1322#define SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE_OUT   sizeof(SUPREQHDR)
     1323typedef struct SUPTRACERUMODFIREPROBE
     1324{
     1325    /** The header. */
     1326    SUPREQHDR               Hdr;
     1327    union
     1328    {
     1329        SUPDRVTRACERUSRCTX  In;
     1330    } u;
     1331} SUPTRACERUMODFIREPROBE, *PSUPTRACERUMODFIREPROBE;
     1332/** @} */
     1333
     1334
    13051335#pragma pack()                          /* paranoia */
    13061336
  • trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h

    r41067 r41117  
    440440    /** The thread currently actively talking to the tracer. (One at the time!) */
    441441    RTNATIVETHREAD                  hTracerCaller;
     442    /** List of tracepoint providers associated with the session
     443     * (SUPDRVTPPROVIDER). */
     444    RTLISTANCHOR                    TpProviders;
     445    /** The number of providers in TpProviders. */
     446    uint32_t                        cTpProviders;
     447    /** The number of threads active in supdrvIOCtl_TracerUmodProbeFire or
     448     *  SUPR0TracerUmodProbeFire. */
     449    uint32_t volatile               cTpProbesFiring;
     450    /** User tracepoint modules (PSUPDRVTRACKERUMOD). */
     451    RTLISTANCHOR                    TpUmods;
     452    /** The user tracepoint module lookup table. */
     453    struct SUPDRVTRACERUMOD        *apTpLookupTable[32];
    442454#ifndef SUPDRV_AGNOSTIC
    443455# if defined(RT_OS_DARWIN)
     
    559571    /** The number of session having opened the tracer currently. */
    560572    uint32_t                        cTracerOpens;
     573    /** The number of threads currently calling into the tracer. */
     574    uint32_t volatile               cTracerCallers;
    561575    /** Set if the tracer is being unloaded. */
    562576    bool                            fTracerUnloading;
     577    /** Hash table for user tracer modules (SUPDRVVTGCOPY). */
     578    RTLISTANCHOR                    aTrackerUmodHash[128];
    563579
    564580    /*
     
    665681void VBOXCALL   supdrvTracerModuleUnloading(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage);
    666682void VBOXCALL   supdrvTracerCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession);
     683int  VBOXCALL   supdrvIOCtl_TracerUmodRegister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession,
     684                                               RTR3PTR R3PtrVtgHdr, RTUINTPTR uVtgHdrAddr,
     685                                               RTR3PTR R3PtrStrTab, uint32_t cbStrTab,
     686                                               const char *pszModName, uint32_t fFlags);
     687int  VBOXCALL   supdrvIOCtl_TracerUmodDeregister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR R3PtrVtgHdr);
     688void  VBOXCALL  supdrvIOCtl_TracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx);
    667689int  VBOXCALL   supdrvIOCtl_TracerOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uint32_t uCookie, uintptr_t uArg);
    668690int  VBOXCALL   supdrvIOCtl_TracerClose(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession);
     
    671693DECLASM(void)   supdrvTracerProbeFireStub(void);
    672694
    673 int  VBOXCALL   supdrvIOCtl_TracerUmodRegister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR pVtgHdr, const char *pszModName, uint32_t fFlags);
    674 int  VBOXCALL   supdrvIOCtl_TracerUmodDeregister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR pVtgHdr);
    675 void  VBOXCALL  supdrvIOCtl_TracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PCSUPDRVTRACERUSRCTX pCtx);
    676 
    677695#ifdef VBOX_WITH_NATIVE_DTRACE
    678696const SUPDRVTRACERREG * VBOXCALL supdrvDTraceInit(void);
  • trunk/src/VBox/HostDrivers/Support/SUPDrvTracer.cpp

    r40981 r41117  
    4343#include <iprt/semaphore.h>
    4444#include <iprt/thread.h>
     45#include <iprt/param.h>
     46#include <iprt/uuid.h>
    4547
    4648
     
    4850*   Structures and Typedefs                                                    *
    4951*******************************************************************************/
     52/** Pointer to a user tracer module registration record. */
     53typedef struct SUPDRVTRACERUMOD *PSUPDRVTRACERUMOD;
     54
    5055/**
    5156 * Data for a tracepoint provider.
     
    5560    /** The entry in the provider list for this image. */
    5661    RTLISTNODE              ListEntry;
     62    /** The entry in the per session provider list for this image. */
     63    RTLISTNODE              SessionListEntry;
    5764
    5865    /** The core structure. */
     
    6572     * SUPR0VtgRegisterDrv.  NULL if pImage is set. */
    6673    PSUPDRVSESSION          pSession;
     74    /** The user tracepoint module associated with this provider.  NULL if
     75     *  pImage is set. */
     76    PSUPDRVTRACERUMOD       pUmod;
    6777
    6878    /** Used to indicate that we've called pfnProviderDeregistered already and it
     
    8393
    8494
     95/**
     96 * User tracer module VTG data copy.
     97 */
     98typedef struct SUPDRVVTGCOPY
     99{
     100    /** Magic (SUDPRVVTGCOPY_MAGIC).  */
     101    uint32_t    u32Magic;
     102    /** Refernece counter (we expect to share a lot of these). */
     103    uint32_t    cRefs;
     104    /** The size of the  */
     105    uint32_t    cbStrTab;
     106    /** Image type flags. */
     107    uint32_t    fFlags;
     108    /** Hash list entry (SUPDRVDEVEXT::aTrackerUmodHash).  */
     109    RTLISTNODE  ListEntry;
     110    /** The VTG object header.
     111     * The rest of the data follows immediately afterwards.  First the object,
     112     * then the probe locations and finally the probe location string table. All
     113     * pointers are fixed up to point within this data. */
     114    VTGOBJHDR   Hdr;
     115} SUPDRVVTGCOPY;
     116/** Pointer to a VTG object copy. */
     117typedef SUPDRVVTGCOPY *PSUPDRVVTGCOPY;
     118/** Magic value for SUPDRVVTGCOPY. */
     119#define SUDPRVVTGCOPY_MAGIC UINT32_C(0x00080386)
     120
     121
     122/**
     123 * User tracer module registration record.
     124 */
     125typedef struct SUPDRVTRACERUMOD
     126{
     127    /** Magic (SUPDRVTRACERUMOD_MAGIC).  */
     128    uint32_t                u32Magic;
     129    /** List entry.  This is anchored in SUPDRVSESSION::UmodList. */
     130    RTLISTNODE              ListEntry;
     131    /** The address of the ring-3 VTG header. */
     132    RTR3PTR                 R3PtrVtgHdr;
     133    /** Pointer to the ring-0 copy of the VTG data. */
     134    PSUPDRVVTGCOPY          pVtgCopy;
     135    /** The memory object that locks down the user memory. */
     136    RTR0MEMOBJ              hMemObjLock;
     137    /** The memory object that maps the locked memory into kernel space. */
     138    RTR0MEMOBJ              hMemObjMap;
     139    /** Pointer to the probe enabled-count array within the mapping. */
     140    uint32_t               *pacProbeEnabled;
     141    /** Pointer to the probe location array within the mapping. */
     142    void                   *pvProbeLocs;
     143    /** The address of the ring-3 probe locations. */
     144    RTR3PTR                 R3PtrProbeLocs;
     145    /** The lookup table index. */
     146    uint8_t                 iLookupTable;
     147    /** The module bit count. */
     148    uint8_t                 cBits;
     149    /** The size of a probe location record. */
     150    uint8_t                 cbProbeLoc;
     151    /** The number of probe locations. */
     152    uint32_t                cProbeLocs;
     153    /** Ring-0 probe location info. */
     154    SUPDRVPROBELOC          aProbeLocs[1];
     155} SUPDRVTRACERUMOD;
     156/** Magic value for SUPDRVVTGCOPY. */
     157#define SUPDRVTRACERUMOD_MAGIC UINT32_C(0x00080486)
     158
     159
    85160/*******************************************************************************
    86161*   Defined Constants And Macros                                               *
     
    99174/** The address of the current probe fire routine for kernel mode. */
    100175PFNRT       g_pfnSupdrvProbeFireKernel = supdrvTracerProbeFireStub;
     176
     177
     178/*******************************************************************************
     179*   Internal Functions                                                         *
     180*******************************************************************************/
     181static void supdrvVtgReleaseObjectCopy(PSUPDRVDEVEXT pDevExt, PSUPDRVVTGCOPY pThis);
    101182
    102183
     
    136217
    137218
    138 /**
    139  * Validates the VTG data.
    140  *
    141  * @returns VBox status code.
    142  * @param   pVtgHdr             The VTG object header of the data to validate.
    143  * @param   cbVtgObj            The size of the VTG object.
    144  * @param   pbImage             The image base. For validating the probe
    145  *                              locations.
    146  * @param   cbImage             The image size to go with @a pbImage.
    147  */
    148 static int supdrvVtgValidate(PVTGOBJHDR pVtgHdr, size_t cbVtgObj, const uint8_t *pbImage, size_t cbImage)
    149 {
    150     uintptr_t   cbTmp;
    151     uintptr_t   offTmp;
    152     uintptr_t   i;
    153     uintptr_t   cProviders;
    154     int         rc;
    155 
    156     if (!pbImage || !cbImage)
    157     {
    158         pbImage = NULL;
    159         cbImage = 0;
    160     }
    161 
    162 #define MY_VALIDATE_PTR(p, cb, cMin, cMax, cbUnit, rcBase) \
    163     do { \
    164         if (   (cb) >= cbVtgObj \
    165             || (uintptr_t)(p) - (uintptr_t)pVtgHdr > cbVtgObj - (cb) ) \
    166         { \
    167             SUPR0Printf("supdrvVtgValidate: " #rcBase "_TOO_PTR - p=%p cb=%#zx pVtgHdr=%p cbVtgHdr=%#zu line=%u %s\n", \
    168                         p, (size_t)(cb), pVtgHdr, cbVtgObj, __LINE__, #p); \
    169             return rcBase ## _PTR; \
    170         } \
    171         if ((cb) <  (cMin) * (cbUnit)) \
    172         { \
    173             SUPR0Printf("supdrvVtgValidate: " #rcBase "_TOO_FEW - cb=%#zx cMin=%#zx cbUnit=%#zx line=%u %s\n", \
    174                         (size_t)(cb), (size_t)(cMin), (size_t)cbUnit, __LINE__, #p); \
    175             return rcBase ## _TOO_FEW; \
    176         } \
    177         if ((cb) >= (cMax) * (cbUnit)) \
    178         { \
    179             SUPR0Printf("supdrvVtgValidate: " #rcBase "_TOO_MUCH - cb=%#zx cMax=%#zx cbUnit=%#zx line=%u %s\n", \
    180                         (size_t)(cb), (size_t)(cMax), (size_t)cbUnit, __LINE__, #p); \
    181             return rcBase ## _TOO_MUCH; \
    182         } \
    183         if ((cb) / (cbUnit) * (cbUnit) != (cb)) \
    184         { \
    185             SUPR0Printf("supdrvVtgValidate: " #rcBase "_NOT_MULTIPLE - cb=%#zx cbUnit=%#zx line=%u %s\n", \
    186                         (size_t)(cb), (size_t)cbUnit, __LINE__, #p); \
    187             return rcBase ## _NOT_MULTIPLE; \
    188         } \
    189     } while (0)
     219/** Used by the validation code below. */
     220#define MY_CHECK_RET(a_Expr, a_rc) \
     221    MY_CHECK_MSG_RET(a_Expr, ("%s: Validation failed on line " RT_XSTR(__LINE__) ": " #a_Expr "\n", __FUNCTION__), a_rc)
     222
     223/** Used by the validation code below. */
     224#define MY_CHECK_MSG_RET(a_Expr, a_PrintfArgs, a_rc) \
     225    do { if (RT_UNLIKELY(!(a_Expr))) { SUPR0Printf a_PrintfArgs; return (a_rc); } } while (0)
     226
     227/** Used by the validation code below. */
    190228#define MY_WITHIN_IMAGE(p, rc) \
    191229    do { \
     
    202240            return (rc); \
    203241    } while (0)
    204 #define MY_VALIDATE_STR(offStrTab) \
     242
     243
     244/**
     245 * Validates the VTG object header.
     246 *
     247 * @returns VBox status code.
     248 * @param   pVtgHdr             The header.
     249 * @param   uVtgHdrAddr         The address where the header is actually
     250 *                              loaded.
     251 * @param   cbVtgObj            The alleged size of the header.
     252 * @param   pbImage             The image base, if available.
     253 * @param   cbImage             The image size, if available.
     254 * @param   fUmod               Whether this is a user module.
     255 */
     256static int supdrvVtgValidateHdr(PVTGOBJHDR pVtgHdr, RTUINTPTR uVtgHdrAddr, const uint8_t *pbImage, size_t cbImage, bool fUmod)
     257{
     258    struct VTGAREAS
     259    {
     260        uint32_t off;
     261        uint32_t cb;
     262    } const        *paAreas;
     263    unsigned        cAreas;
     264    unsigned        i;
     265    uint32_t        cbVtgObj;
     266    uint32_t        off;
     267
     268#define MY_VALIDATE_SIZE(cb, cMin, cMax, cbUnit, rcBase) \
    205269    do { \
    206         if ((offStrTab) >= pVtgHdr->cbStrTab) \
     270        if ((cb) <  (cMin) * (cbUnit)) \
     271        { \
     272            SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_TOO_FEW - cb=%#zx cMin=%#zx cbUnit=%#zx line=%u %s\n", \
     273                        (size_t)(cb), (size_t)(cMin), (size_t)cbUnit, __LINE__, #cb); \
     274            return rcBase ## _TOO_FEW; \
     275        } \
     276        if ((cb) >= (cMax) * (cbUnit)) \
     277        { \
     278            SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_TOO_MUCH - cb=%#zx cMax=%#zx cbUnit=%#zx line=%u %s\n", \
     279                        (size_t)(cb), (size_t)(cMax), (size_t)cbUnit, __LINE__, #cb); \
     280            return rcBase ## _TOO_MUCH; \
     281        } \
     282        if ((cb) / (cbUnit) * (cbUnit) != (cb)) \
     283        { \
     284            SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_NOT_MULTIPLE - cb=%#zx cbUnit=%#zx line=%u %s\n", \
     285                        (size_t)(cb), (size_t)cbUnit, __LINE__, #cb); \
     286            return rcBase ## _NOT_MULTIPLE; \
     287        } \
     288    } while (0)
     289
     290#define MY_VALIDATE_OFF(off, cb, cMin, cMax, cbUnit, cbAlign, rcBase) \
     291    do { \
     292        if (   (cb) >= cbVtgObj \
     293            || off > cbVtgObj - (cb) ) \
     294        { \
     295            SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_OFF - off=%#x cb=%#x pVtgHdr=%p cbVtgHdr=%#zx line=%u %s\n", \
     296                        (off), (cb), pVtgHdr, cbVtgObj, __LINE__, #off); \
     297            return rcBase ## _OFF; \
     298        } \
     299        if (RT_ALIGN(off, cbAlign) != (off)) \
     300        { \
     301            SUPR0Printf("supdrvVtgValidateHdr: " #rcBase "_OFF - off=%#x align=%#zx line=%u %s\n", \
     302                        (off), (size_t)(cbAlign), __LINE__, #off); \
     303            return rcBase ## _OFF; \
     304        } \
     305        MY_VALIDATE_SIZE(cb, cMin, cMax, cbUnit, rcBase); \
     306    } while (0)
     307
     308    /*
     309     * Make sure both pbImage and cbImage are NULL/0 if one if of them is.
     310     */
     311    if (!pbImage || !cbImage)
     312    {
     313        pbImage = NULL;
     314        cbImage = 0;
     315        cbVtgObj = pVtgHdr->cbObj;
     316    }
     317    else
     318    {
     319        MY_WITHIN_IMAGE(pVtgHdr, VERR_SUPDRV_VTG_BAD_HDR_PTR);
     320        cbVtgObj = pVtgHdr->cbObj;
     321        MY_WITHIN_IMAGE((uint8_t *)pVtgHdr + cbVtgObj - 1, VERR_SUPDRV_VTG_BAD_HDR_PTR);
     322    }
     323
     324    if (cbVtgObj > _1M)
     325    {
     326        SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_TRACER_TOO_LARGE - cbVtgObj=%#x\n", cbVtgObj);
     327        return VERR_SUPDRV_TRACER_TOO_LARGE;
     328    }
     329
     330    /*
     331     * Set the probe location array offset and size members.
     332     */
     333    if (!pVtgHdr->offProbeLocs)
     334    {
     335        uint64_t u64Tmp = pVtgHdr->uProbeLocsEnd.u64 - pVtgHdr->uProbeLocs.u64;
     336        if (u64Tmp >= UINT32_MAX)
     337            return VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH;
     338        pVtgHdr->cbProbeLocs  = (uint32_t)u64Tmp;
     339
     340        u64Tmp = pVtgHdr->uProbeLocs.u64 - uVtgHdrAddr;
     341        if ((int64_t)u64Tmp != (int32_t)u64Tmp)
     342            return VERR_SUPDRV_VTG_BAD_HDR_PTR;
     343        pVtgHdr->offProbeLocs = (int32_t)u64Tmp;
     344    }
     345
     346    /*
     347     * The non-area description fields.
     348     */
     349    if (memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)))
     350        return VERR_SUPDRV_VTG_MAGIC;
     351    if (   pVtgHdr->cBits != ARCH_BITS
     352        && (   !fUmod
     353            || (   pVtgHdr->cBits != 32
     354                && pVtgHdr->cBits != 64)) )
     355        return VERR_SUPDRV_VTG_BITS;
     356    if (   pVtgHdr->au32Reserved1[0]
     357        || pVtgHdr->au32Reserved1[1]
     358        || pVtgHdr->au32Reserved1[2]
     359        || pVtgHdr->au32Reserved1[3])
     360        return VERR_SUPDRV_VTG_BAD_HDR_MISC;
     361    if (RTUuidIsNull(&pVtgHdr->Uuid))
     362        return VERR_SUPDRV_VTG_BAD_HDR_MISC;
     363
     364    /*
     365     * Check the individual area descriptors.
     366     */
     367    MY_VALIDATE_OFF(pVtgHdr->offStrTab,          pVtgHdr->cbStrTab,       4,   _1M, sizeof(char),            sizeof(uint8_t),  VERR_SUPDRV_VTG_BAD_HDR);
     368    MY_VALIDATE_OFF(pVtgHdr->offArgLists,        pVtgHdr->cbArgLists,     1,  _32K, sizeof(uint32_t),        sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
     369    MY_VALIDATE_OFF(pVtgHdr->offProbes,          pVtgHdr->cbProbes,       1,  _32K, sizeof(VTGDESCPROBE),    sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
     370    MY_VALIDATE_OFF(pVtgHdr->offProviders,       pVtgHdr->cbProviders,    1,    16, sizeof(VTGDESCPROVIDER), sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
     371    MY_VALIDATE_OFF(pVtgHdr->offProbeEnabled,    pVtgHdr->cbProbeEnabled, 1,  _32K, sizeof(uint32_t),        sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_HDR);
     372    if (!fUmod)
     373    {
     374        MY_WITHIN_IMAGE(pVtgHdr->uProbeLocs.p,    VERR_SUPDRV_VTG_BAD_HDR_PTR);
     375        MY_WITHIN_IMAGE(pVtgHdr->uProbeLocsEnd.p, VERR_SUPDRV_VTG_BAD_HDR_PTR);
     376        MY_VALIDATE_SIZE(                        pVtgHdr->cbProbeLocs,    1, _128K, sizeof(VTGPROBELOC),     VERR_SUPDRV_VTG_BAD_HDR);
     377    }
     378    else
     379    {
     380        if (pVtgHdr->cBits == 32)
     381            MY_VALIDATE_SIZE(                   pVtgHdr->cbProbeLocs,    1, _8K,   sizeof(VTGPROBELOC32),    VERR_SUPDRV_VTG_BAD_HDR);
     382        else
     383            MY_VALIDATE_SIZE(                   pVtgHdr->cbProbeLocs,    1, _8K,   sizeof(VTGPROBELOC64),    VERR_SUPDRV_VTG_BAD_HDR);
     384        /* Will check later that offProbeLocs are following closely on the
     385           enable count array, so no need to validate the offset here. */
     386    }
     387
     388    /*
     389     * Some additional consistency checks.
     390     */
     391    if (   pVtgHdr->uProbeLocsEnd.u64 - pVtgHdr->uProbeLocs.u64 != pVtgHdr->cbProbeLocs
     392        || (int64_t)(pVtgHdr->uProbeLocs.u64 - uVtgHdrAddr)     != pVtgHdr->offProbeLocs)
     393    {
     394        SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - uProbeLocs=%#llx uProbeLocsEnd=%#llx offProbeLocs=%#llx cbProbeLocs=%#x uVtgHdrAddr=%RTptr\n",
     395                    pVtgHdr->uProbeLocs.u64, pVtgHdr->uProbeLocsEnd.u64, pVtgHdr->offProbeLocs, pVtgHdr->cbProbeLocs, uVtgHdrAddr);
     396        return VERR_SUPDRV_VTG_BAD_HDR_MISC;
     397    }
     398
     399    if (pVtgHdr->cbProbes / sizeof(VTGDESCPROBE) != pVtgHdr->cbProbeEnabled / sizeof(uint32_t))
     400    {
     401        SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - cbProbeEnabled=%#zx cbProbes=%#zx\n",
     402                    pVtgHdr->cbProbeEnabled, pVtgHdr->cbProbes);
     403        return VERR_SUPDRV_VTG_BAD_HDR_MISC;
     404    }
     405
     406    /*
     407     * Check that there are no overlapping areas.  This is a little bit ugly...
     408     */
     409    paAreas = (struct VTGAREAS const *)&pVtgHdr->offStrTab;
     410    cAreas  = pVtgHdr->offProbeLocs >= 0 ? 6 : 5;
     411    off     = sizeof(VTGOBJHDR);
     412    for (i = 0; i < cAreas; i++)
     413    {
     414        if (paAreas[i].off < off)
     415        {
     416            SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - overlapping areas %d and %d\n", i, i-1);
     417            return VERR_SUPDRV_VTG_BAD_HDR_MISC;
     418        }
     419        off = paAreas[i].off + paAreas[i].cb;
     420    }
     421    if (   pVtgHdr->offProbeLocs > 0
     422        && (uint32_t)-pVtgHdr->offProbeLocs < pVtgHdr->cbProbeLocs)
     423    {
     424        SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - probe locations overlaps the header\n");
     425        return VERR_SUPDRV_VTG_BAD_HDR_MISC;
     426    }
     427
     428    /*
     429     * Check that the object size is correct.
     430     */
     431    if (pVtgHdr->cbObj != pVtgHdr->offProbeEnabled + pVtgHdr->cbProbeEnabled)
     432    {
     433        SUPR0Printf("supdrvVtgValidateHdr: VERR_SUPDRV_VTG_BAD_HDR_MISC - bad header size %#x, expected %#x\n",
     434                    pVtgHdr->cbObj, pVtgHdr->offProbeEnabled + pVtgHdr->cbProbeEnabled);
     435        return VERR_SUPDRV_VTG_BAD_HDR_MISC;
     436    }
     437
     438
     439    return VINF_SUCCESS;
     440#undef MY_VALIDATE_OFF
     441#undef MY_VALIDATE_SIZE
     442}
     443
     444
     445/**
     446 * Validates the VTG data.
     447 *
     448 * @returns VBox status code.
     449 * @param   pVtgHdr             The VTG object header of the data to validate.
     450 * @param   uVtgHdrAddr         The address where the header is actually
     451 *                              loaded.
     452 * @param   pbImage             The image base. For validating the probe
     453 *                              locations.
     454 * @param   cbImage             The image size to go with @a pbImage.
     455 * @param   fUmod               Whether this is a user module.
     456 */
     457static int supdrvVtgValidate(PVTGOBJHDR pVtgHdr, RTUINTPTR uVtgHdrAddr, const uint8_t *pbImage, size_t cbImage, bool fUmod)
     458{
     459    uintptr_t   offTmp;
     460    uintptr_t   i;
     461    uintptr_t   cProviders;
     462    int         rc;
     463
     464    if (!pbImage || !cbImage)
     465    {
     466        pbImage = NULL;
     467        cbImage = 0;
     468    }
     469
     470#define MY_VALIDATE_STR(a_offStrTab) \
     471    do { \
     472        if ((a_offStrTab) >= pVtgHdr->cbStrTab) \
    207473            return VERR_SUPDRV_VTG_STRTAB_OFF; \
    208         rc = supdrvVtgValidateString(pVtgHdr->pachStrTab + (offStrTab)); \
     474        rc = supdrvVtgValidateString((char *)pVtgHdr + pVtgHdr->offStrTab + (a_offStrTab)); \
    209475        if (rc != VINF_SUCCESS) \
    210476            return rc; \
     
    223489     * The header.
    224490     */
    225     if (memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)))
    226         return VERR_SUPDRV_VTG_MAGIC;
    227     if (pVtgHdr->cBits != ARCH_BITS)
    228         return VERR_SUPDRV_VTG_BITS;
    229     if (pVtgHdr->u32Reserved0)
    230         return VERR_SUPDRV_VTG_BAD_HDR;
    231 
    232     MY_VALIDATE_PTR(pVtgHdr->paProviders,       pVtgHdr->cbProviders,    1,    16, sizeof(VTGDESCPROVIDER), VERR_SUPDRV_VTG_BAD_HDR);
    233     MY_VALIDATE_PTR(pVtgHdr->paProbes,          pVtgHdr->cbProbes,       1,  _32K, sizeof(VTGDESCPROBE),    VERR_SUPDRV_VTG_BAD_HDR);
    234     MY_VALIDATE_PTR(pVtgHdr->pafProbeEnabled,   pVtgHdr->cbProbeEnabled, 1,  _32K, sizeof(bool),            VERR_SUPDRV_VTG_BAD_HDR);
    235     MY_VALIDATE_PTR(pVtgHdr->pachStrTab,        pVtgHdr->cbStrTab,       4,   _1M, sizeof(char),            VERR_SUPDRV_VTG_BAD_HDR);
    236     MY_VALIDATE_PTR(pVtgHdr->paArgLists,        pVtgHdr->cbArgLists,     1,  _32K, sizeof(uint32_t),        VERR_SUPDRV_VTG_BAD_HDR);
    237 
    238     MY_WITHIN_IMAGE(pVtgHdr->paProbLocs,    VERR_SUPDRV_VTG_BAD_HDR_PTR);
    239     MY_WITHIN_IMAGE(pVtgHdr->paProbLocsEnd, VERR_SUPDRV_VTG_BAD_HDR_PTR);
    240     if ((uintptr_t)pVtgHdr->paProbLocs > (uintptr_t)pVtgHdr->paProbLocsEnd)
    241     {
    242         SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_PTR - paProbeLocs=%p > paProbLocsEnd=%p\n",
    243                     pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd);
    244         return VERR_SUPDRV_VTG_BAD_HDR_PTR;
    245     }
    246     cbTmp = (uintptr_t)pVtgHdr->paProbLocsEnd - (uintptr_t)pVtgHdr->paProbLocs;
    247     if (cbTmp < sizeof(VTGPROBELOC))
    248     {
    249         SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_TOO_FEW - cbTmp=%#zx paProbeLocs=%p paProbLocsEnd=%p\n",
    250                     cbTmp, pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd);
    251         return VERR_SUPDRV_VTG_BAD_HDR_TOO_FEW;
    252     }
    253     if (cbTmp >= _128K * sizeof(VTGPROBELOC))
    254     {
    255         SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH - cbTmp=%#zx paProbeLocs=%p paProbLocsEnd=%p\n",
    256                     cbTmp, pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd);
    257         return VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH;
    258     }
    259     if (cbTmp / sizeof(VTGPROBELOC) * sizeof(VTGPROBELOC) != cbTmp)
    260     {
    261         SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR_NOT_MULTIPLE - cbTmp=%#zx cbUnit=%#zx paProbeLocs=%p paProbLocsEnd=%p\n",
    262                     cbTmp, sizeof(VTGPROBELOC), pVtgHdr->paProbLocs, pVtgHdr->paProbLocsEnd);
    263         return VERR_SUPDRV_VTG_BAD_HDR_NOT_MULTIPLE;
    264     }
    265 
    266     if (pVtgHdr->cbProbes / sizeof(VTGDESCPROBE) != pVtgHdr->cbProbeEnabled)
    267     {
    268         SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_VTG_BAD_HDR - cbProbeEnabled=%#zx cbProbes=%#zx\n",
    269                     pVtgHdr->cbProbeEnabled, pVtgHdr->cbProbes);
    270         return VERR_SUPDRV_VTG_BAD_HDR;
    271     }
     491    rc = supdrvVtgValidateHdr(pVtgHdr, uVtgHdrAddr, pbImage, cbImage, fUmod);
     492    if (RT_FAILURE(rc))
     493        return rc;
    272494
    273495    /*
     
    277499    while (i-- > 0)
    278500    {
    279         MY_VALIDATE_STR(pVtgHdr->paProviders[i].offName);
    280         if (pVtgHdr->paProviders[i].iFirstProbe >= pVtgHdr->cbProbeEnabled)
    281             return VERR_SUPDRV_VTG_BAD_PROVIDER;
    282         if (pVtgHdr->paProviders[i].iFirstProbe + pVtgHdr->paProviders[i].cProbes > pVtgHdr->cbProbeEnabled)
    283             return VERR_SUPDRV_VTG_BAD_PROVIDER;
    284         MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrSelf);
    285         MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrModules);
    286         MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrFunctions);
    287         MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrNames);
    288         MY_VALIDATE_ATTR(pVtgHdr->paProviders[i].AttrArguments);
    289         if (pVtgHdr->paProviders[i].bReserved)
    290             return VERR_SUPDRV_VTG_BAD_PROVIDER;
     501        PCVTGDESCPROVIDER pProvider = (PCVTGDESCPROVIDER)((uintptr_t)pVtgHdr + pVtgHdr->offProviders) + i;
     502
     503        MY_VALIDATE_STR(pProvider->offName);
     504        MY_CHECK_RET(pProvider->iFirstProbe < pVtgHdr->cbProbeEnabled / sizeof(uint32_t), VERR_SUPDRV_VTG_BAD_PROVIDER);
     505        MY_CHECK_RET((uint32_t)pProvider->iFirstProbe + pProvider->cProbes <= pVtgHdr->cbProbeEnabled / sizeof(uint32_t),
     506                     VERR_SUPDRV_VTG_BAD_PROVIDER);
     507        MY_VALIDATE_ATTR(pProvider->AttrSelf);
     508        MY_VALIDATE_ATTR(pProvider->AttrModules);
     509        MY_VALIDATE_ATTR(pProvider->AttrFunctions);
     510        MY_VALIDATE_ATTR(pProvider->AttrNames);
     511        MY_VALIDATE_ATTR(pProvider->AttrArguments);
     512        MY_CHECK_RET(pProvider->bReserved == 0, VERR_SUPDRV_VTG_BAD_PROVIDER);
    291513    }
    292514
     
    297519    while (i-- > 0)
    298520    {
    299         PVTGDESCARGLIST pArgList;
    300         unsigned        iArg;
    301         bool            fHaveLargeArgs;
    302 
    303         MY_VALIDATE_STR(pVtgHdr->paProbes[i].offName);
    304         if (pVtgHdr->paProbes[i].offArgList >= pVtgHdr->cbArgLists)
     521        PCVTGDESCPROBE      pProbe    = (PCVTGDESCPROBE)(   (uintptr_t)pVtgHdr + pVtgHdr->offProbes)    + i;
     522        PCVTGDESCPROVIDER   pProvider = (PCVTGDESCPROVIDER)((uintptr_t)pVtgHdr + pVtgHdr->offProviders) + pProbe->idxProvider;
     523        PCVTGDESCARGLIST    pArgList  = (PCVTGDESCARGLIST)( (uintptr_t)pVtgHdr + pVtgHdr->offArgLists + pProbe->offArgList );
     524        unsigned            iArg;
     525        bool                fHaveLargeArgs;
     526
     527
     528        MY_VALIDATE_STR(pProbe->offName);
     529        MY_CHECK_RET(pProbe->offArgList < pVtgHdr->cbArgLists, VERR_SUPDRV_VTG_BAD_PROBE);
     530        MY_CHECK_RET((pProbe->offArgList & 3) == 0, VERR_SUPDRV_VTG_BAD_PROBE);
     531        MY_CHECK_RET(pProbe->idxEnabled == i, VERR_SUPDRV_VTG_BAD_PROBE); /* The lists are parallel. */
     532        MY_CHECK_RET(pProbe->idxProvider < cProviders, VERR_SUPDRV_VTG_BAD_PROBE);
     533        MY_CHECK_RET(i - pProvider->iFirstProbe < pProvider->cProbes, VERR_SUPDRV_VTG_BAD_PROBE);
     534        if (pProbe->offObjHdr != (intptr_t)pVtgHdr - (intptr_t)pProbe)
     535        {
     536            SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - iProbe=%u offObjHdr=%d expected %zd\n",
     537                        i, pProbe->offObjHdr, (intptr_t)pVtgHdr - (intptr_t)pProbe);
    305538            return VERR_SUPDRV_VTG_BAD_PROBE;
    306         if (pVtgHdr->paProbes[i].offArgList & 3)
    307             return VERR_SUPDRV_VTG_BAD_PROBE;
    308         if (pVtgHdr->paProbes[i].idxEnabled != i) /* The lists are parallel. */
    309             return VERR_SUPDRV_VTG_BAD_PROBE;
    310         if (pVtgHdr->paProbes[i].idxProvider >= cProviders)
    311             return VERR_SUPDRV_VTG_BAD_PROBE;
    312         if (  i - pVtgHdr->paProviders[pVtgHdr->paProbes[i].idxProvider].iFirstProbe
    313             >= pVtgHdr->paProviders[pVtgHdr->paProbes[i].idxProvider].cProbes)
    314             return VERR_SUPDRV_VTG_BAD_PROBE;
    315         if (pVtgHdr->paProbes[i].u32User)
    316             return VERR_SUPDRV_VTG_BAD_PROBE;
    317         if (pVtgHdr->paProbes[i].u32User2)
    318             return VERR_SUPDRV_VTG_BAD_PROBE;
    319         if (   pVtgHdr->paProbes[i].offObjHdr
    320             != (intptr_t)pVtgHdr - (intptr_t)&pVtgHdr->paProbes[i])
    321         {
    322             SUPR0Printf("supdrvVtgValidate: VERR_SUPDRV_TRACER_BAD_ARG_FLAGS - iProbe=%u offObjHdr=%d expected %zd\n",
    323                         i, pVtgHdr->paProbes[i].offObjHdr, (intptr_t)pVtgHdr - (intptr_t)&pVtgHdr->paProbes[i]);
    324             return VERR_SUPDRV_VTG_BAD_PROBE;
    325539        }
    326540
    327541        /* The referenced argument list. */
    328         pArgList = (PVTGDESCARGLIST)((uintptr_t)pVtgHdr->paArgLists + pVtgHdr->paProbes[i].offArgList);
    329542        if (pArgList->cArgs > 16)
    330543        {
     
    383596
    384597    /*
    385      * Check that pafProbeEnabled is all zero.
    386      */
    387     i = pVtgHdr->cbProbeEnabled;
    388     while (i-- > 0)
    389         if (pVtgHdr->pafProbeEnabled[0])
    390             return VERR_SUPDRV_VTG_BAD_PROBE_ENABLED;
     598     * Check that pacProbeEnabled is all zeros.
     599     */
     600    {
     601        uint32_t const *pcProbeEnabled = (uint32_t const *)((uintptr_t)pVtgHdr + pVtgHdr->offProbeEnabled);
     602        i = pVtgHdr->cbProbeEnabled / sizeof(uint32_t);
     603        while (i-- > 0)
     604            MY_CHECK_RET(pcProbeEnabled[0] == 0, VERR_SUPDRV_VTG_BAD_PROBE_ENABLED);
     605    }
    391606
    392607    /*
    393608     * Probe locations.
    394609     */
    395     i = pVtgHdr->paProbLocsEnd - pVtgHdr->paProbLocs;
    396     while (i-- > 0)
    397     {
    398         if (pVtgHdr->paProbLocs[i].uLine >= _1G)
    399             return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
    400         if (pVtgHdr->paProbLocs[i].fEnabled)
    401             return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
    402         if (pVtgHdr->paProbLocs[i].idProbe != UINT32_MAX)
    403             return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
    404         MY_WITHIN_IMAGE(pVtgHdr->paProbLocs[i].pszFunction, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
    405         offTmp = (uintptr_t)pVtgHdr->paProbLocs[i].pbProbe - (uintptr_t)pVtgHdr->paProbes;
    406         if (offTmp >= pVtgHdr->cbProbes)
    407             return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
    408         if (offTmp / sizeof(VTGDESCPROBE) * sizeof(VTGDESCPROBE) != offTmp)
    409             return VERR_SUPDRV_VTG_BAD_PROBE_LOC;
     610    {
     611        PCVTGPROBELOC paProbeLocs = (PCVTGPROBELOC)((intptr_t)pVtgHdr + pVtgHdr->offProbeLocs);
     612        i = pVtgHdr->cbProbeLocs / sizeof(VTGPROBELOC);
     613        while (i-- > 0)
     614        {
     615            MY_CHECK_RET(paProbeLocs[i].uLine < _1G, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
     616            MY_CHECK_RET(paProbeLocs[i].fEnabled == false, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
     617            MY_CHECK_RET(paProbeLocs[i].idProbe == 0, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
     618            MY_WITHIN_IMAGE(paProbeLocs[i].pszFunction, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
     619            offTmp = (uintptr_t)paProbeLocs[i].pbProbe - (uintptr_t)pVtgHdr->offProbes - (uintptr_t)pVtgHdr;
     620            MY_CHECK_RET(offTmp < pVtgHdr->cbProbes, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
     621            MY_CHECK_RET(offTmp / sizeof(VTGDESCPROBE) * sizeof(VTGDESCPROBE) == offTmp, VERR_SUPDRV_VTG_BAD_PROBE_LOC);
     622        }
    410623    }
    411624
    412625    return VINF_SUCCESS;
     626}
     627
    413628#undef MY_VALIDATE_STR
    414 #undef MY_VALIDATE_PTR
     629#undef MY_VALIDATE_ATTR
    415630#undef MY_WITHIN_IMAGE
    416 }
    417631
    418632
     
    427641{
    428642    Assert(offStrTab < pVtgHdr->cbStrTab);
    429     return &pVtgHdr->pachStrTab[offStrTab];
     643    return (char *)pVtgHdr + pVtgHdr->offStrTab + offStrTab;
    430644}
    431645
     
    439653{
    440654    LOG_TRACER(("Freeing tracepoint provider '%s' / %p\n", pProv->szName, pProv->Core.TracerData.DTrace.idProvider));
    441     pProv->fRegistered = false;
    442     pProv->fZombie     = true;
    443     pProv->Core.pDesc  = NULL;
    444     pProv->Core.pHdr   = NULL;
     655    pProv->fRegistered          = false;
     656    pProv->fZombie              = true;
     657    pProv->Core.pDesc           = NULL;
     658    pProv->Core.pHdr            = NULL;
     659    pProv->Core.paProbeLocsRO   = NULL;
     660    pProv->Core.pvProbeLocsEn   = NULL;
     661    pProv->Core.pacProbeEnabled = NULL;
     662    pProv->Core.paR0ProbeLocs   = NULL;
     663    pProv->Core.paR0Probes      = NULL;
    445664    RT_ZERO(pProv->Core.TracerData);
    446665    RTMemFree(pProv);
     
    449668
    450669/**
    451  * Deregisters a provider.
     670 * Unlinks and deregisters a provider.
    452671 *
    453672 * If the provider is still busy, it will be put in the zombie list.
     
    461680{
    462681    int rc;
     682
     683    RTListNodeRemove(&pProv->ListEntry);
     684    if (pProv->pSession)
     685    {
     686        RTListNodeRemove(&pProv->SessionListEntry);
     687        RTListInit(&pProv->SessionListEntry);
     688        pProv->pSession->cTpProviders--;
     689    }
     690
    463691    if (!pProv->fRegistered || !pDevExt->pTracerOps)
    464692        rc = VINF_SUCCESS;
     
    471699    }
    472700
    473     pProv->fZombie = true;
     701    pProv->fZombie              = true;
     702    pProv->pImage               = NULL;
     703    pProv->pSession             = NULL;
     704    pProv->pUmod                = NULL;
     705    pProv->Core.pDesc           = NULL;
     706    pProv->Core.pHdr            = NULL;
     707    pProv->Core.paProbeLocsRO   = NULL;
     708    pProv->Core.pvProbeLocsEn   = NULL;
     709    pProv->Core.pacProbeEnabled = NULL;
     710    pProv->Core.paR0ProbeLocs   = NULL;
     711
    474712    RTListAppend(&pDevExt->TracerProviderZombieList, &pProv->ListEntry);
    475713    LOG_TRACER(("Invalidated provider '%s' / %p and put it on the zombie list (rc=%Rrc)\n",
     
    521759    RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
    522760    {
    523         RTListNodeRemove(&pProv->ListEntry);
    524761        supdrvTracerDeregisterVtgObj(pDevExt, pProv);
    525762    }
     
    589826 * @param   pszName             The driver name.
    590827 * @param   pVtgHdr             The VTG object header.
    591  * @param   pVtgObj             The size of the VTG object.
    592828 * @param   pImage              The image if applicable.
    593829 * @param   pSession            The session if applicable.
     830 * @param   pUmod               The associated user tracepoint module if
     831 *                              applicable.
    594832 * @param   pszModName          The module name.
    595833 */
    596 static int supdrvTracerRegisterVtgObj(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, size_t cbVtgObj, PSUPDRVLDRIMAGE pImage,
    597                                       PSUPDRVSESSION pSession, const char *pszModName)
     834static int supdrvTracerRegisterVtgObj(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, PSUPDRVLDRIMAGE pImage,
     835                                      PSUPDRVSESSION pSession, PSUPDRVTRACERUMOD pUmod, const char *pszModName)
    598836{
    599837    int                 rc;
    600838    uintptr_t           i;
    601839    PSUPDRVTPPROVIDER   pProv;
     840    size_t              cchModName;
    602841
    603842    /*
     
    609848    AssertPtrNullReturn(pSession, VERR_INVALID_POINTER);
    610849    AssertPtrReturn(pszModName, VERR_INVALID_POINTER);
     850    cchModName = strlen(pszModName);
    611851
    612852    if (pImage)
    613         rc = supdrvVtgValidate(pVtgHdr, cbVtgObj, (const uint8_t *)pImage->pvImage, pImage->cbImageBits);
     853        rc = supdrvVtgValidate(pVtgHdr, (uintptr_t)pVtgHdr,
     854                               (const uint8_t *)pImage->pvImage, pImage->cbImageBits,
     855                               false /*fUmod*/);
    614856    else
    615         rc = supdrvVtgValidate(pVtgHdr, cbVtgObj, NULL, 0);
     857        rc = supdrvVtgValidate(pVtgHdr, (uintptr_t)pVtgHdr, NULL, 0, pUmod != NULL);
    616858    if (RT_FAILURE(rc))
    617859        return rc;
    618860
     861    /*
     862     * Check that there aren't any obvious duplicates.
     863     * (Yes, this isn't race free, but it's good enough for now.)
     864     */
    619865    rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
    620866    if (RT_FAILURE(rc))
    621867        return rc;
    622     RTListForEach(&pDevExt->TracerProviderList, pProv, SUPDRVTPPROVIDER, ListEntry)
    623     {
    624         if (pProv->Core.pHdr == pVtgHdr)
    625         {
    626             rc = VERR_SUPDRV_VTG_ALREADY_REGISTERED;
    627             break;
    628         }
    629         if (   pProv->pSession == pSession
    630             && pProv->pImage   == pImage)
    631         {
    632             rc = VERR_SUPDRV_VTG_ONLY_ONCE_PER_SESSION;
    633             break;
     868    if (pImage || pSession->R0Process == NIL_RTPROCESS)
     869    {
     870        RTListForEach(&pDevExt->TracerProviderList, pProv, SUPDRVTPPROVIDER, ListEntry)
     871        {
     872            if (pProv->Core.pHdr == pVtgHdr)
     873            {
     874                rc = VERR_SUPDRV_VTG_ALREADY_REGISTERED;
     875                break;
     876            }
     877
     878            if (   pProv->pSession == pSession
     879                && pProv->pImage   == pImage)
     880            {
     881                rc = VERR_SUPDRV_VTG_ONLY_ONCE_PER_SESSION;
     882                break;
     883            }
     884        }
     885    }
     886    else
     887    {
     888        RTListForEach(&pSession->TpProviders, pProv, SUPDRVTPPROVIDER, SessionListEntry)
     889        {
     890            if (pProv->Core.pHdr == pVtgHdr)
     891            {
     892                rc = VERR_SUPDRV_VTG_ALREADY_REGISTERED;
     893                break;
     894            }
    634895        }
    635896    }
     
    644905    while (i-- > 0)
    645906    {
    646         PVTGDESCPROVIDER pDesc   = &pVtgHdr->paProviders[i];
     907        PVTGDESCPROVIDER pDesc   = (PVTGDESCPROVIDER)((uintptr_t)pVtgHdr + pVtgHdr->offProviders) + i;
    647908        const char      *pszName = supdrvVtgGetString(pVtgHdr, pDesc->offName);
    648         size_t const     cchName = strlen(pszName);
    649         pProv = (PSUPDRVTPPROVIDER)RTMemAllocZ(RT_OFFSETOF(SUPDRVTPPROVIDER, szName[cchName + 1]));
     909        size_t const     cchName = strlen(pszName) + (pUmod ? 16 : 0);
     910
     911        pProv = (PSUPDRVTPPROVIDER)RTMemAllocZ(RT_OFFSETOF(SUPDRVTPPROVIDER, szName[cchName + 1 + cchModName + 1]));
    650912        if (pProv)
    651913        {
    652             pProv->Core.pDesc       = pDesc;
    653             pProv->Core.pHdr        = pVtgHdr;
    654             pProv->Core.pszName     = &pProv->szName[0];
    655             pProv->Core.pszModName  = pszModName;
    656             pProv->pImage           = pImage;
    657             pProv->pSession         = pSession;
    658             pProv->fZombie          = false;
    659             pProv->fRegistered      = true;
    660             memcpy(&pProv->szName[0], pszName, cchName + 1);
    661 
     914            pProv->Core.pszName         = &pProv->szName[0];
     915            pProv->Core.pszModName      = &pProv->szName[cchName + 1];
     916            pProv->Core.pDesc           = pDesc;
     917            pProv->Core.pHdr            = pVtgHdr;
     918            pProv->Core.paProbeLocsRO   = (PCVTGPROBELOC )((uintptr_t)pVtgHdr + pVtgHdr->offProbeLocs);
     919            if (!pUmod)
     920            {
     921                pProv->Core.pvProbeLocsEn   = (void     *)((uintptr_t)pVtgHdr + pVtgHdr->offProbeLocs);
     922                pProv->Core.pacProbeEnabled = (uint32_t *)((uintptr_t)pVtgHdr + pVtgHdr->offProbeEnabled);
     923                pProv->Core.paR0ProbeLocs   = NULL;
     924                pProv->Core.paR0Probes      = NULL;
     925                pProv->Core.cbProbeLocsEn   = sizeof(VTGPROBELOC);
     926                pProv->Core.cBits           = ARCH_BITS;
     927                pProv->Core.fUmod           = false;
     928            }
     929            else
     930            {
     931                pProv->Core.pvProbeLocsEn   = pUmod->pvProbeLocs;
     932                pProv->Core.pacProbeEnabled = pUmod->pacProbeEnabled;
     933                pProv->Core.paR0ProbeLocs   = &pUmod->aProbeLocs[0];
     934                pProv->Core.paR0Probes      = (PSUPDRVPROBEINFO)&pUmod->aProbeLocs[pUmod->cProbeLocs];
     935                pProv->Core.cbProbeLocsEn   = pUmod->cbProbeLoc;
     936                pProv->Core.cBits           = pUmod->cBits;
     937                pProv->Core.fUmod           = true;
     938            }
     939            pProv->pImage               = pImage;
     940            pProv->pSession             = pSession;
     941            pProv->pUmod                = pUmod;
     942            pProv->fZombie              = false;
     943            pProv->fRegistered          = true;
     944
     945            if (!pUmod)
     946                memcpy(pProv->szName, pszName, cchName + 1);
     947            else
     948                RTStrPrintf(pProv->szName, cchName + 1, "%s%u", pszName, (uint32_t)pSession->Process);
     949            memcpy((void *)pProv->Core.pszModName, pszModName, cchModName + 1);
     950
     951            /*
     952             * Do the actual registration and list manipulations while holding
     953             * down the lock.
     954             */
    662955            rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
    663956            if (RT_SUCCESS(rc))
     
    674967                {
    675968                    RTListAppend(&pDevExt->TracerProviderList, &pProv->ListEntry);
     969                    if (pSession)
     970                    {
     971                        RTListAppend(&pSession->TpProviders, &pProv->SessionListEntry);
     972                        pSession->cTpProviders++;
     973                    }
     974                    else
     975                        RTListInit(&pProv->SessionListEntry);
    676976                    RTSemFastMutexRelease(pDevExt->mtxTracer);
    677977                    LOG_TRACER(("Registered tracepoint provider '%s' in '%s' -> %p\n",
     
    683983                    LOG_TRACER(("Failed to register tracepoint provider '%s' in '%s' -> %Rrc\n",
    684984                                pProv->szName, pszModName, rc));
    685                     RTMemFree(pProv);
    686985                }
    687986            }
     
    690989            rc = VERR_NO_MEMORY;
    691990
     991        /*
     992         * In case of failure, we have to undo any providers we already
     993         * managed to register.
     994         */
    692995        if (RT_FAILURE(rc))
    693996        {
    694997            PSUPDRVTPPROVIDER   pProvNext;
    695             supdrvTracerFreeProvider(pProv);
     998
     999            if (pProv)
     1000                supdrvTracerFreeProvider(pProv);
    6961001
    6971002            RTSemFastMutexRequest(pDevExt->mtxTracer);
    698             RTListForEachReverseSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
    699             {
    700                 if (pProv->Core.pHdr == pVtgHdr)
     1003            if (pImage)
     1004            {
     1005                RTListForEachReverseSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
    7011006                {
    702                     RTListNodeRemove(&pProv->ListEntry);
    703                     supdrvTracerDeregisterVtgObj(pDevExt, pProv);
     1007                    if (pProv->Core.pHdr == pVtgHdr)
     1008                        supdrvTracerDeregisterVtgObj(pDevExt, pProv);
     1009                }
     1010            }
     1011            else
     1012            {
     1013                RTListForEachSafe(&pSession->TpProviders, pProv, pProvNext, SUPDRVTPPROVIDER, SessionListEntry)
     1014                {
     1015                    if (pProv->Core.pHdr == pVtgHdr)
     1016                        supdrvTracerDeregisterVtgObj(pDevExt, pProv);
    7041017                }
    7051018            }
     
    7311044    LOG_TRACER(("SUPR0TracerRegisterDrv: pSession=%p pVtgHdr=%p pszName=%s\n", pSession, pVtgHdr, pszName));
    7321045
    733     rc = supdrvTracerRegisterVtgObj(pSession->pDevExt, pVtgHdr, _1M, NULL /*pImage*/, pSession, pszName);
     1046    rc = supdrvTracerRegisterVtgObj(pSession->pDevExt, pVtgHdr, NULL /*pImage*/, pSession, NULL /*pUmod*/, pszName);
    7341047
    7351048    /*
     
    7621075     */
    7631076    RTSemFastMutexRequest(pDevExt->mtxTracer);
    764     RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
    765     {
    766         if (pProv->pSession == pSession)
    767         {
    768             RTListNodeRemove(&pProv->ListEntry);
    769             supdrvTracerDeregisterVtgObj(pDevExt, pProv);
    770         }
     1077    RTListForEachSafe(&pSession->TpProviders, pProv, pProvNext, SUPDRVTPPROVIDER, SessionListEntry)
     1078    {
     1079        supdrvTracerDeregisterVtgObj(pDevExt, pProv);
    7711080    }
    7721081    RTSemFastMutexRelease(pDevExt->mtxTracer);
     
    7931102    PSUPDRVLDRIMAGE pImage = (PSUPDRVLDRIMAGE)hMod;
    7941103    PSUPDRVDEVEXT   pDevExt;
    795     uintptr_t       cbVtgObj;
    7961104    int             rc;
    7971105
     
    8091117    AssertReturn(pDevExt->pLdrInitImage  == pImage, VERR_WRONG_ORDER);
    8101118    AssertReturn(pDevExt->hLdrInitThread == RTThreadNativeSelf(), VERR_WRONG_ORDER);
    811 
    812     /*
    813      * Calculate the max VTG object size and hand it over to the common code.
    814      */
    815     cbVtgObj = (uintptr_t)pVtgHdr - (uintptr_t)pImage->pvImage;
    816     AssertMsgReturn(cbVtgObj /*off*/ < pImage->cbImageBits,
    817                     ("pVtgHdr=%p offVtgObj=%p cbImageBits=%p\n", pVtgHdr, cbVtgObj, pImage->cbImageBits),
    818                     VERR_INVALID_PARAMETER);
    819     cbVtgObj = pImage->cbImageBits - cbVtgObj;
    820 
    821     rc = supdrvTracerRegisterVtgObj(pDevExt, pVtgHdr, cbVtgObj, pImage, NULL, pImage->szName);
     1119    AssertReturn((uintptr_t)pVtgHdr - (uintptr_t)pImage->pvImage < pImage->cbImageBits, VERR_INVALID_PARAMETER);
     1120
     1121    /*
     1122     * Do the job.
     1123     */
     1124    rc = supdrvTracerRegisterVtgObj(pDevExt, pVtgHdr, pImage, NULL /*pSession*/, NULL /*pUmod*/, pImage->szName);
    8221125    LOG_TRACER(("SUPR0TracerRegisterModule: rc=%d\n", rc));
    8231126
     
    10211324            else
    10221325                LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Waiting on %u opens\n", pDevExt->cTracerOpens));
     1326        }
     1327
     1328        /* Tracer calls. */
     1329        if (pDevExt->cTracerCallers)
     1330        {
     1331            cZombies++;
     1332            if (!(i & 0xf))
     1333                SUPR0Printf("supdrvTracerCommonDeregisterImpl: Waiting on %u callers\n", pDevExt->cTracerCallers);
     1334            else
     1335                LOG_TRACER(("supdrvTracerCommonDeregisterImpl: Waiting on %u callers\n", pDevExt->cTracerCallers));
    10231336        }
    10241337
     
    11791492        {
    11801493            if (pProv->pImage == pImage)
    1181             {
    1182                 RTListNodeRemove(&pProv->ListEntry);
    11831494                supdrvTracerDeregisterVtgObj(pDevExt, pProv);
    1184             }
    11851495        }
    11861496
     
    12041514{
    12051515    /*
    1206      * If ring-0 session, make sure it has deregistered VTG objects and the tracer.
    1207      */
    1208     if (pSession->R0Process == NIL_RTR0PROCESS)
    1209     {
    1210         SUPDRVTPPROVIDER *pProvNext;
    1211         SUPDRVTPPROVIDER *pProv;
    1212 
    1213         RTSemFastMutexRequest(pDevExt->mtxTracer);
    1214         RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry)
    1215         {
    1216             if (pProv->pSession == pSession)
    1217             {
    1218                 RTListNodeRemove(&pProv->ListEntry);
    1219                 supdrvTracerDeregisterVtgObj(pDevExt, pProv);
    1220             }
    1221         }
    1222         RTSemFastMutexRelease(pDevExt->mtxTracer);
    1223 
    1224         (void)SUPR0TracerDeregisterImpl(NULL, pSession);
    1225     }
     1516     * Deregister all providers.
     1517     */
     1518    SUPDRVTPPROVIDER   *pProvNext;
     1519    SUPDRVTPPROVIDER   *pProv;
     1520    RTSemFastMutexRequest(pDevExt->mtxTracer);
     1521    RTListForEachSafe(&pSession->TpProviders, pProv, pProvNext, SUPDRVTPPROVIDER, SessionListEntry)
     1522    {
     1523        supdrvTracerDeregisterVtgObj(pDevExt, pProv);
     1524    }
     1525    RTSemFastMutexRelease(pDevExt->mtxTracer);
    12261526
    12271527    /*
     
    12301530    if (pSession->uTracerData)
    12311531        supdrvIOCtl_TracerClose(pDevExt, pSession);
    1232 }
    1233 
    1234 
    1235 int  VBOXCALL   supdrvIOCtl_TracerUmodRegister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR pVtgHdr, const char *pszModName, uint32_t fFlags)
    1236 {
    1237     return VERR_NOT_IMPLEMENTED;
    1238 }
    1239 
    1240 int  VBOXCALL   supdrvIOCtl_TracerUmodDeregister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR pVtgHdr)
    1241 {
    1242     return VERR_NOT_IMPLEMENTED;
    1243 }
    1244 
    1245 void  VBOXCALL  supdrvIOCtl_TracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PCSUPDRVTRACERUSRCTX pCtx)
    1246 {
    1247 
     1532
     1533    /*
     1534     * Deregister any tracer implementation.
     1535     */
     1536    if (pSession->R0Process == NIL_RTR0PROCESS)
     1537        (void)SUPR0TracerDeregisterImpl(NULL, pSession);
     1538
     1539    if (pSession->R0Process != NIL_RTR0PROCESS)
     1540    {
     1541        /*
     1542         * Free any lingering user modules.  We don't bother holding the lock
     1543         * here as there shouldn't be anyone messing with the session at this
     1544         * point.
     1545         */
     1546        PSUPDRVTRACERUMOD pUmodNext;
     1547        PSUPDRVTRACERUMOD pUmod;
     1548        RTListForEachSafe(&pSession->TpUmods, pUmod, pUmodNext, SUPDRVTRACERUMOD, ListEntry)
     1549        {
     1550            RTR0MemObjFree(pUmod->hMemObjMap, false /*fFreeMappings*/);
     1551            RTR0MemObjFree(pUmod->hMemObjLock, false /*fFreeMappings*/);
     1552            supdrvVtgReleaseObjectCopy(pDevExt, pUmod->pVtgCopy);
     1553            RTMemFree(pUmod);
     1554        }
     1555    }
     1556}
     1557
     1558
     1559static void supdrvVtgReleaseObjectCopy(PSUPDRVDEVEXT pDevExt, PSUPDRVVTGCOPY pThis)
     1560{
     1561    uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
     1562    if (!cRefs)
     1563    {
     1564        RTSemFastMutexRequest(pDevExt->mtxTracer);
     1565        pThis->u32Magic = ~SUDPRVVTGCOPY_MAGIC;
     1566        RTListNodeRemove(&pThis->ListEntry);
     1567        RTSemFastMutexRelease(pDevExt->mtxTracer);
     1568
     1569        RTMemFree(pThis);
     1570    }
     1571}
     1572
     1573
     1574/**
     1575 * Finds a matching VTG object copy, caller owns the lock already.
     1576 *
     1577 * @returns Copy with reference. NULL if not found.
     1578 * @param   pHashList           The hash list to search.
     1579 * @param   pHdr                The VTG header (valid).
     1580 * @param   cbStrTab            The string table size.
     1581 * @param   fFlags              The user module flags.
     1582 */
     1583static PSUPDRVVTGCOPY supdrvVtgFindObjectCopyLocked(PRTLISTANCHOR pHashList, PCVTGOBJHDR pHdr, uint32_t cbStrTab, uint32_t fFlags)
     1584{
     1585    PSUPDRVVTGCOPY  pCur;
     1586
     1587    fFlags &= SUP_TRACER_UMOD_FLAGS_TYPE_MASK;
     1588    RTListForEach(pHashList, pCur, SUPDRVVTGCOPY, ListEntry)
     1589    {
     1590#define HDR_EQUALS(member) pCur->Hdr.member == pHdr->member
     1591        if (   HDR_EQUALS(Uuid.au32[0])
     1592            && HDR_EQUALS(Uuid.au32[1])
     1593            && HDR_EQUALS(Uuid.au32[2])
     1594            && HDR_EQUALS(Uuid.au32[3])
     1595            && HDR_EQUALS(cbObj)
     1596            && HDR_EQUALS(cBits)
     1597            && pCur->cbStrTab == cbStrTab
     1598            && pCur->fFlags == fFlags
     1599           )
     1600        {
     1601            if (RT_LIKELY(   HDR_EQUALS(offStrTab)
     1602                          && HDR_EQUALS(cbStrTab)
     1603                          && HDR_EQUALS(offArgLists)
     1604                          && HDR_EQUALS(cbArgLists)
     1605                          && HDR_EQUALS(offProbes)
     1606                          && HDR_EQUALS(cbProbes)
     1607                          && HDR_EQUALS(offProviders)
     1608                          && HDR_EQUALS(cbProviders)
     1609                          && HDR_EQUALS(offProbeEnabled)
     1610                          && HDR_EQUALS(cbProbeEnabled)
     1611                          && HDR_EQUALS(offProbeLocs)
     1612                          && HDR_EQUALS(cbProbeLocs)
     1613                         )
     1614                )
     1615            {
     1616                Assert(pCur->cRefs > 0);
     1617                Assert(pCur->cRefs < _1M);
     1618                pCur->cRefs++;
     1619                return pCur;
     1620            }
     1621        }
     1622#undef HDR_EQUALS
     1623    }
     1624
     1625    return NULL;
     1626}
     1627
     1628
     1629/**
     1630 * Finds a matching VTG object copy.
     1631 *
     1632 * @returns Copy with reference. NULL if not found.
     1633 * @param   pDevExt             The device extension.
     1634 * @param   pHdr                The VTG header (valid).
     1635 * @param   cbStrTab            The string table size.
     1636 * @param   fFlags              The user module flags.
     1637 */
     1638static PSUPDRVVTGCOPY supdrvVtgFindObjectCopy(PSUPDRVDEVEXT pDevExt, PCVTGOBJHDR pHdr, uint32_t cbStrTab, uint32_t fFlags)
     1639{
     1640    PRTLISTANCHOR   pHashList = &pDevExt->aTrackerUmodHash[pHdr->Uuid.au8[3] % RT_ELEMENTS(pDevExt->aTrackerUmodHash)];
     1641    PSUPDRVVTGCOPY pRet;
     1642
     1643    int rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
     1644    AssertRCReturn(rc, NULL);
     1645
     1646    pRet = supdrvVtgFindObjectCopyLocked(pHashList, pHdr, cbStrTab, fFlags);
     1647
     1648    RTSemFastMutexRelease(pDevExt->mtxTracer);
     1649    return pRet;
     1650}
     1651
     1652
     1653/**
     1654 * Makes a shared copy of the VTG object.
     1655 *
     1656 * @returns VBox status code.
     1657 * @param   pDevExt             The device extension.
     1658 * @param   pVtgHdr             The VTG header (valid).
     1659 * @param   R3PtrVtgHdr         The ring-3 VTG header address.
     1660 * @param   uVtgHdrAddr         The address of the VTG header in the context
     1661 *                              where it is actually used.
     1662 * @param   R3PtrStrTab         The ring-3 address of the probe location string
     1663 *                              table.  The probe location array have offsets
     1664 *                              into this instead of funciton name pointers.
     1665 * @param   cbStrTab            The size of the probe location string table.
     1666 * @param   fFlags              The user module flags.
     1667 * @param   pUmod               The structure we've allocated to track the
     1668 *                              module.  This have a valid kernel mapping of the
     1669 *                              probe location array.  Upon successful return,
     1670 *                              the pVtgCopy member will hold the address of our
     1671 *                              copy (with a referenced of course).
     1672 */
     1673static int supdrvVtgCreateObjectCopy(PSUPDRVDEVEXT pDevExt, PCVTGOBJHDR pVtgHdr, RTR3PTR R3PtrVtgHdr, RTUINTPTR uVtgHdrAddr,
     1674                                     RTR3PTR R3PtrStrTab, uint32_t cbStrTab, uint32_t fFlags, PSUPDRVTRACERUMOD pUmod)
     1675{
     1676    /*
     1677     * Calculate the space required, allocate and copy in the data.
     1678     */
     1679    int             rc;
     1680    size_t const    cProbeLocs   = pVtgHdr->cbProbeLocs / (pVtgHdr->cBits == 32 ? sizeof(VTGPROBELOC32) : sizeof(VTGPROBELOC64));
     1681    size_t const    cbProbeLocs  = cProbeLocs * sizeof(VTGPROBELOC);
     1682    size_t const    offProbeLocs = RT_ALIGN(pVtgHdr->cbObj, 8);
     1683    size_t const    cb           = offProbeLocs + cbProbeLocs + cbStrTab + 1;
     1684    PSUPDRVVTGCOPY  pThis = (PSUPDRVVTGCOPY)RTMemAlloc(RT_OFFSETOF(SUPDRVVTGCOPY, Hdr) + cb);
     1685    if (!pThis)
     1686        return VERR_NO_MEMORY;
     1687
     1688    pThis->u32Magic = SUDPRVVTGCOPY_MAGIC;
     1689    pThis->cRefs    = 1;
     1690    pThis->cbStrTab = cbStrTab;
     1691    pThis->fFlags   = fFlags & SUP_TRACER_UMOD_FLAGS_TYPE_MASK;
     1692    RTListInit(&pThis->ListEntry);
     1693
     1694    rc = RTR0MemUserCopyFrom(&pThis->Hdr, R3PtrVtgHdr, pVtgHdr->cbObj);
     1695    if (RT_SUCCESS(rc))
     1696    {
     1697        char  *pchStrTab = (char *)&pThis->Hdr + offProbeLocs + cbProbeLocs;
     1698        rc = RTR0MemUserCopyFrom(pchStrTab, R3PtrStrTab, cbStrTab);
     1699        if (RT_SUCCESS(rc))
     1700        {
     1701            PVTGPROBELOC    paDst = (PVTGPROBELOC)((char *)&pThis->Hdr + offProbeLocs);
     1702            uint32_t        i;
     1703
     1704            /*
     1705             * Some paranoia: Overwrite the header with the copy we've already
     1706             * validated and zero terminate the string table.
     1707             */
     1708            pThis->Hdr = *pVtgHdr;
     1709            pchStrTab[cbStrTab] = '\0';
     1710
     1711            /*
     1712             * Set the probe location array related header members since we're
     1713             * making our own copy in a different location.
     1714             */
     1715            pThis->Hdr.uProbeLocs.u64     = (uintptr_t)paDst;
     1716            pThis->Hdr.uProbeLocsEnd.u64  = (uintptr_t)paDst + cbProbeLocs;
     1717            pThis->Hdr.offProbeLocs       = offProbeLocs;
     1718            pThis->Hdr.cbProbeLocs        = cbProbeLocs;
     1719            pThis->Hdr.cBits              = ARCH_BITS;
     1720
     1721            /*
     1722             * Copy, convert and fix up the the probe location table.
     1723             */
     1724            if (pVtgHdr->cBits == 32)
     1725            {
     1726                uintptr_t const offDelta = (uintptr_t)&pThis->Hdr - uVtgHdrAddr;
     1727                PCVTGPROBELOC32 paSrc    = (PCVTGPROBELOC32)pUmod->pvProbeLocs;
     1728
     1729                for (i = 0; i < cProbeLocs; i++)
     1730                {
     1731                    paDst[i].uLine    = paSrc[i].uLine;
     1732                    paDst[i].fEnabled = paSrc[i].fEnabled;
     1733                    paDst[i].idProbe  = paSrc[i].idProbe;
     1734                    if (paSrc[i].pszFunction > cbStrTab)
     1735                    {
     1736                        rc = VERR_SUPDRV_TRACER_UMOD_STRTAB_OFF_BAD;
     1737                        break;
     1738                    }
     1739                    paDst[i].pszFunction = pchStrTab + paSrc[i].pszFunction;
     1740                    paDst[i].pbProbe     = (uint8_t *)(paSrc[i].pbProbe + offDelta);
     1741                }
     1742            }
     1743            else
     1744            {
     1745                uint64_t const  offDelta = (uintptr_t)&pThis->Hdr - uVtgHdrAddr;
     1746                PCVTGPROBELOC64 paSrc    = (PCVTGPROBELOC64)pUmod->pvProbeLocs;
     1747
     1748                for (i = 0; i < cProbeLocs; i++)
     1749                {
     1750                    paDst[i].uLine    = paSrc[i].uLine;
     1751                    paDst[i].fEnabled = paSrc[i].fEnabled;
     1752                    paDst[i].idProbe  = paSrc[i].idProbe;
     1753                    if (paSrc[i].pszFunction > cbStrTab)
     1754                    {
     1755                        rc = VERR_SUPDRV_TRACER_UMOD_STRTAB_OFF_BAD;
     1756                        break;
     1757                    }
     1758                    paDst[i].pszFunction = pchStrTab + (uintptr_t)paSrc[i].pszFunction;
     1759                    paDst[i].pbProbe     = (uint8_t *)(uintptr_t)(paSrc[i].pbProbe + offDelta);
     1760                }
     1761            }
     1762
     1763            /*
     1764             * Validate it
     1765             *
     1766             * Note! fUmod is false as this is a kernel copy with all native
     1767             *       structures.
     1768             */
     1769            if (RT_SUCCESS(rc))
     1770                rc = supdrvVtgValidate(&pThis->Hdr, (uintptr_t)&pThis->Hdr, (uint8_t *)&pThis->Hdr, cb, false /*fUmod*/);
     1771            if (RT_SUCCESS(rc))
     1772            {
     1773                /*
     1774                 * Add it to the hash list, making sure nobody raced us.
     1775                 */
     1776                PRTLISTANCHOR pHashList = &pDevExt->aTrackerUmodHash[  pVtgHdr->Uuid.au8[3]
     1777                                                                     % RT_ELEMENTS(pDevExt->aTrackerUmodHash)];
     1778
     1779                rc = RTSemFastMutexRequest(pDevExt->mtxTracer);
     1780                if (RT_SUCCESS(rc))
     1781                {
     1782                    pUmod->pVtgCopy = supdrvVtgFindObjectCopyLocked(pHashList, pVtgHdr, cbStrTab, fFlags);
     1783                    if (!pUmod->pVtgCopy)
     1784                    {
     1785                        pUmod->pVtgCopy = pThis;
     1786                        RTListAppend(pHashList, &pThis->ListEntry);
     1787                        RTSemFastMutexRelease(pDevExt->mtxTracer);
     1788                        return rc;
     1789                    }
     1790
     1791                    /*
     1792                     * Someone raced us, free our copy and return the existing
     1793                     * one instead.
     1794                     */
     1795                    RTSemFastMutexRelease(pDevExt->mtxTracer);
     1796                }
     1797            }
     1798        }
     1799    }
     1800    RTMemFree(pThis);
     1801    return rc;
     1802}
     1803
     1804
     1805/**
     1806 * Undoes what supdrvTracerUmodSetProbeIds did.
     1807 *
     1808 * @param   pDevExt             The device extension.
     1809 * @param   pSession            The current session.
     1810 * @param   pUmod               The user tracepoint module.
     1811 */
     1812static void supdrvTracerUmodClearProbeIds(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUMOD pUmod)
     1813{
     1814    uint32_t i;
     1815
     1816    AssertReturnVoid(pUmod->iLookupTable < RT_ELEMENTS(pSession->apTpLookupTable));
     1817    AssertReturnVoid(pSession->apTpLookupTable[pUmod->iLookupTable] == pUmod);
     1818
     1819    /*
     1820     * Clear the probe IDs and disable the probes.
     1821     */
     1822    i = pUmod->cProbeLocs;
     1823    if (pUmod->cBits == 32)
     1824    {
     1825        PVTGPROBELOC32 paProbeLocs = (PVTGPROBELOC32)pUmod->pvProbeLocs;
     1826        while (i-- > 0)
     1827            paProbeLocs[i].idProbe = 0;
     1828    }
     1829    else
     1830    {
     1831        PVTGPROBELOC64 paProbeLocs = (PVTGPROBELOC64)pUmod->pvProbeLocs;
     1832        while (i-- > 0)
     1833            paProbeLocs[i].idProbe = 0;
     1834    }
     1835
     1836    /*
     1837     * Free the lookup table entry.  We'll have to wait for the table to go
     1838     * idle to make sure there are no current users of pUmod.
     1839     */
     1840    RTSemFastMutexRequest(pDevExt->mtxTracer);
     1841    if (pSession->apTpLookupTable[pUmod->iLookupTable] == pUmod)
     1842    {
     1843        if (pSession->cTpProbesFiring > 0)
     1844        {
     1845            uint32_t i = 0;
     1846            while (pSession->cTpProbesFiring > 0)
     1847            {
     1848                RTSemFastMutexRelease(pDevExt->mtxTracer);
     1849                i++;
     1850                if (!(i & 0xff))
     1851                    SUPR0Printf("supdrvTracerUmodClearProbeIds: waiting for lookup table to go idle (i=%u)\n", i);
     1852                RTThreadSleep(10);
     1853                RTSemFastMutexRequest(pDevExt->mtxTracer);
     1854            }
     1855        }
     1856        ASMAtomicWriteNullPtr(&pSession->apTpLookupTable[pUmod->iLookupTable]);
     1857    }
     1858    RTSemFastMutexRelease(pDevExt->mtxTracer);
     1859}
     1860
     1861
     1862/**
     1863 * Allocates a lookup table entry for the Umod and sets the
     1864 * VTGPROBELOC::idProbe fields in user mode.
     1865 *
     1866 * @returns VINF_SUCCESS or VERR_SUPDRV_TRACER_TOO_MANY_PROVIDERS.
     1867 * @param   pDevExt             The device extension.
     1868 * @param   pSession            The current session.
     1869 * @param   pUmod               The user tracepoint module.
     1870 */
     1871static int supdrvTracerUmodSetProbeIds(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUMOD pUmod)
     1872{
     1873    uint32_t iBase;
     1874    uint32_t i;
     1875
     1876    /*
     1877     * Allocate a lookup table entry.
     1878     */
     1879    RTSemFastMutexRequest(pDevExt->mtxTracer);
     1880    for (i = 0; i < RT_ELEMENTS(pSession->apTpLookupTable); i++)
     1881    {
     1882        if (!pSession->apTpLookupTable[i])
     1883        {
     1884            pSession->apTpLookupTable[i] = pUmod;
     1885            pUmod->iLookupTable = i;
     1886            break;
     1887        }
     1888    }
     1889    RTSemFastMutexRelease(pDevExt->mtxTracer);
     1890    if (i >= RT_ELEMENTS(pSession->apTpLookupTable))
     1891        return VERR_SUPDRV_TRACER_TOO_MANY_PROVIDERS;
     1892
     1893    /*
     1894     * Set probe IDs of the usermode probe location to indicate our lookup
     1895     * table entry as well as the probe location array entry.
     1896     */
     1897    iBase = (uint32_t)pUmod->iLookupTable << 24;
     1898    i = pUmod->cProbeLocs;
     1899    if (pUmod->cBits == 32)
     1900    {
     1901        PVTGPROBELOC32 paProbeLocs = (PVTGPROBELOC32)pUmod->pvProbeLocs;
     1902        while (i-- > 0)
     1903            paProbeLocs[i].idProbe = iBase | i;
     1904    }
     1905    else
     1906    {
     1907        PVTGPROBELOC64 paProbeLocs = (PVTGPROBELOC64)pUmod->pvProbeLocs;
     1908        while (i-- > 0)
     1909            paProbeLocs[i].idProbe = iBase | i;
     1910    }
     1911
     1912    return VINF_SUCCESS;
     1913}
     1914
     1915
     1916int  VBOXCALL   supdrvIOCtl_TracerUmodRegister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession,
     1917                                               RTR3PTR R3PtrVtgHdr, RTUINTPTR uVtgHdrAddr,
     1918                                               RTR3PTR R3PtrStrTab, uint32_t cbStrTab,
     1919                                               const char *pszModName, uint32_t fFlags)
     1920{
     1921    VTGOBJHDR           Hdr;
     1922    PSUPDRVTRACERUMOD   pUmod;
     1923    RTR3PTR             R3PtrLock;
     1924    size_t              cbLock;
     1925    uint32_t            cProbeLocs;
     1926    int                 rc;
     1927
     1928    /*
     1929     * Validate input.
     1930     */
     1931    if (pSession->R0Process == NIL_RTR0PROCESS)
     1932        return VERR_INVALID_CONTEXT;
     1933    if (   fFlags != SUP_TRACER_UMOD_FLAGS_EXE
     1934        && fFlags != SUP_TRACER_UMOD_FLAGS_SHARED)
     1935        return VERR_INVALID_PARAMETER;
     1936
     1937    if (pSession->cTpProviders >= RT_ELEMENTS(pSession->apTpLookupTable))
     1938        return VERR_SUPDRV_TRACER_TOO_MANY_PROVIDERS;
     1939
     1940    if (   cbStrTab < 2
     1941        || cbStrTab > _1M)
     1942        return VERR_SUPDRV_TRACER_UMOD_STRTAB_TOO_BIG;
     1943
     1944    /*
     1945     * Read the VTG header into a temporary buffer and perform some simple
     1946     * validations to make sure we aren't wasting our time here.
     1947     */
     1948    rc = RTR0MemUserCopyFrom(&Hdr, R3PtrVtgHdr, sizeof(Hdr));
     1949    if (RT_FAILURE(rc))
     1950        return rc;
     1951    rc = supdrvVtgValidateHdr(&Hdr, uVtgHdrAddr, NULL, 0, true /*fUmod*/);
     1952    if (RT_FAILURE(rc))
     1953        return rc;
     1954    if (Hdr.cbProviders / sizeof(VTGDESCPROVIDER) > 2)
     1955        return VERR_SUPDRV_TRACER_TOO_MANY_PROVIDERS;
     1956
     1957    /*
     1958     * Check how much needs to be locked down and how many probe locations
     1959     * there are.
     1960     */
     1961    if (   Hdr.offProbeLocs <= 0
     1962        || Hdr.offProbeEnabled > (uint32_t)Hdr.offProbeLocs
     1963        || (uint32_t)Hdr.offProbeLocs - Hdr.offProbeEnabled - Hdr.cbProbeEnabled > 128)
     1964        return VERR_SUPDRV_TRACER_UMOD_NOT_ADJACENT;
     1965    R3PtrLock  = R3PtrVtgHdr + Hdr.offProbeEnabled;
     1966    cbLock     = Hdr.offProbeLocs + Hdr.cbProbeLocs - Hdr.offProbeEnabled + (R3PtrLock & PAGE_OFFSET_MASK);
     1967    R3PtrLock &= ~(RTR3PTR)PAGE_OFFSET_MASK;
     1968    if (cbLock > _64K)
     1969        return VERR_SUPDRV_TRACER_UMOD_TOO_MANY_PROBES;
     1970
     1971    cProbeLocs = Hdr.cbProbeLocs / (Hdr.cBits == 32 ? sizeof(VTGPROBELOC32) : sizeof(VTGPROBELOC64));
     1972
     1973    /*
     1974     * Allocate the tracker data we keep in the session.
     1975     */
     1976    pUmod = (PSUPDRVTRACERUMOD)RTMemAllocZ(  RT_OFFSETOF(SUPDRVTRACERUMOD, aProbeLocs[cProbeLocs])
     1977                                           + (Hdr.cbProbeEnabled / sizeof(uint32_t) * sizeof(SUPDRVPROBEINFO)) );
     1978    if (!pUmod)
     1979        return VERR_NO_MEMORY;
     1980    pUmod->u32Magic         = SUPDRVTRACERUMOD_MAGIC;
     1981    RTListInit(&pUmod->ListEntry);
     1982    pUmod->R3PtrVtgHdr      = R3PtrVtgHdr;
     1983    pUmod->pVtgCopy         = NULL;
     1984    pUmod->hMemObjLock      = NIL_RTR0MEMOBJ;
     1985    pUmod->hMemObjMap       = NIL_RTR0MEMOBJ;
     1986    pUmod->R3PtrProbeLocs   = (RTR3INTPTR)R3PtrVtgHdr + Hdr.offProbeLocs;
     1987    pUmod->iLookupTable     = UINT8_MAX;
     1988    pUmod->cBits            = Hdr.cBits;
     1989    pUmod->cbProbeLoc       = Hdr.cBits == 32 ? sizeof(VTGPROBELOC32) : sizeof(VTGPROBELOC64);
     1990    pUmod->cProbeLocs       = cProbeLocs;
     1991
     1992    /*
     1993     * Lock down and map the user-mode structures.
     1994     */
     1995    rc = RTR0MemObjLockUser(&pUmod->hMemObjLock, R3PtrLock, cbLock, RTMEM_PROT_READ | RTMEM_PROT_WRITE, NIL_RTR0PROCESS);
     1996    if (RT_SUCCESS(rc))
     1997    {
     1998        rc = RTR0MemObjMapKernel(&pUmod->hMemObjMap, pUmod->hMemObjLock, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
     1999        if (RT_SUCCESS(rc))
     2000        {
     2001            pUmod->pacProbeEnabled  = (uint32_t *)(  (uintptr_t)RTR0MemObjAddress(pUmod->hMemObjMap)
     2002                                                   + ((uintptr_t)(R3PtrVtgHdr + Hdr.offProbeEnabled) & PAGE_OFFSET_MASK));
     2003            pUmod->pvProbeLocs      = (uint8_t *)pUmod->pacProbeEnabled + Hdr.offProbeLocs - Hdr.offProbeEnabled;
     2004
     2005            /*
     2006             * Does some other process use the same module already?  If so,
     2007             * share the VTG data with it.  Otherwise, make a ring-0 copy it.
     2008             */
     2009            pUmod->pVtgCopy = supdrvVtgFindObjectCopy(pDevExt, &Hdr, cbStrTab, fFlags);
     2010            if (!pUmod->pVtgCopy)
     2011                rc = supdrvVtgCreateObjectCopy(pDevExt, &Hdr, R3PtrVtgHdr, uVtgHdrAddr, R3PtrStrTab, cbStrTab, fFlags, pUmod);
     2012            if (RT_SUCCESS(rc))
     2013            {
     2014                AssertPtr(pUmod->pVtgCopy);
     2015
     2016                /*
     2017                 * Grabe a place in apTpLookupTable and set the probe IDs
     2018                 * accordingly.
     2019                 */
     2020                rc = supdrvTracerUmodSetProbeIds(pDevExt, pSession, pUmod);
     2021                if (RT_SUCCESS(rc))
     2022                {
     2023                    /*
     2024                     * Register the providers.
     2025                     */
     2026                    rc = supdrvTracerRegisterVtgObj(pDevExt, &pUmod->pVtgCopy->Hdr,
     2027                                                    NULL /*pImage*/, pSession, pUmod, pszModName);
     2028                    if (RT_SUCCESS(rc))
     2029                    {
     2030                        RTSemFastMutexRequest(pDevExt->mtxTracer);
     2031                        RTListAppend(&pSession->TpUmods, &pUmod->ListEntry);
     2032                        RTSemFastMutexRelease(pDevExt->mtxTracer);
     2033
     2034                        return VINF_SUCCESS;
     2035                    }
     2036
     2037                    /* bail out. */
     2038                    supdrvTracerUmodClearProbeIds(pDevExt, pSession, pUmod);
     2039                }
     2040                supdrvVtgReleaseObjectCopy(pDevExt, pUmod->pVtgCopy);
     2041            }
     2042            RTR0MemObjFree(pUmod->hMemObjMap, false /*fFreeMappings*/);
     2043        }
     2044        RTR0MemObjFree(pUmod->hMemObjLock, false /*fFreeMappings*/);
     2045    }
     2046    pUmod->u32Magic = ~SUPDRVTRACERUMOD_MAGIC;
     2047    RTMemFree(pUmod);
     2048    return rc;
     2049}
     2050
     2051
     2052int  VBOXCALL   supdrvIOCtl_TracerUmodDeregister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR R3PtrVtgHdr)
     2053{
     2054    PSUPDRVTRACERUMOD   pUmod = NULL;
     2055    uint32_t            i;
     2056    int                 rc;
     2057
     2058    /*
     2059     * Validate the request.
     2060     */
     2061    RTSemFastMutexRequest(pDevExt->mtxTracer);
     2062    for (i = 0; i < RT_ELEMENTS(pSession->apTpLookupTable); i++)
     2063    {
     2064        pUmod = pSession->apTpLookupTable[i];
     2065        if (   pUmod
     2066            && pUmod->u32Magic    == SUPDRVTRACERUMOD_MAGIC
     2067            && pUmod->R3PtrVtgHdr == R3PtrVtgHdr)
     2068            break;
     2069    }
     2070    RTSemFastMutexRelease(pDevExt->mtxTracer);
     2071    if (pUmod)
     2072    {
     2073        SUPDRVTPPROVIDER   *pProvNext;
     2074        SUPDRVTPPROVIDER   *pProv;
     2075
     2076        /*
     2077         * Remove ourselves from the lookup table and clean up the ring-3 bits
     2078         * we've dirtied.  We do this first to make sure no probes are firing
     2079         * when we're destroying the providers in the next step.
     2080         */
     2081        supdrvTracerUmodClearProbeIds(pDevExt, pSession, pUmod);
     2082
     2083        /*
     2084         * Deregister providers related to the VTG object.
     2085         */
     2086        RTSemFastMutexRequest(pDevExt->mtxTracer);
     2087        RTListForEachSafe(&pSession->TpProviders, pProv, pProvNext, SUPDRVTPPROVIDER, SessionListEntry)
     2088        {
     2089            if (pProv->pUmod == pUmod)
     2090                supdrvTracerDeregisterVtgObj(pDevExt, pProv);
     2091        }
     2092        RTSemFastMutexRelease(pDevExt->mtxTracer);
     2093
     2094        /*
     2095         * Destroy the Umod object.
     2096         */
     2097        pUmod->u32Magic = ~SUPDRVTRACERUMOD_MAGIC;
     2098        supdrvVtgReleaseObjectCopy(pDevExt, pUmod->pVtgCopy);
     2099        RTR0MemObjFree(pUmod->hMemObjMap, false /*fFreeMappings*/);
     2100        RTR0MemObjFree(pUmod->hMemObjLock, false /*fFreeMappings*/);
     2101        RTMemFree(pUmod);
     2102    }
     2103    else
     2104        rc = VERR_NOT_FOUND;
     2105    return rc;
     2106}
     2107
     2108
     2109/**
     2110 * Implementation of supdrvIOCtl_TracerUmodProbeFire and
     2111 * SUPR0TracerUmodProbeFire.
     2112 *
     2113 * @param   pDevExt             The device extension.
     2114 * @param   pSession            The calling session.
     2115 * @param   pCtx                The context record.
     2116 */
     2117static void supdrvTracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx)
     2118{
     2119    /*
     2120     * We cannot trust user mode to hand us the right bits nor not calling us
     2121     * when disabled.  So, we have to check for our selves.
     2122     */
     2123    PSUPDRVTRACERUMOD   pUmod;
     2124    uint32_t const      iLookupTable = pCtx->idProbe >> 24;
     2125    uint32_t const      iProbeLoc    = pCtx->idProbe & UINT32_C(0x00ffffff);
     2126
     2127    if (RT_UNLIKELY(   !pDevExt->pTracerOps
     2128                    || pDevExt->fTracerUnloading))
     2129        return;
     2130    if (RT_UNLIKELY(iLookupTable >= RT_ELEMENTS(pSession->apTpLookupTable)))
     2131        return;
     2132    if (RT_UNLIKELY(   pCtx->cBits != 32
     2133                    && pCtx->cBits != 64))
     2134        return;
     2135
     2136    ASMAtomicIncU32(&pSession->cTpProviders);
     2137
     2138    pUmod = pSession->apTpLookupTable[iLookupTable];
     2139    if (RT_LIKELY(pUmod))
     2140    {
     2141        if (RT_LIKELY(   pUmod->u32Magic == SUPDRVTRACERUMOD_MAGIC
     2142                      && iProbeLoc < pUmod->cProbeLocs
     2143                      && pCtx->cBits == pUmod->cBits))
     2144        {
     2145            RTR3PTR R3PtrProbeLoc = pUmod->R3PtrProbeLocs + iProbeLoc * pUmod->cbProbeLoc;
     2146            if (RT_LIKELY(   (pCtx->cBits == 32 ? (RTR3PTR)pCtx->u.X86.uVtgProbeLoc : pCtx->u.Amd64.uVtgProbeLoc)
     2147                          == R3PtrProbeLoc))
     2148            {
     2149                if (RT_LIKELY(pUmod->aProbeLocs[iProbeLoc].fEnabled))
     2150                {
     2151                    ASMAtomicIncU32(&pDevExt->cTracerCallers);
     2152                    if (RT_LIKELY(   pDevExt->pTracerOps
     2153                                  && !pDevExt->fTracerUnloading))
     2154                    {
     2155                        pCtx->idProbe = pUmod->aProbeLocs[iProbeLoc].idProbe;
     2156                        pDevExt->pTracerOps->pfnProbeFireUser(pDevExt->pTracerOps, pSession, pCtx);
     2157                    }
     2158                    ASMAtomicDecU32(&pDevExt->cTracerCallers);
     2159                }
     2160            }
     2161        }
     2162    }
     2163
     2164    ASMAtomicDecU32(&pSession->cTpProviders);
     2165}
     2166
     2167
     2168SUPR0DECL(void) SUPR0TracerUmodProbeFire(PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx)
     2169{
     2170    AssertReturnVoid(SUP_IS_SESSION_VALID(pSession));
     2171    AssertPtrReturnVoid(pCtx);
     2172
     2173    supdrvTracerUmodProbeFire(pSession->pDevExt, pSession, pCtx);
     2174}
     2175
     2176
     2177void  VBOXCALL  supdrvIOCtl_TracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx)
     2178{
     2179    supdrvTracerUmodProbeFire(pDevExt, pSession, pCtx);
    12482180}
    12492181
     
    14342366    if (RT_SUCCESS(rc))
    14352367    {
     2368        uint32_t i;
     2369
    14362370        pDevExt->TracerHlp.uVersion    = SUPDRVTRACERHLP_VERSION;
    14372371        /** @todo  */
     
    14392373        RTListInit(&pDevExt->TracerProviderList);
    14402374        RTListInit(&pDevExt->TracerProviderZombieList);
     2375        for (i = 0; i < RT_ELEMENTS(pDevExt->aTrackerUmodHash); i++)
     2376            RTListInit(&pDevExt->aTrackerUmodHash[i]);
    14412377
    14422378#ifdef VBOX_WITH_NATIVE_DTRACE
     
    14502386         */
    14512387#ifdef VBOX_WITH_DTRACE_R0DRV
    1452         rc = supdrvTracerRegisterVtgObj(pDevExt, &g_VTGObjHeader, _1M, NULL /*pImage*/, NULL /*pSession*/, "vboxdrv");
     2388        rc = supdrvTracerRegisterVtgObj(pDevExt, &g_VTGObjHeader, NULL /*pImage*/, NULL /*pSession*/, NULL /*pUmod*/, "vboxdrv");
    14532389        if (RT_SUCCESS(rc))
    14542390            return rc;
  • trunk/src/VBox/HostDrivers/Support/SUPLib.cpp

    r40981 r41117  
    5151#include <VBox/param.h>
    5252#include <VBox/log.h>
     53#include <VBox/VBoxTpG.h>
    5354
    5455#include <iprt/assert.h>
     
    23892390
    23902391
    2391 SUPDECL(void) SUPTracerFireProbe(struct VTGPROBELOC *pVtgProbeLoc, uintptr_t uArg0, uintptr_t uArg1, uintptr_t uArg2,
    2392                                  uintptr_t uArg3, uintptr_t uArg4)
    2393 {
    2394     /* C and stubbed for now. */
    2395 }
    2396 
    2397 
    2398 SUPR3DECL(int) SUPR3TracerRegisterModule(uintptr_t hModNative, const char *pszModule, struct VTGOBJHDR *pVtgHdr, uint32_t fFlags)
     2392typedef struct SUPDRVTRACERSTRTAB
     2393{
     2394    /** Pointer to the string table. */
     2395    char       *pchStrTab;
     2396    /** The actual string table size. */
     2397    uint32_t    cbStrTab;
     2398    /** The original string pointers. */
     2399    RTUINTPTR   apszOrgFunctions[1];
     2400} SUPDRVTRACERSTRTAB, *PSUPDRVTRACERSTRTAB;
     2401
     2402
     2403/**
     2404 * Destroys a string table, restoring the original pszFunction member valus.
     2405 *
     2406 * @param   pThis               The string table structure.
     2407 * @param   paProbLocs          The probe location array.
     2408 * @param   cProbLocs           The number of probe locations.
     2409 */
     2410static void supr3TracerDestroyStrTab(PSUPDRVTRACERSTRTAB pThis, PVTGPROBELOC32 paProbeLocs32, PVTGPROBELOC64 paProbeLocs64,
     2411                                     uint32_t cProbeLocs, bool f32Bit)
     2412{
     2413    /* Restore. */
     2414    size_t i = cProbeLocs;
     2415    if (f32Bit)
     2416        while (i--)
     2417            paProbeLocs32[i].pszFunction = (uint32_t)pThis->apszOrgFunctions[i];
     2418    else
     2419        while (i--)
     2420            paProbeLocs64[i].pszFunction = pThis->apszOrgFunctions[i];
     2421
     2422    /* Free. */
     2423    RTMemFree(pThis->pchStrTab);
     2424    RTMemFree(pThis);
     2425}
     2426
     2427
     2428/**
     2429 * Creates a string table for the pszFunction members in the probe location
     2430 * array.
     2431 *
     2432 * This will save and replace the pszFunction members with offsets.
     2433 *
     2434 * @returns Pointer to a string table structure.  NULL on failure.
     2435 * @param   paProbLocs          The probe location array.
     2436 * @param   cProbLocs           The number of elements in the array.
     2437 * @param   cBits
     2438 */
     2439static PSUPDRVTRACERSTRTAB supr3TracerCreateStrTab(PVTGPROBELOC32 paProbeLocs32,
     2440                                                   PVTGPROBELOC64 paProbeLocs64,
     2441                                                   uint32_t cProbeLocs,
     2442                                                   RTUINTPTR offDelta,
     2443                                                   bool f32Bit)
     2444{
     2445    if (cProbeLocs > _128K)
     2446        return NULL;
     2447
     2448    /*
     2449     * Allocate the string table structures.
     2450     */
     2451    size_t              cbThis    = RT_OFFSETOF(SUPDRVTRACERSTRTAB, apszOrgFunctions[cProbeLocs]);
     2452    PSUPDRVTRACERSTRTAB pThis     = (PSUPDRVTRACERSTRTAB)RTMemAlloc(cbThis);
     2453    if (!pThis)
     2454        return NULL;
     2455
     2456    uint32_t const      cHashBits = cProbeLocs * 2 - 1;
     2457    uint32_t           *pbmHash   = (uint32_t *)RTMemAllocZ(RT_ALIGN_32(cHashBits, 64) / 8 );
     2458    if (!pbmHash)
     2459    {
     2460        RTMemFree(pThis);
     2461        return NULL;
     2462    }
     2463
     2464    /*
     2465     * Calc the max string table size and save the orignal pointers so we can
     2466     * replace them later.
     2467     */
     2468    size_t cbMax = 1;
     2469    for (uint32_t i = 0; i < cProbeLocs; i++)
     2470    {
     2471        pThis->apszOrgFunctions[i] = f32Bit ? paProbeLocs32[i].pszFunction : paProbeLocs64[i].pszFunction;
     2472        const char *pszFunction = (const char *)(uintptr_t)(pThis->apszOrgFunctions[i] + offDelta);
     2473        size_t cch = strlen(pszFunction);
     2474        if (cch > _1K)
     2475        {
     2476            cbMax = 0;
     2477            break;
     2478        }
     2479        cbMax += cch + 1;
     2480    }
     2481
     2482    /* Alloc space for it. */
     2483    if (cbMax > 0)
     2484        pThis->pchStrTab = (char *)RTMemAlloc(cbMax);
     2485    else
     2486        pThis->pchStrTab = NULL;
     2487    if (!pThis->pchStrTab)
     2488    {
     2489        RTMemFree(pbmHash);
     2490        RTMemFree(pThis);
     2491        return NULL;
     2492    }
     2493
     2494    /*
     2495     * Create the string table.
     2496     */
     2497    uint32_t off = 0;
     2498    uint32_t offPrev = 0;
     2499
     2500    for (uint32_t i = 0; i < cProbeLocs; i++)
     2501    {
     2502        const char * const psz      = (const char *)(uintptr_t)(pThis->apszOrgFunctions[i] + offDelta);
     2503        size_t       const cch      = strlen(psz);
     2504        uint32_t     const iHashBit = RTStrHash1(psz) % cHashBits;
     2505        if (ASMBitTestAndSet(pbmHash, iHashBit))
     2506        {
     2507            /* Often it's the most recent string. */
     2508            if (   off - offPrev < cch + 1
     2509                || memcmp(&pThis->pchStrTab[offPrev], psz, cch + 1))
     2510            {
     2511                /* It wasn't, search the entire string table. (lazy bird) */
     2512                offPrev = 0;
     2513                while (offPrev < off)
     2514                {
     2515                    size_t cchCur = strlen(&pThis->pchStrTab[offPrev]);
     2516                    if (   cchCur == cch
     2517                        && !memcmp(&pThis->pchStrTab[offPrev], psz, cch + 1))
     2518                        break;
     2519                    offPrev += (uint32_t)cchCur + 1;
     2520                }
     2521            }
     2522        }
     2523        else
     2524            offPrev = off;
     2525
     2526        /* Add the string to the table. */
     2527        if (offPrev >= off)
     2528        {
     2529            memcpy(&pThis->pchStrTab[off], psz, cch + 1);
     2530            offPrev = off;
     2531            off += (uint32_t)cch + 1;
     2532        }
     2533
     2534        /* Update the entry */
     2535        if (f32Bit)
     2536            paProbeLocs32[i].pszFunction = offPrev;
     2537        else
     2538            paProbeLocs64[i].pszFunction = offPrev;
     2539    }
     2540
     2541    pThis->cbStrTab = off;
     2542    RTMemFree(pbmHash);
     2543    return pThis;
     2544}
     2545
     2546
     2547
     2548SUPR3DECL(int) SUPR3TracerRegisterModule(uintptr_t hModNative, const char *pszModule, struct VTGOBJHDR *pVtgHdr,
     2549                                         RTUINTPTR uVtgHdrAddr, uint32_t fFlags)
    23992550{
    24002551    /* Validate input. */
    24012552    NOREF(hModNative);
    24022553    AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
     2554    AssertReturn(!memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)), VERR_SUPDRV_VTG_MAGIC);
    24032555    AssertPtrReturn(pszModule, VERR_INVALID_POINTER);
    24042556    size_t cchModule = strlen(pszModule);
     
    24072559    AssertReturn(fFlags == SUP_TRACER_UMOD_FLAGS_EXE || fFlags == SUP_TRACER_UMOD_FLAGS_SHARED, VERR_INVALID_PARAMETER);
    24082560
    2409     /* fake */
     2561    /*
     2562     * Set the probe location array offset and size members. If the size is
     2563     * zero, don't bother ring-0 with it.
     2564     */
     2565    if (!pVtgHdr->offProbeLocs)
     2566    {
     2567        uint64_t u64Tmp = pVtgHdr->uProbeLocsEnd.u64 - pVtgHdr->uProbeLocs.u64;
     2568        if (u64Tmp >= UINT32_MAX)
     2569            return VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH;
     2570        pVtgHdr->cbProbeLocs  = (uint32_t)u64Tmp;
     2571
     2572        u64Tmp = pVtgHdr->uProbeLocs.u64 - (uintptr_t)pVtgHdr;
     2573        if ((int64_t)u64Tmp != (int32_t)u64Tmp)
     2574            return VERR_SUPDRV_VTG_BAD_HDR_PTR;
     2575        pVtgHdr->offProbeLocs = (int32_t)u64Tmp;
     2576    }
     2577
     2578    if (   !pVtgHdr->cbProbeLocs
     2579        || !pVtgHdr->cbProbes)
     2580        return VINF_SUCCESS;
     2581
     2582    /*
     2583     * Fake out.
     2584     */
    24102585    if (RT_UNLIKELY(g_u32FakeMode))
    24112586        return VINF_SUCCESS;
     2587
     2588    /*
     2589     * Create a string table for the function names in the location array.
     2590     * It's somewhat easier to do that here than from ring-0.
     2591     */
     2592    size_t const        cProbeLocs  = pVtgHdr->cbProbeLocs
     2593                                    / (pVtgHdr->cBits == 32 ? sizeof(VTGPROBELOC32) : sizeof(VTGPROBELOC64));
     2594    PVTGPROBELOC        paProbeLocs = (PVTGPROBELOC)((uintptr_t)pVtgHdr + pVtgHdr->offProbeLocs);
     2595    PSUPDRVTRACERSTRTAB pStrTab     = supr3TracerCreateStrTab((PVTGPROBELOC32)paProbeLocs,
     2596                                                              (PVTGPROBELOC64)paProbeLocs,
     2597                                                              cProbeLocs, (uintptr_t)pVtgHdr - uVtgHdrAddr,
     2598                                                              pVtgHdr->cBits == 32);
     2599    if (!pStrTab)
     2600        return VERR_NO_MEMORY;
     2601
    24122602
    24132603    /*
     
    24212611    Req.Hdr.fFlags          = SUPREQHDR_FLAGS_DEFAULT;
    24222612    Req.Hdr.rc              = VERR_INTERNAL_ERROR;
    2423     Req.u.In.pVtgHdr        = pVtgHdr;
     2613    Req.u.In.uVtgHdrAddr    = uVtgHdrAddr;
     2614    Req.u.In.R3PtrVtgHdr    = pVtgHdr;
     2615    Req.u.In.R3PtrStrTab    = pStrTab->pchStrTab;
     2616    Req.u.In.cbStrTab       = pStrTab->cbStrTab;
    24242617    Req.u.In.fFlags         = fFlags;
    24252618
     
    24512644    if (RT_SUCCESS(rc))
    24522645        rc = Req.Hdr.rc;
     2646
     2647    supr3TracerDestroyStrTab(pStrTab, (PVTGPROBELOC32)paProbeLocs, (PVTGPROBELOC64)paProbeLocs,
     2648                             cProbeLocs,  pVtgHdr->cBits == 32);
    24532649    return rc;
    24542650}
     
    24592655    /* Validate input. */
    24602656    AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
    2461 
    2462     /* fake */
     2657    AssertReturn(!memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)), VERR_SUPDRV_VTG_MAGIC);
     2658
     2659    /*
     2660     * Don't bother if the object is empty.
     2661     */
     2662    if (   !pVtgHdr->cbProbeLocs
     2663        || !pVtgHdr->cbProbes)
     2664        return VINF_SUCCESS;
     2665
     2666    /*
     2667     * Fake out.
     2668     */
    24632669    if (RT_UNLIKELY(g_u32FakeMode))
    24642670        return VINF_SUCCESS;
     
    24822688}
    24832689
     2690
     2691DECLASM(void) suplibTracerFireProbe(PVTGPROBELOC pProbeLoc, PSUPTRACERUMODFIREPROBE pReq)
     2692{
     2693    pReq->Hdr.u32Cookie         = g_u32Cookie;
     2694    pReq->Hdr.u32SessionCookie  = g_u32SessionCookie;
     2695    Assert(pReq->Hdr.cbIn  == SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE_IN);
     2696    Assert(pReq->Hdr.cbOut == SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE_OUT);
     2697    pReq->Hdr.fFlags            = SUPREQHDR_FLAGS_DEFAULT;
     2698    pReq->Hdr.rc                = VINF_SUCCESS;
     2699
     2700    suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_UMOD_FIRE_PROBE, pReq, SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE);
     2701}
     2702
  • trunk/src/VBox/Runtime/VBox/VBoxRTDeps.cpp

    r40130 r41117  
    5656    (PFNRT)SUPR3PageAllocEx,
    5757    (PFNRT)SUPSemEventCreate,
     58    (PFNRT)SUPTracerFireProbe,
    5859#endif
    5960    (PFNRT)xmlModuleOpen,
  • trunk/src/VBox/VMM/VMMR3/VM.cpp

    r40975 r41117  
    160160
    161161#if defined(VBOX_WITH_DTRACE_R3) && !defined(VBOX_WITH_NATIVE_DTRACE)
    162     //SUPR3TracerRegisterModule(&g_VTGObjHeader, "VBoxVMM");
     162    SUPR3TracerRegisterModule(~(uintptr_t)0, "VBoxVMM", &g_VTGObjHeader, (uintptr_t)&g_VTGObjHeader,
     163                              SUP_TRACER_UMOD_FLAGS_SHARED);
    163164#endif
    164165
  • trunk/src/bldprogs/VBoxTpG.cpp

    r40975 r41117  
    3737#include <iprt/stream.h>
    3838#include <iprt/string.h>
     39#include <iprt/uuid.h>
    3940
    4041#include "scmstream.h"
     
    474475                    "  NAME(%%1):\n"
    475476                    " %%endmacro\n"
    476                     " segment VTG.Obj public CLASS=DATA align=4096 use32\n"
     477                    " segment VTG.Obj public CLASS=VTG align=4096 use32\n"
    477478                    "\n"
    478479                    "%%elifdef ASM_FORMAT_MACHO\n"
     
    502503                    "  NAME(%%1):\n"
    503504                    " %%endmacro\n"
    504                     " [section .VTGPrLc.Begin progbits alloc noexec write align=4096]\n"
     505                    " [section .VTGData progbits alloc noexec write align=4096]\n"
     506                    " [section .VTGPrLc.Begin progbits alloc noexec write align=32]\n"
     507                    " dd 0,0,0,0, 0,0,0,0\n"
    505508                    "VTG_GLOBAL g_aVTGPrLc, data\n"
    506509                    " [section .VTGPrLc       progbits alloc noexec write align=1]\n"
    507510                    " [section .VTGPrLc.End   progbits alloc noexec write align=1]\n"
    508511                    "VTG_GLOBAL g_aVTGPrLc_End, data\n"
     512                    " dd 0,0,0,0, 0,0,0,0\n"
    509513                    " [section .VTGData progbits alloc noexec write align=4096]\n"
    510514                    "\n"
     
    517521                    "                ;0         1         2         3\n"
    518522                    "                ;012345678901234567890123456789012\n"
    519                     "    db          'VTG Object Header v1.4', 0, 0\n"
     523                    "    db          'VTG Object Header v1.5', 0, 0\n"
    520524                    "    dd          %u\n"
     525                    "    dd          NAME(g_acVTGProbeEnabled_End) - NAME(g_VTGObjHeader)\n"
     526                    "    dd          NAME(g_achVTGStringTable)     - NAME(g_VTGObjHeader)\n"
     527                    "    dd          NAME(g_achVTGStringTable_End) - NAME(g_achVTGStringTable)\n"
     528                    "    dd          NAME(g_aVTGArgLists)          - NAME(g_VTGObjHeader)\n"
     529                    "    dd          NAME(g_aVTGArgLists_End)      - NAME(g_aVTGArgLists)\n"
     530                    "    dd          NAME(g_aVTGProbes)            - NAME(g_VTGObjHeader)\n"
     531                    "    dd          NAME(g_aVTGProbes_End)        - NAME(g_aVTGProbes)\n"
     532                    "    dd          NAME(g_aVTGProviders)         - NAME(g_VTGObjHeader)\n"
     533                    "    dd          NAME(g_aVTGProviders_End)     - NAME(g_aVTGProviders)\n"
     534                    "    dd          NAME(g_acVTGProbeEnabled)     - NAME(g_VTGObjHeader)\n"
     535                    "    dd          NAME(g_acVTGProbeEnabled_End) - NAME(g_acVTGProbeEnabled)\n"
    521536                    "    dd          0\n"
    522                     "    RTCCPTR_DEF NAME(g_aVTGProviders)\n"
    523                     "    RTCCPTR_DEF NAME(g_aVTGProviders_End)     - NAME(g_aVTGProviders)\n"
    524                     "    RTCCPTR_DEF NAME(g_aVTGProbes)\n"
    525                     "    RTCCPTR_DEF NAME(g_aVTGProbes_End)        - NAME(g_aVTGProbes)\n"
    526                     "    RTCCPTR_DEF NAME(g_afVTGProbeEnabled)\n"
    527                     "    RTCCPTR_DEF NAME(g_afVTGProbeEnabled_End) - NAME(g_afVTGProbeEnabled)\n"
    528                     "    RTCCPTR_DEF NAME(g_achVTGStringTable)\n"
    529                     "    RTCCPTR_DEF NAME(g_achVTGStringTable_End) - NAME(g_achVTGStringTable)\n"
    530                     "    RTCCPTR_DEF NAME(g_aVTGArgLists)\n"
    531                     "    RTCCPTR_DEF NAME(g_aVTGArgLists_End)      - NAME(g_aVTGArgLists)\n"
     537                    "    dd          0\n"
    532538                    "%%ifdef ASM_FORMAT_MACHO ; Apple has a real decent linker!\n"
    533539                    "extern section$start$__VTG$__VTGPrLc\n"
    534540                    "    RTCCPTR_DEF section$start$__VTG$__VTGPrLc\n"
     541                    " %%if ARCH_BITS == 32\n"
     542                    "    dd          0\n"
     543                    " %%endif\n"
    535544                    "extern section$end$__VTG$__VTGPrLc\n"
    536545                    "    RTCCPTR_DEF section$end$__VTG$__VTGPrLc\n"
     546                    " %%if ARCH_BITS == 32\n"
     547                    "    dd          0\n"
     548                    " %%endif\n"
    537549                    "%%else\n"
    538550                    "    RTCCPTR_DEF NAME(g_aVTGPrLc)\n"
    539                     "    RTCCPTR_DEF NAME(g_aVTGPrLc_End) ; cross section/segment size not possible\n"
     551                    " %%if ARCH_BITS == 32\n"
     552                    "    dd          0\n"
     553                    " %%endif\n"
     554                    "    RTCCPTR_DEF NAME(g_aVTGPrLc_End)\n"
     555                    " %%if ARCH_BITS == 32\n"
     556                    "    dd          0\n"
     557                    " %%endif\n"
    540558                    "%%endif\n"
    541                     "    RTCCPTR_DEF 0\n"
    542                     "    RTCCPTR_DEF 0\n"
    543                     "    RTCCPTR_DEF 0\n"
    544                     "    RTCCPTR_DEF 0\n"
    545559                    ,
    546560                    g_pszScript, g_cBits);
    547 
    548     /*
    549      * Declare the probe enable flags.
    550      */
     561    RTUUID Uuid;
     562    int rc = RTUuidCreate(&Uuid);
     563    if (RT_FAILURE(rc))
     564        return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTUuidCreate failed: %Rrc", rc);
    551565    ScmStreamPrintf(pStrm,
    552                     ";\n"
    553                     "; Probe enabled flags.  Since these will be accessed all the time\n"
    554                     "; they are placed together and early in the section to get some more\n"
    555                     "; cache and TLB hits when the probes are disabled.\n"
    556                     ";\n"
    557                     "VTG_GLOBAL g_afVTGProbeEnabled, data\n"
    558                     );
    559     uint32_t        cProbes = 0;
    560     RTListForEach(&g_ProviderHead, pProvider, VTGPROVIDER, ListEntry)
    561     {
    562         RTListForEach(&pProvider->ProbeHead, pProbe, VTGPROBE, ListEntry)
    563         {
    564             ScmStreamPrintf(pStrm,
    565                             "VTG_GLOBAL g_fVTGProbeEnabled_%s_%s, data\n"
    566                             "    db 0\n",
    567                             pProvider->pszName, pProbe->pszMangledName);
    568             cProbes++;
    569         }
    570     }
    571     ScmStreamPrintf(pStrm, "VTG_GLOBAL g_afVTGProbeEnabled_End, data\n");
    572     if (cProbes >= _32K)
    573         return RTMsgErrorExit(RTEXITCODE_FAILURE, "Too many probes: %u (max %u)", cProbes, _32K - 1);
     566                    "    dd 0%08xh, 0%08xh, 0%08xh, 0%08xh\n"
     567                    "    dd 0, 0, 0, 0\n"
     568                    , Uuid.au32[0], Uuid.au32[1], Uuid.au32[2], Uuid.au32[3]);
    574569
    575570    /*
     
    595590                    "; The argument lists.\n"
    596591                    ";\n"
     592                    "ALIGNDATA(16)\n"
    597593                    "VTG_GLOBAL g_aVTGArgLists, data\n");
    598594    uint32_t off = 0;
     
    665661                    "; Prob definitions.\n"
    666662                    ";\n"
     663                    "ALIGNDATA(16)\n"
    667664                    "VTG_GLOBAL g_aVTGProbes, data\n"
    668665                    "\n");
     
    676673            ScmStreamPrintf(pStrm,
    677674                            "VTG_GLOBAL g_VTGProbeData_%s_%s, data ; idx=#%4u\n"
    678                             "    dd %6u  ; name\n"
    679                             "    dd %6u  ; Argument list offset\n"
    680                             "    dw NAME(g_fVTGProbeEnabled_%s_%s) - NAME(g_afVTGProbeEnabled)\n"
    681                             "    dw %6u  ; provider index\n"
    682                             "    dd NAME(g_VTGObjHeader) - NAME(g_VTGProbeData_%s_%s) ; offset to the object header\n"
    683                             "    dd      0  ; for the application\n"
    684                             "    dd      0  ; for the application\n"
     675                            "    dd %6u  ; offName\n"
     676                            "    dd %6u  ; offArgList\n"
     677                            "    dw (NAME(g_cVTGProbeEnabled_%s_%s) - NAME(g_acVTGProbeEnabled)) / 4 ; idxEnabled\n"
     678                            "    dw %6u  ; idxProvider\n"
     679                            "    dd NAME(g_VTGObjHeader) - NAME(g_VTGProbeData_%s_%s) ; offObjHdr\n"
    685680                            ,
    686681                            pProvider->pszName, pProbe->pszMangledName, iProbe,
     
    700695
    701696    /*
    702      * The providers data.
     697     * The provider data.
    703698     */
    704699    ScmStreamPrintf(pStrm,
     
    707702                    "; Provider data.\n"
    708703                    ";\n"
     704                    "ALIGNDATA(16)\n"
    709705                    "VTG_GLOBAL g_aVTGProviders, data\n");
    710706    iProvider = 0;
     
    735731    }
    736732    ScmStreamPrintf(pStrm, "VTG_GLOBAL g_aVTGProviders_End, data\n");
     733
     734    /*
     735     * Declare the probe enable flags.
     736     *
     737     * These must be placed at the end so they'll end up adjacent to the probe
     738     * locations.  This is important for reducing the amount of memory we need
     739     * to lock down for user mode modules.
     740     */
     741    ScmStreamPrintf(pStrm,
     742                    ";\n"
     743                    "; Probe enabled flags.\n"
     744                    ";\n"
     745                    "ALIGNDATA(16)\n"
     746                    "VTG_GLOBAL g_acVTGProbeEnabled, data\n"
     747                    );
     748    uint32_t        cProbes = 0;
     749    RTListForEach(&g_ProviderHead, pProvider, VTGPROVIDER, ListEntry)
     750    {
     751        RTListForEach(&pProvider->ProbeHead, pProbe, VTGPROBE, ListEntry)
     752        {
     753            ScmStreamPrintf(pStrm,
     754                            "VTG_GLOBAL g_cVTGProbeEnabled_%s_%s, data\n"
     755                            "    dd 0\n",
     756                            pProvider->pszName, pProbe->pszMangledName);
     757            cProbes++;
     758        }
     759    }
     760    ScmStreamPrintf(pStrm, "VTG_GLOBAL g_acVTGProbeEnabled_End, data\n");
     761    if (cProbes >= _32K)
     762        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Too many probes: %u (max %u)", cProbes, _32K - 1);
     763
    737764
    738765    /*
     
    942969        {
    943970            ScmStreamPrintf(pStrm,
    944                             "extern bool    g_fVTGProbeEnabled_%s_%s;\n"
    945                             "extern uint8_t g_VTGProbeData_%s_%s;\n"
    946                             "DECLASM(void)  VTGProbeStub_%s_%s(PVTGPROBELOC",
     971                            "extern uint32_t g_cVTGProbeEnabled_%s_%s;\n"
     972                            "extern uint8_t  g_VTGProbeData_%s_%s;\n"
     973                            "DECLASM(void)   VTGProbeStub_%s_%s(PVTGPROBELOC",
    947974                            pProv->pszName, pProbe->pszMangledName,
    948975                            pProv->pszName, pProbe->pszMangledName,
     
    956983                            ");\n"
    957984                            "# define %s_ENABLED() \\\n"
    958                             "    (RT_UNLIKELY(g_fVTGProbeEnabled_%s_%s)) \n"
     985                            "    (RT_UNLIKELY(g_cVTGProbeEnabled_%s_%s)) \n"
    959986                            "# define %s("
    960987                            , szTmp,
     
    971998                            ") \\\n"
    972999                            "    do { \\\n"
    973                             "        if (RT_UNLIKELY(g_fVTGProbeEnabled_%s_%s)) \\\n"
     1000                            "        if (RT_UNLIKELY(g_cVTGProbeEnabled_%s_%s)) \\\n"
    9741001                            "        { \\\n"
    9751002                            "            VTG_DECL_VTGPROBELOC(s_VTGProbeLoc) = \\\n"
    976                             "            { __LINE__, 0, UINT32_MAX, __FUNCTION__, &g_VTGProbeData_%s_%s }; \\\n"
     1003                            "            { __LINE__, 0, 0, __FUNCTION__, &g_VTGProbeData_%s_%s }; \\\n"
    9771004                            "            VTGProbeStub_%s_%s(&s_VTGProbeLoc",
    9781005                            pProv->pszName, pProbe->pszMangledName,
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