Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

436 lines
11 KiB

  1. /*++
  2. Module Name:
  3. ktrace.c
  4. Abstract:
  5. This module implements a tracing facility for use by all kernel mode
  6. modules in Windows NT.
  7. Author:
  8. Roy D'Souza (rdsouza@gomez) 22-May-1996
  9. Environment:
  10. User or Kernel mode.
  11. Revision History:
  12. --*/
  13. #include "ki.h"
  14. #if DBG && IA64_KTRACE
  15. #include "ktrace.h"
  16. #include "ktracep.h"
  17. /***********************************************************************
  18. Format of KTrace record (144 bytes)
  19. ***********************************************************************/
  20. typedef struct _KTRACE_RECORD_ {
  21. ULONG ModuleID;
  22. USHORT MessageType;
  23. USHORT MessageIndex;
  24. LARGE_INTEGER SystemTime;
  25. ULONGLONG Arg1;
  26. ULONGLONG Arg2;
  27. ULONGLONG Arg3;
  28. ULONGLONG Arg4;
  29. ULONGLONG Arg5;
  30. LARGE_INTEGER HiResTimeStamp;
  31. } KTRACE_RECORD, *PKTRACE_RECORD;
  32. /* IF YOU MAKE ANY CHANGE TO THE ABOVE TYPEDEF YOU
  33. ALSO NEED TO UPDATE THE CONSTANT RECORD_SIZE_IN_BYTES
  34. IN FILE KTRACEP.H, SO THAT THE SIMDB MACROS WILL CONTINUE
  35. TO WORK CORRECTLY
  36. */
  37. /***********************************************************************
  38. KTrace Private Data
  39. ***********************************************************************/
  40. KTRACE_RECORD KTrace[MAXIMUM_PROCESSORS][KTRACE_LOG_SIZE];
  41. //
  42. // Current queue head
  43. //
  44. static ULONG KTraceQueueHead = 0;
  45. //
  46. // By default the mask is on for all:
  47. //
  48. static ULONG ModuleIDMask = 0xFFFFFFFF;
  49. /***********************************************************************
  50. KeEnableKTrace - selectively enable/disable client's rights to trace
  51. ***********************************************************************/
  52. VOID
  53. NTAPI
  54. KeEnableKTrace (
  55. ULONG IDMask
  56. )
  57. /*++
  58. Routine Description:
  59. Selectively enable or disable individual module's abilities to
  60. write to the KTrace.
  61. By default all modules are permitted to write traces.
  62. Any kernel mode modules can call this routine to toggle write
  63. write permissions.
  64. Arguments:
  65. IDMask
  66. A bit pattern which specifies the modules that are to be enabled.
  67. Return Value:
  68. None.
  69. --*/
  70. {
  71. ModuleIDMask = IDMask;
  72. return;
  73. } // KeEnableKTrace
  74. /***********************************************************************
  75. CurrentKTraceEntry -- return address of current entry and update trace index
  76. ***********************************************************************/
  77. PKTRACE_RECORD CurrentEntry = 0;
  78. PKTRACE_RECORD
  79. NTAPI
  80. KiCurrentKTraceEntry (
  81. )
  82. /*++
  83. Routine Description:
  84. Provide pointer to next trace entry for use by assembly code that updates trace
  85. table.
  86. Arguments:
  87. None.
  88. Return Value:
  89. Pointer to next entry.
  90. --*/
  91. {
  92. ULONG CurrentProcessor;
  93. CurrentProcessor = KeGetCurrentProcessorNumber();
  94. if (CurrentProcessor > MAXIMUM_PROCESSORS) {
  95. DbgPrint("KTrace:CurrentKTraceEntry:KeGetCurrentProcessorNumber invalid\n");
  96. return NULL;
  97. }
  98. CurrentEntry = &KTrace[CurrentProcessor][KTraceQueueHead];
  99. KTraceQueueHead = (KTraceQueueHead + 1) % KTRACE_LOG_SIZE;
  100. return CurrentEntry;
  101. } // CurrentKTraceEntry
  102. /***********************************************************************
  103. AddTrace - add an entry into the trace.
  104. ***********************************************************************/
  105. NTSTATUS
  106. NTAPI
  107. KeAddKTrace (
  108. ULONG ModuleID,
  109. USHORT MessageType,
  110. USHORT MessageIndex,
  111. ULONGLONG Arg1,
  112. ULONGLONG Arg2,
  113. ULONGLONG Arg3,
  114. ULONGLONG Arg4
  115. )
  116. /*++
  117. Routine Description:
  118. Add a record to the KTrace log. Can be called by anybody in the
  119. kernel. (Need to figure out a way to export this through ntoskrnl.lib
  120. so that drivers can access it.)
  121. Arguments:
  122. ModuleID identifies the client making this call. See ktrace.h
  123. for definitions.
  124. MessageType specifies the type/severity of the message (i.e. warning,
  125. error, checkpoint...) See ktrace.h
  126. Arg1-4 for unrestricted use by the client.
  127. Return Value:
  128. Status
  129. STATUS_SUCCESS if successful.
  130. STATUS_UNSUCCESSFUL if failure.
  131. --*/
  132. {
  133. ULONG CurrentProcessor;
  134. LARGE_INTEGER PerfCtr;
  135. NTSTATUS Status = STATUS_SUCCESS;
  136. LARGE_INTEGER SystemTime;
  137. if (!(ModuleID & ModuleIDMask))
  138. return STATUS_UNSUCCESSFUL;
  139. CurrentProcessor = KeGetCurrentProcessorNumber();
  140. if (CurrentProcessor > MAXIMUM_PROCESSORS) {
  141. DbgPrint("KTrace:AddTrace:KeGetCurrentProcessorNumber invalid\n");
  142. return STATUS_UNSUCCESSFUL;
  143. }
  144. KTrace[CurrentProcessor][KTraceQueueHead].ModuleID = ModuleID;
  145. KTrace[CurrentProcessor][KTraceQueueHead].MessageType = MessageType;
  146. KTrace[CurrentProcessor][KTraceQueueHead].MessageIndex = MessageIndex;
  147. KTrace[CurrentProcessor][KTraceQueueHead].Arg1 = Arg1;
  148. KTrace[CurrentProcessor][KTraceQueueHead].Arg2 = Arg2;
  149. KTrace[CurrentProcessor][KTraceQueueHead].Arg3 = Arg3;
  150. KTrace[CurrentProcessor][KTraceQueueHead].Arg4 = Arg4;
  151. KeQuerySystemTime(&SystemTime);
  152. KTrace[CurrentProcessor][KTraceQueueHead].SystemTime = SystemTime;
  153. #if 0
  154. Status = NtQueryPerformanceCounter(&PerfCtr, NULL);
  155. if (!NT_SUCCESS(Status)) {
  156. DbgPrint("NtQueryPerformanceCounter failed with %x\n", Status);
  157. return Status;
  158. }
  159. KTrace[CurrentProcessor][KTraceQueueHead].HiResTimeStamp = PerfCtr;
  160. #endif
  161. KTraceQueueHead = (KTraceQueueHead + 1) % KTRACE_LOG_SIZE;
  162. return Status;
  163. } // AddTrace
  164. /***********************************************************************
  165. QueryDumpKTraceBuffer - API query: selectively dump trace
  166. ***********************************************************************/
  167. LONG
  168. NTAPI
  169. KeQueryDumpKTrace (
  170. ULONG Processor,
  171. ULONG StartEntry,
  172. ULONG NumberOfEntries,
  173. ULONG ModuleFilter,
  174. ULONG MessageFilter,
  175. BOOLEAN Sort)
  176. /*++
  177. Routine Description:
  178. Arguments:
  179. ProcessorMask
  180. Specify the particular processor of interest.
  181. StartEntry
  182. The offset from the start of the queue to start dumping records.
  183. If this entry is 0 then the dumping starts from the head of the
  184. queue.
  185. If this argument is specified to be larger than the size of the
  186. KTrace buffer, then the dump wraps around appropriately.
  187. NumberOfEntries
  188. The number of log entries to dump starting from StartEntry.
  189. ModuleFilter
  190. A bit pattern specifying the modules of interest. See ktrace.h
  191. for a definition of modules. Only the logs of these modules are
  192. included in the dump. Bits representing undefined modules are
  193. ignored.
  194. MessageFilter
  195. A bit pattern specifying the subset of message types to dump. See
  196. ktrace.h for definitions of all message types.
  197. Sort
  198. Sort the output before dumping. Base the sort on the global NT
  199. timestamp. Most recent entries are dumped first. (NOT IMPLEMENTED
  200. YET).
  201. Return Value:
  202. The number of records that were dumped.
  203. Returns -1 if error.
  204. --*/
  205. {
  206. ULONG Index = StartEntry;
  207. ULONG RecordCount = 0;
  208. //
  209. // Verify that we have a valid processor number:
  210. //
  211. #if !defined(NT_UP)
  212. if (Processor > KeRegisteredProcessors) {
  213. DbgPrint("KTrace error: attempt to access invalid processor"
  214. "%d on a system with %d processors\n",
  215. Processor,
  216. KeRegisteredProcessors);
  217. return 0L;
  218. }
  219. #else
  220. if (Processor > 0) {
  221. DbgPrint("KTrace error: attempted to access invalid processor"
  222. "%d on a uni-processor system\n",
  223. Processor);
  224. }
  225. #endif
  226. //
  227. // Loop through the entire KTrace
  228. //
  229. while (NumberOfEntries > 0) {
  230. //
  231. // See if the current record matches the query criteria
  232. //
  233. if ((ModuleFilter & KTrace[Processor][Index].ModuleID) &&
  234. (MessageFilter & KTrace[Processor][Index].MessageType)) {
  235. DumpRecord(Processor, Index);
  236. RecordCount++;
  237. }
  238. NumberOfEntries = NumberOfEntries - 1;
  239. Index = Index > 0 ? Index - 1 : KTRACE_LOG_SIZE - 1;
  240. }
  241. return RecordCount;
  242. } // QueryDumpKTraceBuffer
  243. /***********************************************************************
  244. KePurgeKTrace - delete all records from the trace.
  245. ***********************************************************************/
  246. VOID
  247. NTAPI
  248. KePurgeKTrace (
  249. )
  250. {
  251. ULONG Index1, Index2;
  252. for (Index1 = 0; Index1 < KTRACE_LOG_SIZE; Index1++) {
  253. for (Index2 = 0; Index2 < MAXIMUM_PROCESSORS; Index2++) {
  254. KTrace[Index2][Index1].ModuleID = 0;
  255. KTrace[Index2][Index1].MessageType = 0;
  256. KTrace[Index2][Index1].MessageIndex = 0;
  257. KTrace[Index2][Index1].SystemTime.HighPart = 0;
  258. KTrace[Index2][Index1].SystemTime.LowPart = 0;
  259. KTrace[Index2][Index1].Arg1 = 0;
  260. KTrace[Index2][Index1].Arg2 = 0;
  261. KTrace[Index2][Index1].Arg3 = 0;
  262. KTrace[Index2][Index1].Arg4 = 0;
  263. KTrace[Index2][Index1].HiResTimeStamp.HighPart = 0;
  264. KTrace[Index2][Index1].HiResTimeStamp.LowPart = 0;
  265. }
  266. }
  267. }
  268. /***********************************************************************
  269. DumpRecord - dump a single record specified by processor number & index.
  270. ***********************************************************************/
  271. VOID
  272. NTAPI
  273. DumpRecord (IN ULONG ProcessorNumber,
  274. IN ULONG Index)
  275. /*++
  276. Routine Description:
  277. Dumps out the specified record in the trace associated with the
  278. specified processor out to the remote debugger console.
  279. Arguments:
  280. ProcessorNumber
  281. The processor whose associated trace log is to be accessed.
  282. Index
  283. The offset of the record in the trace to be dumped.
  284. Return Value:
  285. None.
  286. --*/
  287. {
  288. #if !defined(NT_UP)
  289. if (ProcessorNumber > KeRegisteredProcessors) {
  290. DbgPrint("KTrace:DumpRecord:"
  291. "illegal processor number %x in a %x-processor system\n",
  292. ProcessorNumber, KeRegisteredProcessors);
  293. return;
  294. }
  295. #else
  296. if (ProcessorNumber > 0) {
  297. DbgPrint("KTrace:DumpRecord:"
  298. "illegal processor %x in a uni-processor system\n",
  299. ProcessorNumber);
  300. }
  301. #endif
  302. DbgPrint("Dumping Record Index [%ld], Processor = [%ld]\n",
  303. Index);
  304. DbgPrint("\tModuleID = [%lx]\n",
  305. KTrace[ProcessorNumber][Index].ModuleID);
  306. DbgPrint("\tMessageType = [%lx]\n",
  307. KTrace[ProcessorNumber][Index].MessageType);
  308. DbgPrint("\tMessageIndex = [%lx]\n",
  309. KTrace[ProcessorNumber][Index].MessageIndex);
  310. DbgPrint("\tArg1= [%lx%LX]\n",
  311. KTrace[ProcessorNumber][Index].Arg1,
  312. KTrace[ProcessorNumber][Index].Arg1);
  313. DbgPrint("\tArg2= [%lx%LX]\n",
  314. KTrace[ProcessorNumber][Index].Arg2,
  315. KTrace[ProcessorNumber][Index].Arg2);
  316. DbgPrint("\tArg3= [%lx%LX]\n",
  317. KTrace[ProcessorNumber][Index].Arg3,
  318. KTrace[ProcessorNumber][Index].Arg3);
  319. DbgPrint("\tArg4= [%lx%LX]\n",
  320. KTrace[ProcessorNumber][Index].Arg4,
  321. KTrace[ProcessorNumber][Index].Arg4);
  322. } // DumpRecord
  323. #endif // DBG
  324. // end ktrace.c