Changeset 41117 in vbox
- Timestamp:
- May 2, 2012 2:22:29 PM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 77725
- Location:
- trunk
- Files:
-
- 1 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Config.kmk
r41101 r41117 614 614 # Set this to enable user mode dtrace probes. 615 615 if1of ($(KBUILD_TARGET), darwin solaris) 616 VBOX_WITH_DTRACE_R3 = 1616 # VBOX_WITH_DTRACE_R3 = 1 617 617 endif 618 618 # Set this to enable kernel driver dtrace probes. 619 619 if1of ($(KBUILD_TARGET), darwin solaris) 620 VBOX_WITH_DTRACE_R0DRV = 1620 # VBOX_WITH_DTRACE_R0DRV = 1 621 621 endif 622 622 # Set this to enable dtrace probes in platform agnostic kernel code. … … 3316 3316 -Wl,--rpath-link,$(L4_LIBDIR) 3317 3317 TEMPLATE_VBOXR3EXE_LDFLAGS.linux = -Wl,-z,noexecstack $(VBOX_LD_as_needed) 3318 ifdef VBOX_WITH_DTRACE_R33319 TEMPLATE_VBOXR3EXE_LDFLAGS.linux += -Wl,--verbose3320 endif3321 3318 3322 3319 ifeq ($(KBUILD_TARGET),linux) -
trunk/include/VBox/VBoxTpG.h
r40986 r41117 34 34 RT_C_DECLS_BEGIN 35 35 36 /** 37 * 32-bit probe location. 38 */ 39 typedef 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; 47 AssertCompileSize(VTGPROBELOC32, 16); 48 /** Pointer to a 32-bit probe location. */ 49 typedef VTGPROBELOC32 *PVTGPROBELOC32; 50 /** Pointer to a const 32-bit probe location. */ 51 typedef VTGPROBELOC32 const *PCVTGPROBELOC32; 52 53 /** 54 * 64-bit probe location. 55 */ 56 typedef 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; 65 AssertCompileSize(VTGPROBELOC64, 32); 66 /** Pointer to a 64-bit probe location. */ 67 typedef VTGPROBELOC64 *PVTGPROBELOC64; 68 /** Pointer to a const 64-bit probe location. */ 69 typedef VTGPROBELOC64 const *PCVTGPROBELOC64; 70 36 71 37 72 /** … … 52 87 /** Pointer to a probe location. */ 53 88 typedef VTGPROBELOC *PVTGPROBELOC; 89 /** Pointer to a const probe location. */ 90 typedef VTGPROBELOC const *PCVTGPROBELOC; 54 91 55 92 /** @def VTG_OBJ_SECT … … 154 191 /** Pointer to an argument descriptor. */ 155 192 typedef VTGDESCARG *PVTGDESCARG; 193 /** Pointer to a const argument descriptor. */ 194 typedef VTGDESCARG const *PCVTGDESCARG; 156 195 157 196 … … 168 207 /** Pointer to a VTG argument list descriptor. */ 169 208 typedef VTGDESCARGLIST *PVTGDESCARGLIST; 209 /** Pointer to a const VTG argument list descriptor. */ 210 typedef VTGDESCARGLIST const *PCVTGDESCARGLIST; 170 211 171 212 … … 181 222 /** The distance from this structure to the VTG object header. */ 182 223 int32_t offObjHdr; 183 uint32_t u32User;184 uint32_t u32User2;185 224 } VTGDESCPROBE; 186 AssertCompileSize(VTGDESCPROBE, 24);225 AssertCompileSize(VTGDESCPROBE, 16); 187 226 /** Pointer to a VTG probe descriptor. */ 188 227 typedef VTGDESCPROBE *PVTGDESCPROBE; 228 /** Pointer to a const VTG probe descriptor. */ 229 typedef VTGDESCPROBE const *PCVTGDESCPROBE; 189 230 190 231 … … 253 294 /** Pointer to a VTG provider descriptor. */ 254 295 typedef VTGDESCPROVIDER *PVTGDESCPROVIDER; 296 /** Pointer to a const VTG provider descriptor. */ 297 typedef VTGDESCPROVIDER const *PCVTGDESCPROVIDER; 255 298 256 299 … … 260 303 typedef struct VTGOBJHDR 261 304 { 305 /** Magic value (VTGOBJHDR_MAGIC). */ 262 306 char szMagic[24]; 307 /** The bitness of the structures. 308 * This only affects the probe location pointers and structures. */ 263 309 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]; 278 384 } VTGOBJHDR; 385 AssertCompileSize(VTGOBJHDR, 128); 386 AssertCompileMemberAlignment(VTGOBJHDR, uProbeLocs, 8); 387 AssertCompileMemberAlignment(VTGOBJHDR, uProbeLocsEnd, 8); 279 388 /** Pointer to a VTG data object header. */ 280 389 typedef VTGOBJHDR *PVTGOBJHDR; 390 /** Pointer to a const VTG data object header. */ 391 typedef VTGOBJHDR const *PCVTGOBJHDR; 281 392 282 393 /** 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" 284 395 285 396 /** The name of the VTG data object header symbol in the object file. */ -
trunk/include/VBox/err.h
r40878 r41117 1623 1623 /** Bad VTG bit count value. */ 1624 1624 #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) 1629 1631 /** Bad VTG header - to low value. */ 1630 #define VERR_SUPDRV_VTG_BAD_HDR_TOO_FEW (-370 8)1632 #define VERR_SUPDRV_VTG_BAD_HDR_TOO_FEW (-3709) 1631 1633 /** Bad VTG header - to high value. */ 1632 #define VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH (-37 09)1634 #define VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH (-3710) 1633 1635 /** Bad VTG header - size value is not a multiple of the structure size. */ 1634 #define VERR_SUPDRV_VTG_BAD_HDR_NOT_MULTIPLE (-371 0)1636 #define VERR_SUPDRV_VTG_BAD_HDR_NOT_MULTIPLE (-3711) 1635 1637 /** Bad VTG string table offset. */ 1636 #define VERR_SUPDRV_VTG_STRTAB_OFF (-371 1)1638 #define VERR_SUPDRV_VTG_STRTAB_OFF (-3712) 1637 1639 /** Bad VTG string. */ 1638 #define VERR_SUPDRV_VTG_BAD_STRING (-371 2)1640 #define VERR_SUPDRV_VTG_BAD_STRING (-3713) 1639 1641 /** VTG string is too long. */ 1640 #define VERR_SUPDRV_VTG_STRING_TOO_LONG (-371 3)1642 #define VERR_SUPDRV_VTG_STRING_TOO_LONG (-3714) 1641 1643 /** Bad VTG attribute value. */ 1642 #define VERR_SUPDRV_VTG_BAD_ATTR (-371 4)1644 #define VERR_SUPDRV_VTG_BAD_ATTR (-3715) 1643 1645 /** Bad VTG provider descriptor. */ 1644 #define VERR_SUPDRV_VTG_BAD_PROVIDER (-371 5)1646 #define VERR_SUPDRV_VTG_BAD_PROVIDER (-3716) 1645 1647 /** Bad VTG probe descriptor. */ 1646 #define VERR_SUPDRV_VTG_BAD_PROBE (-371 6)1648 #define VERR_SUPDRV_VTG_BAD_PROBE (-3717) 1647 1649 /** Bad VTG argument list descriptor. */ 1648 #define VERR_SUPDRV_VTG_BAD_ARGLIST (-371 7)1650 #define VERR_SUPDRV_VTG_BAD_ARGLIST (-3718) 1649 1651 /** Bad VTG probe enabled data. */ 1650 #define VERR_SUPDRV_VTG_BAD_PROBE_ENABLED (-371 8)1652 #define VERR_SUPDRV_VTG_BAD_PROBE_ENABLED (-3719) 1651 1653 /** Bad VTG probe location record. */ 1652 #define VERR_SUPDRV_VTG_BAD_PROBE_LOC (-37 19)1654 #define VERR_SUPDRV_VTG_BAD_PROBE_LOC (-3720) 1653 1655 /** The VTG object for the session or image has already been registered. */ 1654 #define VERR_SUPDRV_VTG_ALREADY_REGISTERED (-372 0)1656 #define VERR_SUPDRV_VTG_ALREADY_REGISTERED (-3721) 1655 1657 /** A driver may only register one VTG object per session. */ 1656 #define VERR_SUPDRV_VTG_ONLY_ONCE_PER_SESSION (-372 1)1658 #define VERR_SUPDRV_VTG_ONLY_ONCE_PER_SESSION (-3722) 1657 1659 /** A tracer has already been registered. */ 1658 #define VERR_SUPDRV_TRACER_ALREADY_REGISTERED (-372 2)1660 #define VERR_SUPDRV_TRACER_ALREADY_REGISTERED (-3723) 1659 1661 /** The session has no tracer associated with it. */ 1660 #define VERR_SUPDRV_TRACER_NOT_REGISTERED (-372 3)1662 #define VERR_SUPDRV_TRACER_NOT_REGISTERED (-3724) 1661 1663 /** The tracer has already been opened in this sesssion. */ 1662 #define VERR_SUPDRV_TRACER_ALREADY_OPENED (-372 4)1664 #define VERR_SUPDRV_TRACER_ALREADY_OPENED (-3725) 1663 1665 /** The tracer has not been opened. */ 1664 #define VERR_SUPDRV_TRACER_NOT_OPENED (-372 5)1666 #define VERR_SUPDRV_TRACER_NOT_OPENED (-3726) 1665 1667 /** There is no tracer present. */ 1666 #define VERR_SUPDRV_TRACER_NOT_PRESENT (-372 6)1668 #define VERR_SUPDRV_TRACER_NOT_PRESENT (-3727) 1667 1669 /** The tracer is unloading. */ 1668 #define VERR_SUPDRV_TRACER_UNLOADING (-372 7)1670 #define VERR_SUPDRV_TRACER_UNLOADING (-3728) 1669 1671 /** Another thread in the session is talking to the tracer. */ 1670 #define VERR_SUPDRV_TRACER_SESSION_BUSY (-372 8)1672 #define VERR_SUPDRV_TRACER_SESSION_BUSY (-3729) 1671 1673 /** The tracer cannot open it self in the same session. */ 1672 #define VERR_SUPDRV_TRACER_CANNOT_OPEN_SELF (-37 29)1674 #define VERR_SUPDRV_TRACER_CANNOT_OPEN_SELF (-3730) 1673 1675 /** 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) 1675 1690 /** @} */ 1676 1691 -
trunk/include/VBox/sup.h
r40983 r41117 91 91 SUPPAGINGMODE_AMD64_GLOBAL_NX 92 92 } SUPPAGINGMODE; 93 94 95 /**96 * The CPU state.97 */98 typedef enum SUPGIPCPUSTATE99 {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 = 0x7fffffff110 } SUPGIPCPUSTATE;111 112 /**113 * Per CPU data.114 */115 typedef struct SUPGIPCPU116 {117 /** Update transaction number.118 * This number is incremented at the start and end of each update. It follows119 * thusly that odd numbers indicates update in progress, while even numbers120 * indicate stable data. Use this to make sure that the data items you fetch121 * 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 enough126 * 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 any175 * process or VM. It can be accessed thru the g_pSUPGlobalInfoPage176 * pointer when a session is open.177 */178 typedef struct SUPGLOBALINFOPAGE179 {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 u32Mode227 * is SUPGIPMODE_ASYNC_TSC, otherwise (SUPGIPMODE_SYNC_TSC) only the first228 * 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 #else235 AssertCompileMemberAlignment(SUPGLOBALINFOPAGE, aCPUs, 256);236 #endif237 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 0x19590106245 /** The GIP version.246 * Upper 16 bits is the major version. Major version is only changed with247 * incompatible changes in the GIP. */248 #define SUPGLOBALINFOPAGE_VERSION 0x00030000249 250 /**251 * SUPGLOBALINFOPAGE::u32Mode values.252 */253 typedef enum SUPGIPMODE254 {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 = 0x7fffffff263 } SUPGIPMODE;264 265 /** Pointer to the Global Information Page.266 *267 * This pointer is valid as long as SUPLib has a open session. Anyone using268 * the page must treat this pointer as highly volatile and not trust it beyond269 * one transaction.270 *271 * @remark The GIP page is read-only to everyone but the support driver and272 * is actually mapped read only everywhere but in ring-0. However273 * it is not marked 'const' as this might confuse compilers into274 * thinking that values doesn't change even if members are marked275 * 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 # else287 # 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 # endif298 /** The GIP.299 * We save a level of indirection by exporting the GIP instead of a variable300 * pointing to it. */301 extern DECLIMPORT(SUPGLOBALINFOPAGE) g_SUPGlobalInfoPage;302 #endif303 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_h312 /**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 else328 {329 iCpu = pGip->aiCpuFromApicId[ASMGetApicId()];330 if (iCpu >= pGip->cCpus)331 return UINT64_MAX;332 }333 334 return pGip->aCPUs[iCpu].u64CpuHz;335 }336 #endif337 338 /**339 * Request for generic VMMR0Entry calls.340 */341 typedef struct SUPVMMR0REQHDR342 {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 0359 /** @see VMMR0_DO_HWACC_RUN. */360 #define SUP_VMMR0_DO_HWACC_RUN 1361 /** @see VMMR0_DO_NOP */362 #define SUP_VMMR0_DO_NOP 2363 /** @} */364 365 /** SUPR3QueryVTCaps capability flags366 * @{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 SUPR0SERVICEREQHDR377 {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 semaphore411 * 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_RING0428 /**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 #endif439 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 and472 * 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 semaphore502 * 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_RING0528 /**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 #endif539 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 and572 * 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_RING3581 582 /** @defgroup grp_sup_r3 SUP Host Context Ring-3 API583 * @ingroup grp_sup584 * @{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 the605 * "real" application binary for which the hardened stub is built. The entry606 * point is invoked upon successful initialization of the support library and607 * 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 SUPINITOP620 {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_End633 } SUPINITOP;634 635 /**636 * Trusted error entry point, optional.637 *638 * This is exported as "TrustedError" by the dynamic libraries which contains639 * 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 systems655 * and when using the open-vboxdrv-via-root-service setup on Windows.656 *657 * This function will perform the integrity checks of the VirtualBox658 * installation, open the support driver, open the root service (later),659 * and load the DLL corresponding to \a pszProgName and execute its main660 * function.661 *662 * @returns Return code appropriate for main().663 *664 * @param pszProgName The program name. This will be used to figure out which665 * 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 a682 * 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 the694 * init call count and just terminated.695 */696 #ifdef __cplusplus697 SUPR3DECL(int) SUPR3Term(bool fForced = false);698 #else699 SUPR3DECL(int) SUPR3Term(int fForced);700 #endif701 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 the708 * 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 path726 * 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 than737 * SUPR3CallVMMR0. When entering using this call the R0 components can call738 * 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 size749 * 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 size765 * 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 SUPLOGGER771 {772 SUPLOGGER_DEBUG = 1,773 SUPLOGGER_RELEASE774 } 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, kernel836 * 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 of867 *868 * @returns VBox status code.869 * @retval VERR_NOT_SUPPORTED if the OS doesn't allow us to change page level870 * protection. See also RTR0MemObjProtect.871 *872 * @param pvR3 The ring-3 address SUPR3PageAllocEx returned.873 * @param R0Ptr The ring-0 address SUPR3PageAllocEx returned if it874 * is desired that the corresponding ring-0 page875 * mappings should change protection as well. Pass876 * NIL_RTR0PTR if the ring-0 pages should remain877 * unaffected.878 * @param off Offset to start at which to start chagning the page879 * 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 combination882 * of RTMEM_PROT_READ, RTMEM_PROT_WRITE and883 * 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 physical898 * 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 the910 * ring-3 mapping executable on WIN64. This is a serious problem in regard to911 * 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 to934 * 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 as953 * 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 as968 * 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 entry974 * 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 a995 * 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 into1028 * the hypervisor or VM process. The integrity check may include verifying1029 * the authenticode/elfsign/whatever signature of the file, which can take1030 * 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 NULL1037 * 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 image1044 * location and that the invocation was absolute.1045 *1046 * This must currently be called after initializing the runtime. The intended1047 * audience is set-uid-to-root applications, root services and similar.1048 *1049 * @returns VBox status code. On failure1050 * message.1051 * @param pszArgv0 The first argument to main().1052 * @param fInternal Set this to @c true if this is an internal1053 * 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 by1062 * normal users on the system. On Unix this translates to root ownership and1063 * 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 or1069 * 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 to1072 * 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 module1082 * 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 be1087 * 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 (hardened1109 * builds).1110 *1111 * Will add dll suffix to the file if missing, then look for it in the1112 * 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 from1127 * extension packs and anything else safely installed on the system, provided1128 * 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 requires1151 * 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 not1186 * at hand.1187 * @param pszModule The module name.1188 * @param pVtgHdr The VTG header.1189 * @param fFlags See SUP_TRACER_UMOD_FLAGS_XXX1190 */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_RING01228 /** @defgroup grp_sup_r0 SUP Host Context Ring-0 API1229 * @ingroup grp_sup1230 * @{1231 */1232 1233 /**1234 * Security objectype.1235 */1236 typedef enum SUPDRVOBJTYPE1237 {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 = 0x7ffffff1256 } 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 symbols1297 * 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 services1315 * such as the host network interface filtering and access to the host1316 * TCP/IP stack.1317 *1318 * @remark Module dependencies and making sure that a component doesn't1319 * get unloaded while in use, is the sole responsibility of the1320 * driver/kext/whatever implementing the component.1321 */1322 typedef struct SUPDRVFACTORY1323 {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 be1330 * 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 Tracing1351 * @{ */1352 1353 /**1354 * Tracer data associated with a provider.1355 */1356 typedef union SUPDRVTRACERDATA1357 {1358 /** Generic */1359 uint64_t au64[2];1360 1361 /** DTrace data. */1362 struct1363 {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 SUPDRVVDTPROVIDERCORE1379 {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 1394 93 1395 94 /** … … 1452 151 uint64_t r13; 1453 152 uint64_t r14; 153 uint64_t r15; 1454 154 } Amd64; 1455 155 } u; 1456 156 } SUPDRVTRACERUSRCTX; 1457 157 /** Pointer to the usermode probe context information. */ 158 typedef SUPDRVTRACERUSRCTX *PSUPDRVTRACERUSRCTX; 159 /** Pointer to the const usermode probe context information. */ 1458 160 typedef SUPDRVTRACERUSRCTX const *PCSUPDRVTRACERUSRCTX; 1459 161 162 /** 163 * The CPU state. 164 */ 165 typedef 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 */ 182 typedef 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; 227 AssertCompileSize(RTCPUID, 4); 228 AssertCompileSize(SUPGIPCPU, 128); 229 AssertCompileMemberAlignment(SUPGIPCPU, u64NanoTS, 8); 230 AssertCompileMemberAlignment(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. */ 234 typedef 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 */ 245 typedef 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; 298 AssertCompileMemberAlignment(SUPGLOBALINFOPAGE, u64NanoTSLastUpdateHz, 8); 299 #if defined(RT_ARCH_SPARC) || defined(RT_ARCH_SPARC64) 300 AssertCompileMemberAlignment(SUPGLOBALINFOPAGE, aCPUs, 32); 301 #else 302 AssertCompileMemberAlignment(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. */ 307 typedef 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 */ 320 typedef 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) 345 extern DECLEXPORT(PSUPGLOBALINFOPAGE) g_pSUPGlobalInfoPage; 346 347 #elif !defined(IN_RING0) || defined(RT_OS_WINDOWS) || defined(RT_OS_SOLARIS) 348 extern 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.) */ 357 DECLINLINE(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. */ 368 extern DECLIMPORT(SUPGLOBALINFOPAGE) g_SUPGlobalInfoPage; 369 #endif 370 371 /** 372 * Gets the GIP pointer. 373 * 374 * @returns Pointer to the GIP or NULL. 375 */ 376 SUPDECL(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 */ 385 DECLINLINE(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 */ 408 typedef 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. */ 416 typedef 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 */ 443 typedef 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. */ 451 typedef 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. */ 457 typedef R0PTRTYPE(struct SUPSEMEVENTHANDLE *) SUPSEMEVENT; 458 /** Pointer to an event semaphore handle. */ 459 typedef 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 */ 470 SUPDECL(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 */ 483 SUPDECL(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 */ 492 SUPDECL(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 */ 504 SUPDECL(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 */ 515 SUPDECL(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 */ 525 SUPDECL(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 */ 535 SUPDECL(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 */ 544 SUPDECL(uint32_t) SUPSemEventGetResolution(PSUPDRVSESSION pSession); 545 546 547 /** Multiple release event semaphore handle. Ring-0 / ring-3. */ 548 typedef R0PTRTYPE(struct SUPSEMEVENTMULTIHANDLE *) SUPSEMEVENTMULTI; 549 /** Pointer to an multiple release event semaphore handle. */ 550 typedef 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 */ 561 SUPDECL(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 */ 574 SUPDECL(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 */ 583 SUPDECL(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 */ 592 SUPDECL(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 */ 604 SUPDECL(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 */ 615 SUPDECL(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 */ 625 SUPDECL(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 */ 635 SUPDECL(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 */ 644 SUPDECL(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 */ 659 SUPR3DECL(int) SUPR3Install(void); 660 661 /** 662 * Uninstalls the support library. 663 * 664 * @returns VBox status code. 665 */ 666 SUPR3DECL(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 */ 681 typedef DECLCALLBACK(int) FNSUPTRUSTEDMAIN(int argc, char **argv, char **envp); 682 /** Pointer to FNSUPTRUSTEDMAIN(). */ 683 typedef FNSUPTRUSTEDMAIN *PFNSUPTRUSTEDMAIN; 684 685 /** Which operation failed. */ 686 typedef 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 */ 714 typedef DECLCALLBACK(void) FNSUPTRUSTEDERROR(const char *pszWhere, SUPINITOP enmWhat, int rc, const char *pszMsgFmt, va_list va); 715 /** Pointer to FNSUPTRUSTEDERROR. */ 716 typedef 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 */ 738 DECLHIDDEN(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 */ 754 SUPR3DECL(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 764 SUPR3DECL(int) SUPR3Term(bool fForced = false); 765 #else 766 SUPR3DECL(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 */ 777 SUPR3DECL(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 */ 789 SUPR3DECL(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 */ 800 SUPR3DECL(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 */ 818 SUPR3DECL(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 */ 834 SUPR3DECL(int) SUPR3CallR0Service(const char *pszService, size_t cchService, uint32_t uOperation, uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr); 835 836 /** Which logger. */ 837 typedef 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 */ 852 SUPR3DECL(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 */ 863 SUPR3DECL(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 */ 871 SUPR3DECL(int) SUPR3LoggerDestroy(SUPLOGGER enmWhich); 872 873 /** 874 * Queries the paging mode of the host OS. 875 * 876 * @returns The paging mode. 877 */ 878 SUPR3DECL(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 */ 890 SUPR3DECL(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 */ 899 SUPR3DECL(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 */ 916 SUPR3DECL(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 */ 930 SUPR3DECL(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 */ 952 SUPR3DECL(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 */ 961 SUPR3DECL(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 */ 980 SUPR3DECL(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 */ 989 SUPR3DECL(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 */ 1005 SUPR3DECL(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 */ 1014 SUPR3DECL(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 */ 1029 SUPR3DECL(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 */ 1044 SUPR3DECL(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 */ 1054 SUPR3DECL(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 */ 1065 SUPR3DECL(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 */ 1073 SUPR3DECL(int) SUPR3LoadVMM(const char *pszFilename); 1074 1075 /** 1076 * Unloads R0 HC VMM code. 1077 * 1078 * @returns VBox status code. 1079 * @deprecated Use SUPR3FreeModule(). 1080 */ 1081 SUPR3DECL(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 */ 1089 SUPR3DECL(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 */ 1107 SUPR3DECL(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 */ 1123 SUPR3DECL(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 */ 1143 SUPR3DECL(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 */ 1158 SUPR3DECL(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 */ 1172 SUPR3DECL(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 */ 1188 SUPR3DECL(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 */ 1203 SUPR3DECL(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 */ 1210 SUPR3DECL(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 */ 1220 SUPR3DECL(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 */ 1229 SUPR3DECL(int) SUPR3TracerOpen(uint32_t uCookie, uintptr_t uArg); 1230 1231 /** 1232 * Closes the tracer. 1233 * 1234 * @returns VBox status code. 1235 */ 1236 SUPR3DECL(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 */ 1246 SUPR3DECL(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 */ 1260 SUPR3DECL(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 */ 1269 SUPR3DECL(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 */ 1281 SUPDECL(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 */ 1306 typedef 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 */ 1336 typedef DECLCALLBACK(void) FNSUPDRVDESTRUCTOR(void *pvObj, void *pvUser1, void *pvUser2); 1337 /** Pointer to a FNSUPDRVDESTRUCTOR(). */ 1338 typedef FNSUPDRVDESTRUCTOR *PFNSUPDRVDESTRUCTOR; 1339 1340 SUPR0DECL(void *) SUPR0ObjRegister(PSUPDRVSESSION pSession, SUPDRVOBJTYPE enmType, PFNSUPDRVDESTRUCTOR pfnDestructor, void *pvUser1, void *pvUser2); 1341 SUPR0DECL(int) SUPR0ObjAddRef(void *pvObj, PSUPDRVSESSION pSession); 1342 SUPR0DECL(int) SUPR0ObjAddRefEx(void *pvObj, PSUPDRVSESSION pSession, bool fNoBlocking); 1343 SUPR0DECL(int) SUPR0ObjRelease(void *pvObj, PSUPDRVSESSION pSession); 1344 SUPR0DECL(int) SUPR0ObjVerifyAccess(void *pvObj, PSUPDRVSESSION pSession, const char *pszObjName); 1345 1346 SUPR0DECL(int) SUPR0LockMem(PSUPDRVSESSION pSession, RTR3PTR pvR3, uint32_t cPages, PRTHCPHYS paPages); 1347 SUPR0DECL(int) SUPR0UnlockMem(PSUPDRVSESSION pSession, RTR3PTR pvR3); 1348 SUPR0DECL(int) SUPR0ContAlloc(PSUPDRVSESSION pSession, uint32_t cPages, PRTR0PTR ppvR0, PRTR3PTR ppvR3, PRTHCPHYS pHCPhys); 1349 SUPR0DECL(int) SUPR0ContFree(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr); 1350 SUPR0DECL(int) SUPR0LowAlloc(PSUPDRVSESSION pSession, uint32_t cPages, PRTR0PTR ppvR0, PRTR3PTR ppvR3, PRTHCPHYS paPages); 1351 SUPR0DECL(int) SUPR0LowFree(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr); 1352 SUPR0DECL(int) SUPR0MemAlloc(PSUPDRVSESSION pSession, uint32_t cb, PRTR0PTR ppvR0, PRTR3PTR ppvR3); 1353 SUPR0DECL(int) SUPR0MemGetPhys(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr, PSUPPAGE paPages); 1354 SUPR0DECL(int) SUPR0MemFree(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr); 1355 SUPR0DECL(int) SUPR0PageAllocEx(PSUPDRVSESSION pSession, uint32_t cPages, uint32_t fFlags, PRTR3PTR ppvR3, PRTR0PTR ppvR0, PRTHCPHYS paPages); 1356 SUPR0DECL(int) SUPR0PageMapKernel(PSUPDRVSESSION pSession, RTR3PTR pvR3, uint32_t offSub, uint32_t cbSub, uint32_t fFlags, PRTR0PTR ppvR0); 1357 SUPR0DECL(int) SUPR0PageProtect(PSUPDRVSESSION pSession, RTR3PTR pvR3, RTR0PTR pvR0, uint32_t offSub, uint32_t cbSub, uint32_t fProt); 1358 SUPR0DECL(int) SUPR0PageFree(PSUPDRVSESSION pSession, RTR3PTR pvR3); 1359 SUPR0DECL(int) SUPR0GipMap(PSUPDRVSESSION pSession, PRTR3PTR ppGipR3, PRTHCPHYS pHCPhysGip); 1360 SUPR0DECL(int) SUPR0QueryVTCaps(PSUPDRVSESSION pSession, uint32_t *pfCaps); 1361 SUPR0DECL(int) SUPR0GipUnmap(PSUPDRVSESSION pSession); 1362 SUPR0DECL(int) SUPR0Printf(const char *pszFormat, ...); 1363 SUPR0DECL(SUPPAGINGMODE) SUPR0GetPagingMode(void); 1364 SUPR0DECL(int) SUPR0EnableVTx(bool fEnable); 1365 1366 /** @name Absolute symbols 1367 * Take the address of these, don't try call them. 1368 * @{ */ 1369 SUPR0DECL(void) SUPR0AbsIs64bit(void); 1370 SUPR0DECL(void) SUPR0Abs64bitKernelCS(void); 1371 SUPR0DECL(void) SUPR0Abs64bitKernelSS(void); 1372 SUPR0DECL(void) SUPR0Abs64bitKernelDS(void); 1373 SUPR0DECL(void) SUPR0AbsKernelCS(void); 1374 SUPR0DECL(void) SUPR0AbsKernelSS(void); 1375 SUPR0DECL(void) SUPR0AbsKernelDS(void); 1376 SUPR0DECL(void) SUPR0AbsKernelES(void); 1377 SUPR0DECL(void) SUPR0AbsKernelFS(void); 1378 SUPR0DECL(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 */ 1392 typedef 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. */ 1411 typedef SUPDRVFACTORY *PSUPDRVFACTORY; 1412 /** Pointer to a const support driver factory. */ 1413 typedef SUPDRVFACTORY const *PCSUPDRVFACTORY; 1414 1415 SUPR0DECL(int) SUPR0ComponentRegisterFactory(PSUPDRVSESSION pSession, PCSUPDRVFACTORY pFactory); 1416 SUPR0DECL(int) SUPR0ComponentDeregisterFactory(PSUPDRVSESSION pSession, PCSUPDRVFACTORY pFactory); 1417 SUPR0DECL(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 */ 1426 typedef 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. */ 1443 typedef 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 */ 1451 typedef 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. */ 1459 typedef 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 */ 1467 typedef 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. */ 1473 typedef SUPDRVPROBEINFO *PSUPDRVPROBEINFO; 1474 1475 /** 1476 * Support driver tracepoint provider core. 1477 */ 1478 typedef 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. */ 1520 typedef SUPDRVVDTPROVIDERCORE *PSUPDRVVDTPROVIDERCORE; 1460 1521 1461 1522 /** Pointer to a tracer registration record. */ -
trunk/src/VBox/HostDrivers/Support/Makefile.kmk
r41092 r41117 87 87 SUPLib.cpp \ 88 88 SUPLibSem.cpp \ 89 SUPLibTracerA.asm \ 89 90 SUPR3HardenedIPRT.cpp \ 90 91 SUPR3HardenedVerify.cpp \ -
trunk/src/VBox/HostDrivers/Support/SUPDrv.c
r41068 r41117 697 697 /*pSession->uTracerData = 0;*/ 698 698 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);*/ 699 704 700 705 VBOXDRV_SESSION_CREATE(pSession, fUser); … … 1794 1799 PSUPTRACERUMODREG pReq = (PSUPTRACERUMODREG)pReqHdr; 1795 1800 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; 1796 1803 1797 1804 /* 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); 1799 1809 return 0; 1800 1810 } … … 1808 1818 /* execute */ 1809 1819 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; 1810 1831 return 0; 1811 1832 } -
trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h
r40982 r41117 32 32 */ 33 33 #include <iprt/types.h> 34 #include <VBox/sup.h> 34 35 35 36 /* … … 193 194 * - Remove RTSpinlockReleaseNoInts. 194 195 */ 195 #define SUPDRV_IOC_VERSION 0x001a000 1196 #define SUPDRV_IOC_VERSION 0x001a0002 196 197 197 198 /** SUP_IOCTL_COOKIE. */ … … 1266 1267 struct 1267 1268 { 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; 1270 1279 /** Future flags, MBZ. */ 1271 1280 uint32_t fFlags; … … 1303 1312 1304 1313 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) 1323 typedef struct SUPTRACERUMODFIREPROBE 1324 { 1325 /** The header. */ 1326 SUPREQHDR Hdr; 1327 union 1328 { 1329 SUPDRVTRACERUSRCTX In; 1330 } u; 1331 } SUPTRACERUMODFIREPROBE, *PSUPTRACERUMODFIREPROBE; 1332 /** @} */ 1333 1334 1305 1335 #pragma pack() /* paranoia */ 1306 1336 -
trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h
r41067 r41117 440 440 /** The thread currently actively talking to the tracer. (One at the time!) */ 441 441 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]; 442 454 #ifndef SUPDRV_AGNOSTIC 443 455 # if defined(RT_OS_DARWIN) … … 559 571 /** The number of session having opened the tracer currently. */ 560 572 uint32_t cTracerOpens; 573 /** The number of threads currently calling into the tracer. */ 574 uint32_t volatile cTracerCallers; 561 575 /** Set if the tracer is being unloaded. */ 562 576 bool fTracerUnloading; 577 /** Hash table for user tracer modules (SUPDRVVTGCOPY). */ 578 RTLISTANCHOR aTrackerUmodHash[128]; 563 579 564 580 /* … … 665 681 void VBOXCALL supdrvTracerModuleUnloading(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage); 666 682 void VBOXCALL supdrvTracerCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession); 683 int 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); 687 int VBOXCALL supdrvIOCtl_TracerUmodDeregister(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, RTR3PTR R3PtrVtgHdr); 688 void VBOXCALL supdrvIOCtl_TracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx); 667 689 int VBOXCALL supdrvIOCtl_TracerOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, uint32_t uCookie, uintptr_t uArg); 668 690 int VBOXCALL supdrvIOCtl_TracerClose(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession); … … 671 693 DECLASM(void) supdrvTracerProbeFireStub(void); 672 694 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 677 695 #ifdef VBOX_WITH_NATIVE_DTRACE 678 696 const SUPDRVTRACERREG * VBOXCALL supdrvDTraceInit(void); -
trunk/src/VBox/HostDrivers/Support/SUPDrvTracer.cpp
r40981 r41117 43 43 #include <iprt/semaphore.h> 44 44 #include <iprt/thread.h> 45 #include <iprt/param.h> 46 #include <iprt/uuid.h> 45 47 46 48 … … 48 50 * Structures and Typedefs * 49 51 *******************************************************************************/ 52 /** Pointer to a user tracer module registration record. */ 53 typedef struct SUPDRVTRACERUMOD *PSUPDRVTRACERUMOD; 54 50 55 /** 51 56 * Data for a tracepoint provider. … … 55 60 /** The entry in the provider list for this image. */ 56 61 RTLISTNODE ListEntry; 62 /** The entry in the per session provider list for this image. */ 63 RTLISTNODE SessionListEntry; 57 64 58 65 /** The core structure. */ … … 65 72 * SUPR0VtgRegisterDrv. NULL if pImage is set. */ 66 73 PSUPDRVSESSION pSession; 74 /** The user tracepoint module associated with this provider. NULL if 75 * pImage is set. */ 76 PSUPDRVTRACERUMOD pUmod; 67 77 68 78 /** Used to indicate that we've called pfnProviderDeregistered already and it … … 83 93 84 94 95 /** 96 * User tracer module VTG data copy. 97 */ 98 typedef 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. */ 117 typedef SUPDRVVTGCOPY *PSUPDRVVTGCOPY; 118 /** Magic value for SUPDRVVTGCOPY. */ 119 #define SUDPRVVTGCOPY_MAGIC UINT32_C(0x00080386) 120 121 122 /** 123 * User tracer module registration record. 124 */ 125 typedef 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 85 160 /******************************************************************************* 86 161 * Defined Constants And Macros * … … 99 174 /** The address of the current probe fire routine for kernel mode. */ 100 175 PFNRT g_pfnSupdrvProbeFireKernel = supdrvTracerProbeFireStub; 176 177 178 /******************************************************************************* 179 * Internal Functions * 180 *******************************************************************************/ 181 static void supdrvVtgReleaseObjectCopy(PSUPDRVDEVEXT pDevExt, PSUPDRVVTGCOPY pThis); 101 182 102 183 … … 136 217 137 218 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. */ 190 228 #define MY_WITHIN_IMAGE(p, rc) \ 191 229 do { \ … … 202 240 return (rc); \ 203 241 } 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 */ 256 static 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) \ 205 269 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 */ 457 static 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) \ 207 473 return VERR_SUPDRV_VTG_STRTAB_OFF; \ 208 rc = supdrvVtgValidateString( pVtgHdr->pachStrTab + (offStrTab)); \474 rc = supdrvVtgValidateString((char *)pVtgHdr + pVtgHdr->offStrTab + (a_offStrTab)); \ 209 475 if (rc != VINF_SUCCESS) \ 210 476 return rc; \ … … 223 489 * The header. 224 490 */ 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; 272 494 273 495 /* … … 277 499 while (i-- > 0) 278 500 { 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(p VtgHdr->paProviders[i].AttrModules);286 MY_VALIDATE_ATTR(p VtgHdr->paProviders[i].AttrFunctions);287 MY_VALIDATE_ATTR(p VtgHdr->paProviders[i].AttrNames);288 MY_VALIDATE_ATTR(p VtgHdr->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); 291 513 } 292 514 … … 297 519 while (i-- > 0) 298 520 { 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); 305 538 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].iFirstProbe313 >= 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].offObjHdr320 != (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;325 539 } 326 540 327 541 /* The referenced argument list. */ 328 pArgList = (PVTGDESCARGLIST)((uintptr_t)pVtgHdr->paArgLists + pVtgHdr->paProbes[i].offArgList);329 542 if (pArgList->cArgs > 16) 330 543 { … … 383 596 384 597 /* 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 } 391 606 392 607 /* 393 608 * Probe locations. 394 609 */ 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 } 410 623 } 411 624 412 625 return VINF_SUCCESS; 626 } 627 413 628 #undef MY_VALIDATE_STR 414 #undef MY_VALIDATE_ PTR629 #undef MY_VALIDATE_ATTR 415 630 #undef MY_WITHIN_IMAGE 416 }417 631 418 632 … … 427 641 { 428 642 Assert(offStrTab < pVtgHdr->cbStrTab); 429 return &pVtgHdr->pachStrTab[offStrTab];643 return (char *)pVtgHdr + pVtgHdr->offStrTab + offStrTab; 430 644 } 431 645 … … 439 653 { 440 654 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; 445 664 RT_ZERO(pProv->Core.TracerData); 446 665 RTMemFree(pProv); … … 449 668 450 669 /** 451 * Deregisters a provider.670 * Unlinks and deregisters a provider. 452 671 * 453 672 * If the provider is still busy, it will be put in the zombie list. … … 461 680 { 462 681 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 463 691 if (!pProv->fRegistered || !pDevExt->pTracerOps) 464 692 rc = VINF_SUCCESS; … … 471 699 } 472 700 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 474 712 RTListAppend(&pDevExt->TracerProviderZombieList, &pProv->ListEntry); 475 713 LOG_TRACER(("Invalidated provider '%s' / %p and put it on the zombie list (rc=%Rrc)\n", … … 521 759 RTListForEachSafe(&pDevExt->TracerProviderList, pProv, pProvNext, SUPDRVTPPROVIDER, ListEntry) 522 760 { 523 RTListNodeRemove(&pProv->ListEntry);524 761 supdrvTracerDeregisterVtgObj(pDevExt, pProv); 525 762 } … … 589 826 * @param pszName The driver name. 590 827 * @param pVtgHdr The VTG object header. 591 * @param pVtgObj The size of the VTG object.592 828 * @param pImage The image if applicable. 593 829 * @param pSession The session if applicable. 830 * @param pUmod The associated user tracepoint module if 831 * applicable. 594 832 * @param pszModName The module name. 595 833 */ 596 static int supdrvTracerRegisterVtgObj(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, size_t cbVtgObj,PSUPDRVLDRIMAGE pImage,597 PSUPDRVSESSION pSession, const char *pszModName)834 static int supdrvTracerRegisterVtgObj(PSUPDRVDEVEXT pDevExt, PVTGOBJHDR pVtgHdr, PSUPDRVLDRIMAGE pImage, 835 PSUPDRVSESSION pSession, PSUPDRVTRACERUMOD pUmod, const char *pszModName) 598 836 { 599 837 int rc; 600 838 uintptr_t i; 601 839 PSUPDRVTPPROVIDER pProv; 840 size_t cchModName; 602 841 603 842 /* … … 609 848 AssertPtrNullReturn(pSession, VERR_INVALID_POINTER); 610 849 AssertPtrReturn(pszModName, VERR_INVALID_POINTER); 850 cchModName = strlen(pszModName); 611 851 612 852 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*/); 614 856 else 615 rc = supdrvVtgValidate(pVtgHdr, cbVtgObj, NULL, 0);857 rc = supdrvVtgValidate(pVtgHdr, (uintptr_t)pVtgHdr, NULL, 0, pUmod != NULL); 616 858 if (RT_FAILURE(rc)) 617 859 return rc; 618 860 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 */ 619 865 rc = RTSemFastMutexRequest(pDevExt->mtxTracer); 620 866 if (RT_FAILURE(rc)) 621 867 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 } 634 895 } 635 896 } … … 644 905 while (i-- > 0) 645 906 { 646 PVTGDESCPROVIDER pDesc = &pVtgHdr->paProviders[i];907 PVTGDESCPROVIDER pDesc = (PVTGDESCPROVIDER)((uintptr_t)pVtgHdr + pVtgHdr->offProviders) + i; 647 908 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])); 650 912 if (pProv) 651 913 { 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 */ 662 955 rc = RTSemFastMutexRequest(pDevExt->mtxTracer); 663 956 if (RT_SUCCESS(rc)) … … 674 967 { 675 968 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); 676 976 RTSemFastMutexRelease(pDevExt->mtxTracer); 677 977 LOG_TRACER(("Registered tracepoint provider '%s' in '%s' -> %p\n", … … 683 983 LOG_TRACER(("Failed to register tracepoint provider '%s' in '%s' -> %Rrc\n", 684 984 pProv->szName, pszModName, rc)); 685 RTMemFree(pProv);686 985 } 687 986 } … … 690 989 rc = VERR_NO_MEMORY; 691 990 991 /* 992 * In case of failure, we have to undo any providers we already 993 * managed to register. 994 */ 692 995 if (RT_FAILURE(rc)) 693 996 { 694 997 PSUPDRVTPPROVIDER pProvNext; 695 supdrvTracerFreeProvider(pProv); 998 999 if (pProv) 1000 supdrvTracerFreeProvider(pProv); 696 1001 697 1002 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) 701 1006 { 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); 704 1017 } 705 1018 } … … 731 1044 LOG_TRACER(("SUPR0TracerRegisterDrv: pSession=%p pVtgHdr=%p pszName=%s\n", pSession, pVtgHdr, pszName)); 732 1045 733 rc = supdrvTracerRegisterVtgObj(pSession->pDevExt, pVtgHdr, _1M, NULL /*pImage*/, pSession, pszName);1046 rc = supdrvTracerRegisterVtgObj(pSession->pDevExt, pVtgHdr, NULL /*pImage*/, pSession, NULL /*pUmod*/, pszName); 734 1047 735 1048 /* … … 762 1075 */ 763 1076 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); 771 1080 } 772 1081 RTSemFastMutexRelease(pDevExt->mtxTracer); … … 793 1102 PSUPDRVLDRIMAGE pImage = (PSUPDRVLDRIMAGE)hMod; 794 1103 PSUPDRVDEVEXT pDevExt; 795 uintptr_t cbVtgObj;796 1104 int rc; 797 1105 … … 809 1117 AssertReturn(pDevExt->pLdrInitImage == pImage, VERR_WRONG_ORDER); 810 1118 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); 822 1125 LOG_TRACER(("SUPR0TracerRegisterModule: rc=%d\n", rc)); 823 1126 … … 1021 1324 else 1022 1325 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)); 1023 1336 } 1024 1337 … … 1179 1492 { 1180 1493 if (pProv->pImage == pImage) 1181 {1182 RTListNodeRemove(&pProv->ListEntry);1183 1494 supdrvTracerDeregisterVtgObj(pDevExt, pProv); 1184 }1185 1495 } 1186 1496 … … 1204 1514 { 1205 1515 /* 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); 1226 1526 1227 1527 /* … … 1230 1530 if (pSession->uTracerData) 1231 1531 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 1559 static 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 */ 1583 static 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 */ 1638 static 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 */ 1673 static 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 */ 1812 static 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 */ 1871 static 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 1916 int 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 2052 int 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 */ 2117 static 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 2168 SUPR0DECL(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 2177 void VBOXCALL supdrvIOCtl_TracerUmodProbeFire(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx) 2178 { 2179 supdrvTracerUmodProbeFire(pDevExt, pSession, pCtx); 1248 2180 } 1249 2181 … … 1434 2366 if (RT_SUCCESS(rc)) 1435 2367 { 2368 uint32_t i; 2369 1436 2370 pDevExt->TracerHlp.uVersion = SUPDRVTRACERHLP_VERSION; 1437 2371 /** @todo */ … … 1439 2373 RTListInit(&pDevExt->TracerProviderList); 1440 2374 RTListInit(&pDevExt->TracerProviderZombieList); 2375 for (i = 0; i < RT_ELEMENTS(pDevExt->aTrackerUmodHash); i++) 2376 RTListInit(&pDevExt->aTrackerUmodHash[i]); 1441 2377 1442 2378 #ifdef VBOX_WITH_NATIVE_DTRACE … … 1450 2386 */ 1451 2387 #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"); 1453 2389 if (RT_SUCCESS(rc)) 1454 2390 return rc; -
trunk/src/VBox/HostDrivers/Support/SUPLib.cpp
r40981 r41117 51 51 #include <VBox/param.h> 52 52 #include <VBox/log.h> 53 #include <VBox/VBoxTpG.h> 53 54 54 55 #include <iprt/assert.h> … … 2389 2390 2390 2391 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) 2392 typedef 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 */ 2410 static 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 */ 2439 static 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 2548 SUPR3DECL(int) SUPR3TracerRegisterModule(uintptr_t hModNative, const char *pszModule, struct VTGOBJHDR *pVtgHdr, 2549 RTUINTPTR uVtgHdrAddr, uint32_t fFlags) 2399 2550 { 2400 2551 /* Validate input. */ 2401 2552 NOREF(hModNative); 2402 2553 AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER); 2554 AssertReturn(!memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)), VERR_SUPDRV_VTG_MAGIC); 2403 2555 AssertPtrReturn(pszModule, VERR_INVALID_POINTER); 2404 2556 size_t cchModule = strlen(pszModule); … … 2407 2559 AssertReturn(fFlags == SUP_TRACER_UMOD_FLAGS_EXE || fFlags == SUP_TRACER_UMOD_FLAGS_SHARED, VERR_INVALID_PARAMETER); 2408 2560 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 */ 2410 2585 if (RT_UNLIKELY(g_u32FakeMode)) 2411 2586 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 2412 2602 2413 2603 /* … … 2421 2611 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT; 2422 2612 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; 2424 2617 Req.u.In.fFlags = fFlags; 2425 2618 … … 2451 2644 if (RT_SUCCESS(rc)) 2452 2645 rc = Req.Hdr.rc; 2646 2647 supr3TracerDestroyStrTab(pStrTab, (PVTGPROBELOC32)paProbeLocs, (PVTGPROBELOC64)paProbeLocs, 2648 cProbeLocs, pVtgHdr->cBits == 32); 2453 2649 return rc; 2454 2650 } … … 2459 2655 /* Validate input. */ 2460 2656 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 */ 2463 2669 if (RT_UNLIKELY(g_u32FakeMode)) 2464 2670 return VINF_SUCCESS; … … 2482 2688 } 2483 2689 2690 2691 DECLASM(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 56 56 (PFNRT)SUPR3PageAllocEx, 57 57 (PFNRT)SUPSemEventCreate, 58 (PFNRT)SUPTracerFireProbe, 58 59 #endif 59 60 (PFNRT)xmlModuleOpen, -
trunk/src/VBox/VMM/VMMR3/VM.cpp
r40975 r41117 160 160 161 161 #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); 163 164 #endif 164 165 -
trunk/src/bldprogs/VBoxTpG.cpp
r40975 r41117 37 37 #include <iprt/stream.h> 38 38 #include <iprt/string.h> 39 #include <iprt/uuid.h> 39 40 40 41 #include "scmstream.h" … … 474 475 " NAME(%%1):\n" 475 476 " %%endmacro\n" 476 " segment VTG.Obj public CLASS= DATAalign=4096 use32\n"477 " segment VTG.Obj public CLASS=VTG align=4096 use32\n" 477 478 "\n" 478 479 "%%elifdef ASM_FORMAT_MACHO\n" … … 502 503 " NAME(%%1):\n" 503 504 " %%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" 505 508 "VTG_GLOBAL g_aVTGPrLc, data\n" 506 509 " [section .VTGPrLc progbits alloc noexec write align=1]\n" 507 510 " [section .VTGPrLc.End progbits alloc noexec write align=1]\n" 508 511 "VTG_GLOBAL g_aVTGPrLc_End, data\n" 512 " dd 0,0,0,0, 0,0,0,0\n" 509 513 " [section .VTGData progbits alloc noexec write align=4096]\n" 510 514 "\n" … … 517 521 " ;0 1 2 3\n" 518 522 " ;012345678901234567890123456789012\n" 519 " db 'VTG Object Header v1. 4', 0, 0\n"523 " db 'VTG Object Header v1.5', 0, 0\n" 520 524 " 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" 521 536 " 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" 532 538 "%%ifdef ASM_FORMAT_MACHO ; Apple has a real decent linker!\n" 533 539 "extern section$start$__VTG$__VTGPrLc\n" 534 540 " RTCCPTR_DEF section$start$__VTG$__VTGPrLc\n" 541 " %%if ARCH_BITS == 32\n" 542 " dd 0\n" 543 " %%endif\n" 535 544 "extern section$end$__VTG$__VTGPrLc\n" 536 545 " RTCCPTR_DEF section$end$__VTG$__VTGPrLc\n" 546 " %%if ARCH_BITS == 32\n" 547 " dd 0\n" 548 " %%endif\n" 537 549 "%%else\n" 538 550 " 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" 540 558 "%%endif\n" 541 " RTCCPTR_DEF 0\n"542 " RTCCPTR_DEF 0\n"543 " RTCCPTR_DEF 0\n"544 " RTCCPTR_DEF 0\n"545 559 , 546 560 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); 551 565 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]); 574 569 575 570 /* … … 595 590 "; The argument lists.\n" 596 591 ";\n" 592 "ALIGNDATA(16)\n" 597 593 "VTG_GLOBAL g_aVTGArgLists, data\n"); 598 594 uint32_t off = 0; … … 665 661 "; Prob definitions.\n" 666 662 ";\n" 663 "ALIGNDATA(16)\n" 667 664 "VTG_GLOBAL g_aVTGProbes, data\n" 668 665 "\n"); … … 676 673 ScmStreamPrintf(pStrm, 677 674 "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" 685 680 , 686 681 pProvider->pszName, pProbe->pszMangledName, iProbe, … … 700 695 701 696 /* 702 * The provider sdata.697 * The provider data. 703 698 */ 704 699 ScmStreamPrintf(pStrm, … … 707 702 "; Provider data.\n" 708 703 ";\n" 704 "ALIGNDATA(16)\n" 709 705 "VTG_GLOBAL g_aVTGProviders, data\n"); 710 706 iProvider = 0; … … 735 731 } 736 732 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 737 764 738 765 /* … … 942 969 { 943 970 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", 947 974 pProv->pszName, pProbe->pszMangledName, 948 975 pProv->pszName, pProbe->pszMangledName, … … 956 983 ");\n" 957 984 "# define %s_ENABLED() \\\n" 958 " (RT_UNLIKELY(g_ fVTGProbeEnabled_%s_%s)) \n"985 " (RT_UNLIKELY(g_cVTGProbeEnabled_%s_%s)) \n" 959 986 "# define %s(" 960 987 , szTmp, … … 971 998 ") \\\n" 972 999 " do { \\\n" 973 " if (RT_UNLIKELY(g_ fVTGProbeEnabled_%s_%s)) \\\n"1000 " if (RT_UNLIKELY(g_cVTGProbeEnabled_%s_%s)) \\\n" 974 1001 " { \\\n" 975 1002 " 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" 977 1004 " VTGProbeStub_%s_%s(&s_VTGProbeLoc", 978 1005 pProv->pszName, pProbe->pszMangledName,
Note:
See TracChangeset
for help on using the changeset viewer.