Leaked source code of windows server 2003
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.

4349 lines
118 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. cpuinfo.c
  5. Abstract:
  6. WinDbg Extension Api
  7. Author:
  8. Peter Johnston (peterj) 19-April-1999
  9. Environment:
  10. User Mode.
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #include "i386.h"
  15. #include "amd64.h"
  16. #include "ia64.h"
  17. #pragma hdrstop
  18. #define MAXIMUM_IA64_VECTOR 256
  19. #if !defined(ROUND_UP)
  20. //
  21. // Macro to round Val up to the next Bnd boundary. Bnd must be an integral
  22. // power of two.
  23. //
  24. #define ROUND_UP( Val, Bnd ) \
  25. (((Val) + ((Bnd) - 1)) & ~((Bnd) - 1))
  26. #endif // !ROUND_UP
  27. VOID
  28. DumpCpuInfoIA64(
  29. ULONG processor,
  30. BOOLEAN doHead
  31. )
  32. {
  33. HRESULT Hr;
  34. ULONG number;
  35. ULONG64 prcb;
  36. UCHAR vendorString[16];
  37. if (doHead)
  38. {
  39. dprintf("CP M/R/F/A Manufacturer SerialNumber Features Speed\n");
  40. }
  41. Hr = g_ExtData->ReadProcessorSystemData(processor,
  42. DEBUG_DATA_KPRCB_OFFSET,
  43. &prcb,
  44. sizeof(prcb),
  45. NULL);
  46. if (Hr != S_OK)
  47. {
  48. return;
  49. }
  50. if ( GetFieldValue(prcb, "nt!_KPRCB", "ProcessorVendorString", vendorString) ) {
  51. dprintf("Unable to read VendorString from Processor %u KPRCB, quitting\n", processor);
  52. return;
  53. }
  54. if ( InitTypeRead( prcb, nt!_KPRCB )) {
  55. dprintf("Unable to read KPRCB for processor %u, quitting.\n", processor);
  56. return;
  57. }
  58. number = (ULONG)ReadField(Number);
  59. if ( number != processor ) {
  60. //
  61. // Processor number isn't what we expected. Bail out.
  62. // This will need revisiting at some stage in the future
  63. // when we support a discontiguous set of processor numbers.
  64. //
  65. dprintf("Processor %d mismatch with processor number in KPRCB = %d, quitting\n",
  66. processor,
  67. number );
  68. return;
  69. }
  70. dprintf("%2d %d,%d,%d,%d %-16s %016I64x %016I64x %ld Mhz\n",
  71. number,
  72. (ULONG) ReadField(ProcessorModel),
  73. (ULONG) ReadField(ProcessorRevision),
  74. (ULONG) ReadField(ProcessorFamily),
  75. (ULONG) ReadField(ProcessorArchRev),
  76. vendorString,
  77. (ULONGLONG) ReadField(ProcessorSerialNumber),
  78. (ULONGLONG) ReadField(ProcessorFeatureBits),
  79. (ULONG) ReadField(MHz)
  80. );
  81. return;
  82. }
  83. VOID
  84. DumpCpuInfoX86(
  85. ULONG processor,
  86. BOOLEAN doHead
  87. )
  88. {
  89. HRESULT Hr;
  90. ULONG64 Prcb;
  91. UCHAR sigWarn1, sigWarn2;
  92. LARGE_INTEGER updateSignature;
  93. PROCESSORINFO pi;
  94. if (doHead)
  95. {
  96. dprintf("CP F/M/S Manufacturer MHz Update Signature Features\n");
  97. }
  98. if (!Ioctl(IG_KD_CONTEXT, &pi, sizeof(pi))) {
  99. dprintf("Unable to get processor info, quitting\n");
  100. return;
  101. }
  102. CHAR VendorString[20]={0};
  103. Hr = g_ExtData->ReadProcessorSystemData(processor,
  104. DEBUG_DATA_KPRCB_OFFSET,
  105. &Prcb,
  106. sizeof(Prcb),
  107. NULL);
  108. if (Hr != S_OK)
  109. {
  110. return;
  111. }
  112. if (InitTypeRead(Prcb, nt!_KPRCB)) {
  113. dprintf("Unable to read PRCB for processor %u, quitting.\n",
  114. processor);
  115. return;
  116. }
  117. if ((ULONG) ReadField(Number) != processor) {
  118. //
  119. // Processor number isn't what I expected. Bail out.
  120. // This will need revisiting at some stage in the future
  121. // when we support a discontiguous set of processor numbers.
  122. //
  123. dprintf("Processor %d mismatch with processor number in PRCB %d, quitting\n",
  124. processor,
  125. (ULONG) ReadField(Number));
  126. return;
  127. }
  128. if (ReadField(CpuID) == 0) {
  129. //
  130. // This processor doesn't support CPUID,... not likely in
  131. // an MP environment but also means we don't have anything
  132. // useful to say.
  133. //
  134. dprintf("Processor %d doesn't support CPUID, quitting.\n",
  135. processor);
  136. return;
  137. }
  138. //
  139. // If this is an Intel processor, family 6 (or, presumably
  140. // above family 6) read the current UpdateSignature from
  141. // the processor rather than using what was there when we
  142. // booted,... it may havee been updated.
  143. //
  144. // Actually, this can't be done unless we can switch processors
  145. // from within an extension. So, mark the processor we did
  146. // it for (unless there's only one processor).
  147. //
  148. *((PULONG64) &updateSignature) = ReadField(UpdateSignature);
  149. sigWarn1 = sigWarn2 = ' ';
  150. GetFieldValue(Prcb, "nt!_KPRCB", "VendorString", VendorString);
  151. if ((!strcmp(VendorString, "GenuineIntel")) &&
  152. ((ULONG) ReadField(CpuType) >= 6)) {
  153. if ((ULONG) ReadField(Number) == pi.Processor)
  154. {
  155. if (TargetMachine == IMAGE_FILE_MACHINE_I386)
  156. {
  157. READ_WRITE_MSR msr;
  158. msr.Msr = 0x8b;
  159. msr.Value = 0;
  160. if (Ioctl(IG_READ_MSR, &msr, sizeof(msr)))
  161. {
  162. updateSignature.QuadPart = msr.Value;
  163. }
  164. }
  165. if (pi.NumberProcessors != 1)
  166. {
  167. sigWarn1 = '>';
  168. sigWarn2 = '<';
  169. }
  170. }
  171. }
  172. //
  173. // This extension could pretty much be !PRCB but it's a
  174. // subset,... perhaps we should have a !PRCB?
  175. //
  176. dprintf("%2d %d,%d,%d %12s%5d%c%08x%08x%c%08x\n",
  177. (ULONG) ReadField(Number),
  178. (ULONG) ReadField(CpuType),
  179. ((ULONG) ReadField(CpuStep) >> 8) & 0xff,
  180. (ULONG) ReadField(CpuStep) & 0xff,
  181. VendorString,
  182. (ULONG) ReadField(MHz),
  183. sigWarn1,
  184. updateSignature.u.HighPart,
  185. updateSignature.u.LowPart,
  186. sigWarn2,
  187. (ULONG) ReadField(FeatureBits));
  188. }
  189. DECLARE_API( cpuinfo )
  190. /*++
  191. Routine Description:
  192. Gather up any info we know is still in memory that we gleaned
  193. using the CPUID instruction,.... and a few other interesting
  194. tidbits as well.
  195. Arguments:
  196. None
  197. Return Value:
  198. None
  199. --*/
  200. {
  201. ULONG64 processor;
  202. BOOLEAN first = TRUE;
  203. ULONG64 NumProcessors = 0;
  204. INIT_API();
  205. g_ExtControl->GetNumberProcessors((PULONG) &NumProcessors);
  206. if (GetExpressionEx(args, &processor, &args))
  207. {
  208. //
  209. // The user specified a procesor number.
  210. //
  211. if (processor >= NumProcessors)
  212. {
  213. dprintf("cpuinfo: invalid processor number specified\n");
  214. }
  215. else
  216. {
  217. NumProcessors = processor + 1;
  218. }
  219. }
  220. else
  221. {
  222. //
  223. // Enumerate all the processors
  224. //
  225. processor = 0;
  226. }
  227. while (processor < NumProcessors)
  228. {
  229. switch( TargetMachine )
  230. {
  231. case IMAGE_FILE_MACHINE_I386:
  232. case IMAGE_FILE_MACHINE_AMD64:
  233. DumpCpuInfoX86((ULONG)processor, first);
  234. break;
  235. case IMAGE_FILE_MACHINE_IA64:
  236. DumpCpuInfoIA64((ULONG)processor, first);
  237. break;
  238. default:
  239. dprintf("!cpuinfo not supported for this target machine: %ld\n", TargetMachine);
  240. processor = NumProcessors;
  241. }
  242. processor++;
  243. first = FALSE;
  244. }
  245. EXIT_API();
  246. return S_OK;
  247. }
  248. DECLARE_API( irql )
  249. /*++
  250. Routine Description:
  251. Displays the current irql
  252. Arguments:
  253. args - the processor number ( default is 0 )
  254. Return Value:
  255. None
  256. --*/
  257. {
  258. HRESULT Hr;
  259. ULONG64 Address=0;
  260. ULONG Processor;
  261. ULONG Prcb;
  262. ULONG Irql;
  263. INIT_API();
  264. if (!*args)
  265. {
  266. GetCurrentProcessor(Client, &Processor, NULL);
  267. }
  268. else
  269. {
  270. Processor = (ULONG) GetExpression(args);
  271. }
  272. Hr = g_ExtData->ReadProcessorSystemData(Processor,
  273. DEBUG_DATA_KPRCB_OFFSET,
  274. &Address,
  275. sizeof(Address),
  276. NULL);
  277. if (Hr != S_OK)
  278. {
  279. dprintf("Cannot get PRCB address\n");
  280. return E_INVALIDARG;
  281. }
  282. if (GetFieldValue(Address, "nt!_KPRCB", "DebuggerSavedIRQL", Irql))
  283. {
  284. dprintf("Current IRQL not queryable from the debugger on this OS\n");
  285. }
  286. else
  287. {
  288. dprintf("Current IRQL -- %d\n", Irql);
  289. }
  290. EXIT_API();
  291. return S_OK;
  292. }
  293. DECLARE_API( prcb )
  294. /*++
  295. Routine Description:
  296. Displays the PRCB
  297. Arguments:
  298. args - the processor number ( default is 0 )
  299. Return Value:
  300. None
  301. --*/
  302. {
  303. HRESULT Hr;
  304. ULONG64 Address=0;
  305. ULONG Processor;
  306. ULONG Prcb;
  307. ULONG Irql;
  308. INIT_API();
  309. if (!*args)
  310. {
  311. GetCurrentProcessor(Client, &Processor, NULL);
  312. }
  313. else
  314. {
  315. Processor = (ULONG) GetExpression(args);
  316. }
  317. Hr = g_ExtData->ReadProcessorSystemData(Processor,
  318. DEBUG_DATA_KPRCB_OFFSET,
  319. &Address,
  320. sizeof(Address),
  321. NULL);
  322. if (Hr != S_OK)
  323. {
  324. dprintf("Cannot get PRCB address\n");
  325. EXIT_API();
  326. return E_INVALIDARG;
  327. }
  328. if (InitTypeRead(Address, nt!_KPRCB) )
  329. {
  330. dprintf("Unable to read PRCB\n");
  331. EXIT_API();
  332. return E_INVALIDARG;
  333. }
  334. dprintf("PRCB for Processor %d at %p:\n",
  335. Processor, Address);
  336. if (!GetFieldValue(Address, "nt!_KPRCB", "DebuggerSavedIRQL", Irql))
  337. {
  338. dprintf("Current IRQL -- %d\n", Irql);
  339. }
  340. dprintf("Threads-- Current %p Next %p Idle %p\n",
  341. ReadField(CurrentThread),
  342. ReadField(NextThread),
  343. ReadField(IdleThread));
  344. dprintf("Number %d SetMember %08lx\n",
  345. (ULONG) ReadField(Number),
  346. (ULONG) ReadField(SetMember));
  347. dprintf("Interrupt Count -- %08lx\n",
  348. (ULONG) ReadField(InterruptCount));
  349. dprintf("Times -- Dpc %08lx Interrupt %08lx \n",
  350. (ULONG) ReadField(DpcTime),
  351. (ULONG) ReadField(InterruptTime));
  352. dprintf(" Kernel %08lx User %08lx \n",
  353. (ULONG) ReadField(KernelTime),
  354. (ULONG) ReadField(UserTime));
  355. EXIT_API();
  356. return S_OK;
  357. }
  358. DECLARE_API( frozen )
  359. /*++
  360. Routine Description:
  361. Displays which processors are in frozen state
  362. Arguments:
  363. args - not used
  364. Return Value:
  365. None
  366. --*/
  367. {
  368. HRESULT Hr;
  369. ULONG64 Address=0;
  370. ULONG Processor;
  371. ULONG NumProcessors;
  372. ULONG CurrentProc;
  373. INIT_API();
  374. GetCurrentProcessor(Client, &CurrentProc, NULL);
  375. Hr = g_ExtControl->GetNumberProcessors((PULONG) &NumProcessors);
  376. if (Hr != S_OK)
  377. {
  378. dprintf("Cannot get number of processors\n");
  379. EXIT_API();
  380. return Hr;
  381. }
  382. dprintf("Processor states:\n");
  383. for (Processor = 0; Processor < NumProcessors; Processor++)
  384. {
  385. ULONG Frozen;
  386. Hr = g_ExtData->ReadProcessorSystemData(Processor,
  387. DEBUG_DATA_KPRCB_OFFSET,
  388. &Address,
  389. sizeof(Address),
  390. NULL);
  391. if (Hr != S_OK)
  392. {
  393. dprintf("Cannot get PRCB address for processor %ld\n", Processor);
  394. EXIT_API();
  395. return E_INVALIDARG;
  396. }
  397. if (Hr = GetFieldValue(Address, "nt!_KPRCB", "IpiFrozen", Frozen) )
  398. {
  399. dprintf("Unable to read PRCB @ %p\n", Address);
  400. EXIT_API();
  401. return Hr;
  402. } else
  403. {
  404. PSTR State;
  405. if (Processor == CurrentProc)
  406. {
  407. State = "Current";
  408. } else if (Frozen)
  409. {
  410. State = "Frozen";
  411. } else
  412. {
  413. State = "Running";
  414. }
  415. dprintf(" %2ld : %s\n", Processor, State);
  416. }
  417. }
  418. EXIT_API();
  419. return S_OK;
  420. }
  421. VOID
  422. DumpPcrX86(
  423. ULONG64 pPcr
  424. )
  425. {
  426. ULONG ListHeadOff;
  427. PROCESSORINFO pi;
  428. ULONG64 Prcb, DpcFlink;
  429. ULONG DpcDataOff;
  430. InitTypeRead(pPcr, nt!_KPCR);
  431. //
  432. // Print out the PCR
  433. //
  434. dprintf("\tNtTib.ExceptionList: %08lx\n", (ULONG) ReadField(NtTib.ExceptionList));
  435. dprintf("\t NtTib.StackBase: %08lx\n", (ULONG) ReadField(NtTib.StackBase));
  436. dprintf("\t NtTib.StackLimit: %08lx\n", (ULONG) ReadField(NtTib.StackLimit));
  437. dprintf("\t NtTib.SubSystemTib: %08lx\n", (ULONG) ReadField(NtTib.SubSystemTib));
  438. dprintf("\t NtTib.Version: %08lx\n", (ULONG) ReadField(NtTib.Version));
  439. dprintf("\t NtTib.UserPointer: %08lx\n", (ULONG) ReadField(NtTib.ArbitraryUserPointer));
  440. dprintf("\t NtTib.SelfTib: %08lx\n", (ULONG) ReadField(NtTib.Self));
  441. dprintf("\n");
  442. dprintf("\t SelfPcr: %08lx\n", (ULONG) ReadField(SelfPcr));
  443. dprintf("\t Prcb: %08lx\n", (ULONG) ReadField(Prcb));
  444. dprintf("\t Irql: %08lx\n", (ULONG) ReadField(Irql));
  445. dprintf("\t IRR: %08lx\n", (ULONG) ReadField(IRR));
  446. dprintf("\t IDR: %08lx\n", (ULONG) ReadField(IDR));
  447. dprintf("\t InterruptMode: %08lx\n", (ULONG) ReadField(InterruptMode));
  448. dprintf("\t IDT: %08lx\n", (ULONG) ReadField(IDT));
  449. dprintf("\t GDT: %08lx\n", (ULONG) ReadField(GDT));
  450. dprintf("\t TSS: %08lx\n", (ULONG) ReadField(TSS));
  451. dprintf("\n");
  452. dprintf("\t CurrentThread: %08lx\n", (ULONG) ReadField(PrcbData.CurrentThread));
  453. dprintf("\t NextThread: %08lx\n", (ULONG) ReadField(PrcbData.NextThread));
  454. dprintf("\t IdleThread: %08lx\n", (ULONG) ReadField(PrcbData.IdleThread));
  455. GetKdContext( &pi );
  456. dprintf("\n");
  457. dprintf( "\t DpcQueue: ");
  458. if (GetFieldOffset("nt!_KPCR", "PrcbData.DpcData", &DpcDataOff))
  459. {
  460. DpcFlink = ReadField(PrcbData.DpcListHead.Flink);
  461. GetFieldOffset("nt!_KPRCB", "DpcListHead", &ListHeadOff);
  462. } else
  463. {
  464. GetFieldValue(pPcr + DpcDataOff, "nt!_KDPC_DATA", "DpcListHead.Flink", DpcFlink);
  465. GetFieldOffset("nt!_KDPC_DATA", "DpcListHead.Flink", &ListHeadOff);
  466. GetFieldOffset("nt!_KPRCB", "DpcData", &DpcDataOff); // get DpcData offset in KPRCB
  467. ListHeadOff += DpcDataOff;
  468. }
  469. Prcb = ReadField(Prcb);
  470. while (DpcFlink != (Prcb + ListHeadOff )) {
  471. CHAR Name[0x100];
  472. ULONG64 Displacement, DeferredRoutine;
  473. Name[0] = 0;
  474. dprintf(" 0x%p ", (DpcFlink) - 4 );
  475. if (GetFieldValue( DpcFlink - 4, "nt!_KDPC", "DeferredRoutine", DeferredRoutine )) {
  476. dprintf( "Failed to read DPC at 0x%p\n", DpcFlink - 4 );
  477. break;
  478. }
  479. GetSymbol( DeferredRoutine, Name, &Displacement );
  480. dprintf("0x%p %s\n\t ", DeferredRoutine, Name );
  481. if (CheckControlC()) {
  482. break;
  483. }
  484. GetFieldValue( DpcFlink - 4, "nt!_KDPC", "DpcListEntry.Flink", DpcFlink);
  485. }
  486. dprintf("\n");
  487. }
  488. DECLARE_API( pcr )
  489. /*++
  490. Routine Description:
  491. Arguments:
  492. args -
  493. Return Value:
  494. None
  495. --*/
  496. {
  497. ULONG Processor = 0;
  498. ULONG64 Pkpcr;
  499. ULONG MajorVersion, Off;
  500. HRESULT Hr;
  501. INIT_API();
  502. if (!*args)
  503. {
  504. GetCurrentProcessor(Client, &Processor, NULL);
  505. }
  506. else
  507. {
  508. Processor = (ULONG) GetExpression(args);
  509. }
  510. Hr = g_ExtData->ReadProcessorSystemData(Processor,
  511. DEBUG_DATA_KPCR_OFFSET,
  512. &Pkpcr,
  513. sizeof(Pkpcr),
  514. NULL);
  515. if (Hr != S_OK)
  516. {
  517. dprintf("Cannot get PRCB address\n");
  518. return E_INVALIDARG;
  519. }
  520. if (GetFieldValue(Pkpcr, "nt!_KPCR", "MajorVersion", MajorVersion)) {
  521. dprintf("Unable to read the PCR at %p\n", Pkpcr);
  522. return E_INVALIDARG;
  523. }
  524. //
  525. // Print out some interesting fields
  526. //
  527. InitTypeRead(Pkpcr, nt!_KPCR);
  528. dprintf("KPCR for Processor %d at %08p:\n", Processor, Pkpcr);
  529. dprintf(" Major %d Minor %d\n",
  530. MajorVersion,
  531. (ULONG) ReadField(MinorVersion));
  532. switch (TargetMachine) {
  533. case IMAGE_FILE_MACHINE_I386:
  534. DumpPcrX86(Pkpcr);
  535. break;
  536. case IMAGE_FILE_MACHINE_IA64:
  537. dprintf("\n");
  538. dprintf("\t Prcb: %016I64X\n", ReadField(Prcb));
  539. dprintf("\t CurrentThread: %016I64X\n", ReadField(CurrentThread));
  540. dprintf("\t InitialStack: %016I64X\n", ReadField(InitialStack));
  541. dprintf("\t StackLimit: %016I64X\n", ReadField(StackLimit));
  542. dprintf("\t InitialBStore: %016I64X\n", ReadField(InitialBStore));
  543. dprintf("\t BStoreLimit: %016I64X\n", ReadField(BStoreLimit));
  544. dprintf("\t PanicStack: %016I64X\n", ReadField(PanicStack));
  545. dprintf("\t CurrentIrql: 0x%lx\n", (ULONG)ReadField(CurrentIrql));
  546. dprintf("\n");
  547. break;
  548. default:
  549. dprintf("Panic Stack %08p\n", ReadField(PanicStack));
  550. dprintf("Dpc Stack %08p\n", ReadField(DpcStack));
  551. dprintf("Irql addresses:\n");
  552. GetFieldOffset("KPCR", "IrqlMask", &Off);
  553. dprintf(" Mask %08p\n",Pkpcr + Off);
  554. GetFieldOffset("KPCR", "IrqlTable", &Off);
  555. dprintf(" Table %08p\n", Pkpcr + Off);
  556. GetFieldOffset("KPCR", "InterruptRoutine", &Off);
  557. dprintf(" Routine %08p\n", Pkpcr + Off);
  558. } /* switch */
  559. EXIT_API();
  560. return S_OK;
  561. }
  562. #define TYPE_NO_MATCH 0xFFFE
  563. #define IH_WITH_SYMBOLS TRUE
  564. #define IH_WITHOUT_SYMBOLS FALSE
  565. typedef struct _INTERRUPTION_MAP {
  566. ULONG Type;
  567. PCSTR Name;
  568. PCSTR OptionalField;
  569. } INTERRUPTION_MAP;
  570. static INTERRUPTION_MAP CodeToName[] = {
  571. 0x0, "VHPT FAULT", "IFA",
  572. 0x4, "ITLB FAULT", "IIPA",
  573. 0x8, "DTLB FAULT", "IFA",
  574. 0xc, "ALT ITLB FAULT", "IIPA",
  575. 0x10, "ALT DTLB FAULT", "IFA",
  576. 0x14, "DATA NESTED TLB", "IFA",
  577. 0x18, "INST KEY MISS", "IIPA",
  578. 0x1c, "DATA KEY MISS", "IFA",
  579. 0x20, "DIRTY BIT FAULT", "IFA",
  580. 0x24, "INST ACCESS BIT", "IIPA",
  581. 0x28, "DATA ACCESS BIT", "IFA",
  582. 0x2c, "BREAK INST FAULT", "IIM",
  583. 0x30, "EXTERNAL INTERRUPT", "IVR",
  584. 0x50, "PAGE NOT PRESENT", "IFA",
  585. 0x51, "KEY PERMISSION", "IFA",
  586. 0x52, "INST ACCESS RIGHT", "IIPA",
  587. 0x53, "DATA ACCESS RIGHT", "IFA",
  588. 0x54, "GENERAL EXCEPTION", "ISR",
  589. 0x55, "DISABLED FP FAULT", "ISR",
  590. 0x56, "NAT CONSUMPTION", "ISR",
  591. 0x57, "SPECULATION FAULT", "IIM",
  592. 0x59, "DEBUG FAULT", "ISR",
  593. 0x5a, "UNALIGNED REF", "IFA",
  594. 0x5b, "LOCKED DATA REF", "ISR",
  595. 0x5c, "FP FAULT", "ISR",
  596. 0x5d, "FP TRAP", "ISR",
  597. 0x5e, "LOWER PRIV TRAP", "IIPA",
  598. 0x5f, "TAKEN BRANCH TRAP", "IIPA",
  599. 0x60, "SINGLE STEP TRAP", "IIPA",
  600. 0x69, "IA32 EXCEPTION", "R0",
  601. 0x6a, "IA32 INTERCEPT", "R0",
  602. 0x6b, "IA32 INTERRUPT", "R0",
  603. 0x80, "KERNEL SYSCALL", "Num",
  604. 0x81, "USER SYSCALL", "Num",
  605. 0x90, "THREAD SWITCH", "OSP",
  606. 0x91, "PROCESS SWITCH", "OSP",
  607. TYPE_NO_MATCH, " ", "OPT"
  608. };
  609. #define DumpHistoryValidIIP( _IHistoryRecord ) \
  610. ( ((_IHistoryRecord).InterruptionType != 0x90 /* THREAD_SWITCH */) && \
  611. ((_IHistoryRecord).InterruptionType != 0x91 /* PROCESS_SWITCH */) )
  612. VOID
  613. DumpHistory(
  614. IHISTORY_RECORD History[],
  615. ULONG Count,
  616. BOOLEAN WithSymbols
  617. )
  618. {
  619. ULONG index;
  620. ULONG i;
  621. BOOL printed;
  622. dprintf("Total # of interruptions = %lu\n", Count);
  623. dprintf("Vector IIP IPSR ExtraField %s\n", WithSymbols ? " IIP Symbol" : "" );
  624. Count = (ULONG)(Count % MAX_NUMBER_OF_IHISTORY_RECORDS);
  625. for (index = 0; index < MAX_NUMBER_OF_IHISTORY_RECORDS; index++) {
  626. printed = FALSE;
  627. for (i = 0; i < sizeof(CodeToName)/sizeof(CodeToName[0]); i++) {
  628. if (History[Count].InterruptionType == CodeToName[i].Type) {
  629. CCHAR symbol[256];
  630. PCHAR s;
  631. ULONG64 displacement;
  632. ULONGLONG iip;
  633. iip = History[Count].IIP;
  634. s = "";
  635. if ( WithSymbols && DumpHistoryValidIIP( History[Count]) ) {
  636. symbol[0] = '!';
  637. GetSymbol( iip, symbol, &displacement);
  638. s = (PCHAR)symbol + strlen( (PCHAR)symbol );
  639. if (s == (PCHAR)symbol ) {
  640. // sprintf( s, (IsPtr64() ? "0x%I64x" : "0x%08x"), iip );
  641. sprintf( s, "0x%016I64x", iip );
  642. }
  643. else {
  644. if ( displacement ) {
  645. // sprintf( s, (IsPtr64() ? "+0x%016I64x" : "+0x%08x"), displacement );
  646. sprintf( s, "+0x%I64x", displacement );
  647. }
  648. }
  649. s = symbol;
  650. }
  651. dprintf( "%18s %16I64x %16I64x %s= %16I64x %s\n",
  652. CodeToName[i].Name,
  653. iip,
  654. History[Count].IPSR,
  655. CodeToName[i].OptionalField,
  656. History[Count].Extra0,
  657. s
  658. );
  659. printed = TRUE;
  660. break;
  661. }
  662. }
  663. if ( !printed ) {
  664. dprintf("VECTOR 0x%lx - unknown for !ih...\n", History[Count].InterruptionType);
  665. }
  666. Count++;
  667. if (Count == MAX_NUMBER_OF_IHISTORY_RECORDS) Count = 0;
  668. }
  669. return;
  670. } // DumpHistory
  671. HRESULT DoIH(
  672. PDEBUG_CLIENT Client,
  673. PCSTR args,
  674. BOOLEAN WithSymbols
  675. )
  676. /*++
  677. Routine Description:
  678. WorkHorse function to dump processors interrupt history records
  679. Arguments:
  680. Client - debug engine interface client
  681. args - the processor number ( default is the current )
  682. WithSymbols - BOOLEAN to specify with or without the IIP Symbols
  683. Return Value:
  684. HRESULT
  685. --*/
  686. {
  687. ULONG processor;
  688. ULONG interruptionCount;
  689. ULONG64 pcrAddress;
  690. HRESULT Hr;
  691. //
  692. // This extension is IA64 specific...
  693. //
  694. if ( TargetMachine != IMAGE_FILE_MACHINE_IA64 )
  695. {
  696. dprintf("ih: IA64 specific extension...\n");
  697. return E_INVALIDARG;
  698. }
  699. INIT_API();
  700. GetCurrentProcessor(Client, &processor, NULL);
  701. if ( *args )
  702. {
  703. processor = (ULONG)GetExpression( args );
  704. }
  705. Hr = g_ExtData->ReadProcessorSystemData(processor,
  706. DEBUG_DATA_KPCR_OFFSET,
  707. &pcrAddress,
  708. sizeof(pcrAddress),
  709. NULL);
  710. if (Hr != S_OK)
  711. {
  712. dprintf("ih: Cannot get PCR address\n");
  713. }
  714. else
  715. {
  716. if (GetFieldValue( pcrAddress, "NT!_KPCR", "InterruptionCount", interruptionCount ) )
  717. {
  718. dprintf("ih: failed to read KPCR for processor %lu\n", processor);
  719. Hr = E_INVALIDARG;
  720. }
  721. else
  722. {
  723. //
  724. // Read and display Interrupt history
  725. //
  726. ULONG result;
  727. IHISTORY_RECORD history[MAX_NUMBER_OF_IHISTORY_RECORDS];
  728. if (!ReadMemory(pcrAddress+0x1000,
  729. (PVOID)history,
  730. sizeof(history),
  731. &result))
  732. {
  733. dprintf("ih: unable to read interrupt history records at %p - result=%lu\n",
  734. pcrAddress + 0x1000, result);
  735. Hr = E_INVALIDARG;
  736. }
  737. else
  738. {
  739. DumpHistory(history, interruptionCount, WithSymbols);
  740. }
  741. }
  742. }
  743. EXIT_API();
  744. return Hr;
  745. } // DoIH()
  746. DECLARE_API( ihs )
  747. /*++
  748. Routine Description:
  749. Dumps the interrupt history records with IIP symbols
  750. Arguments:
  751. args - the processor number ( default is current processor )
  752. Return Value:
  753. None
  754. --*/
  755. {
  756. return( DoIH( Client, args, IH_WITH_SYMBOLS ) );
  757. } // !ihs
  758. DECLARE_API( ih )
  759. /*++
  760. Routine Description:
  761. Dumps the interrupt history records
  762. Arguments:
  763. args - the processor number ( default is current processor )
  764. Return Value:
  765. None
  766. --*/
  767. {
  768. return( DoIH( Client, args, IH_WITHOUT_SYMBOLS ) );
  769. } // !ih
  770. VOID
  771. DumpBTHistory(
  772. ULONGLONG Bth[], // Branch Trace record
  773. ULONG64 BthAddress, // BTH Virtual Address
  774. ULONG MaxBtrNumber // Maximum number of records
  775. )
  776. {
  777. ULONG rec;
  778. dprintf( "BTH @ 0x%I64x:\n"
  779. " b mp slot address symbol\n"
  780. , BthAddress);
  781. for ( rec = 0; rec < (MaxBtrNumber - 1) ; rec++ ) {
  782. DisplayBtbPmdIA64( " ", Bth[rec], DISPLAY_MIN );
  783. }
  784. DisplayBtbIndexPmdIA64( "BTB Index: ", Bth[rec], DISPLAY_MIN );
  785. return;
  786. } // DumpBTHistory()
  787. DECLARE_API( bth )
  788. /*++
  789. Routine Description:
  790. Dumps the IA-64 branch trace buffer saved in _KPCR.
  791. The '!btb' extension dumps the processor branch trace buffer configuration and trace registers.
  792. Arguments:
  793. args - the processor number ( default is the current processor )
  794. Return Value:
  795. None
  796. --*/
  797. {
  798. ULONG processor;
  799. ULONG64 pcrAddress;
  800. HRESULT Hr;
  801. //
  802. // This extension is IA64 specific...
  803. //
  804. if ( TargetMachine != IMAGE_FILE_MACHINE_IA64 )
  805. {
  806. dprintf("ih: IA64 specific extension...\n");
  807. return E_INVALIDARG;
  808. }
  809. INIT_API();
  810. GetCurrentProcessor(Client, &processor, NULL);
  811. if ( *args )
  812. {
  813. processor = (ULONG)GetExpression( args );
  814. }
  815. Hr = g_ExtData->ReadProcessorSystemData(processor,
  816. DEBUG_DATA_KPCR_OFFSET,
  817. &pcrAddress,
  818. sizeof(pcrAddress),
  819. NULL);
  820. if (Hr != S_OK)
  821. {
  822. dprintf("Cannot get PCR address\n");
  823. }
  824. else
  825. {
  826. ULONG pcrSize;
  827. pcrSize = GetTypeSize("nt!_KPCR");
  828. if ( pcrSize == 0 ) {
  829. dprintf( "bth: failed to get _KPCR size\n" );
  830. Hr = E_FAIL;
  831. }
  832. else {
  833. ULONG result;
  834. ULONG64 bthAddress;
  835. ULONGLONG bth[MAX_NUMBER_OF_BTBHISTORY_RECORDS];
  836. pcrSize = ROUND_UP( pcrSize, 16 );
  837. bthAddress = pcrAddress + (ULONG64)pcrSize;
  838. if ( !ReadMemory( bthAddress, bth, sizeof(bth), &result ) ) {
  839. dprintf( "bth: unable to read branch trace history records at %p - result=%lu\n",
  840. bthAddress, result);
  841. Hr = E_FAIL;
  842. }
  843. else {
  844. DumpBTHistory( bth, bthAddress, (ULONG)(sizeof(bth)/sizeof(bth[0])) );
  845. }
  846. }
  847. }
  848. EXIT_API();
  849. return Hr;
  850. } // !bth
  851. DECLARE_API( btb )
  852. /*++
  853. Routine Description:
  854. Dumps the IA-64 branch trace buffer.
  855. Arguments:
  856. args - the processor number ( default is the current processor )
  857. Return Value:
  858. None
  859. --*/
  860. {
  861. ULONG processor;
  862. ULONG64 msr;
  863. ULONG reg;
  864. HRESULT Hr = S_OK;
  865. UNREFERENCED_PARAMETER (args);
  866. //
  867. // This extension is IA64 specific...
  868. //
  869. if ( TargetMachine != IMAGE_FILE_MACHINE_IA64 )
  870. {
  871. dprintf("ih: IA64 specific extension...\n");
  872. return E_INVALIDARG;
  873. }
  874. INIT_API();
  875. GetCurrentProcessor(Client, &processor, NULL);
  876. dprintf("BTB for processor %ld:\n"
  877. " b mp slot address symbol\n"
  878. , processor);
  879. // Thierry 11/20/2000 - FIXFIX - This is Itanium specific. Should be using PMD[] but
  880. // not currently collected in _KSPECIAL_REGISTERS.
  881. for ( reg = 0; reg < 8; reg++) {
  882. msr = 0;
  883. ReadMsr( 680 + reg, &msr );
  884. DisplayBtbPmdIA64( " ", msr, DISPLAY_MIN );
  885. }
  886. EXIT_API();
  887. return Hr;
  888. } // !btb
  889. DECLARE_API( idt )
  890. {
  891. ULONG64 Pkpcr;
  892. ULONG64 Address;
  893. ULONG64 IdtAddress;
  894. ULONG DispatchCodeOffset;
  895. ULONG ListEntryOffset;
  896. ULONG64 currentIdt, endIdt;
  897. ULONG64 displacement;
  898. ULONG64 unexpectedStart, unexpectedEnd;
  899. ULONG64 firstIntObj;
  900. ULONG64 flink;
  901. ULONG idtEntrySize;
  902. CHAR buffer[100];
  903. ULONG processor;
  904. ULONG idtChainCount;
  905. HRESULT Hr;
  906. USHORT interruptObjectType;
  907. BOOL bShowAll = FALSE;
  908. BOOL bTaskGate = FALSE;
  909. switch (TargetMachine)
  910. {
  911. case IMAGE_FILE_MACHINE_I386:
  912. currentIdt = 0x30;
  913. break;
  914. case IMAGE_FILE_MACHINE_AMD64:
  915. currentIdt = 0;
  916. break;
  917. case IMAGE_FILE_MACHINE_IA64:
  918. dprintf("Use !ivt on IA64\n");
  919. return E_INVALIDARG;
  920. default:
  921. dprintf("Unsupported platform\n");
  922. return E_INVALIDARG;
  923. }
  924. INIT_API();
  925. GetCurrentProcessor(Client, &processor, NULL);
  926. Hr = g_ExtData->ReadProcessorSystemData(processor,
  927. DEBUG_DATA_KPCR_OFFSET,
  928. &Pkpcr,
  929. sizeof(Pkpcr),
  930. NULL);
  931. EXIT_API();
  932. if (Hr != S_OK)
  933. {
  934. dprintf("Cannot get PCR address\n");
  935. return E_INVALIDARG;
  936. }
  937. endIdt = 0xfe;
  938. while(*args)
  939. {
  940. switch (*args)
  941. {
  942. case ' ':
  943. args++;
  944. continue;
  945. case '-':
  946. case '/':
  947. args++;
  948. if (*args == 'a')
  949. {
  950. currentIdt = 0;
  951. bShowAll = TRUE;
  952. args++;
  953. break;
  954. }
  955. else
  956. {
  957. dprintf("!idt [-a] [vector]\n");
  958. return E_INVALIDARG;
  959. }
  960. default:
  961. if (GetExpressionEx(args, &currentIdt, &args))
  962. {
  963. endIdt = currentIdt+1;
  964. bShowAll = TRUE;
  965. } else
  966. {
  967. dprintf("Bad argument '%s'\n", args);
  968. return E_INVALIDARG;
  969. }
  970. break;
  971. }
  972. }
  973. if ((endIdt - currentIdt) > 10000)
  974. {
  975. dprintf("Range is too big %p , %p\n", currentIdt, endIdt);
  976. }
  977. //
  978. // Find the offset of the Dispatch Code in the
  979. // interrupt object, so that we can simulate
  980. // a "CONTAINING_RECORD" later.
  981. //
  982. GetFieldOffset("nt!_KINTERRUPT", "DispatchCode", &DispatchCodeOffset);
  983. GetFieldOffset("nt!_KINTERRUPT", "InterruptListEntry", &ListEntryOffset);
  984. interruptObjectType = (USHORT)GetExpression("val nt!InterruptObject");
  985. InitTypeRead(Pkpcr, nt!_KPCR);
  986. if (TargetMachine == IMAGE_FILE_MACHINE_I386)
  987. {
  988. IdtAddress = ReadField(IDT);
  989. unexpectedStart = GetExpression("nt!KiStartUnexpectedRange");
  990. unexpectedEnd = GetExpression("nt!KiEndUnexpectedRange");
  991. idtEntrySize = GetTypeSize("nt!_KIDTENTRY");
  992. }
  993. else if (TargetMachine == IMAGE_FILE_MACHINE_AMD64)
  994. {
  995. IdtAddress = ReadField(IdtBase);
  996. unexpectedStart = GetExpression("nt!KxUnexpectedInterrupt1");
  997. unexpectedEnd = GetExpression("nt!KxUnexpectedInterrupt255");
  998. idtEntrySize = GetTypeSize("nt!_KIDTENTRY64");
  999. }
  1000. if (!unexpectedStart || !unexpectedEnd)
  1001. {
  1002. dprintf("\n\nCan't read kernel symbols.\n");
  1003. return E_INVALIDARG;
  1004. }
  1005. dprintf("\nDumping IDT:\n\n");
  1006. for (; currentIdt < endIdt; currentIdt++) {
  1007. if (CheckControlC()) {
  1008. break;
  1009. }
  1010. Address = (ULONG64)(IdtAddress + (currentIdt * idtEntrySize));
  1011. if (TargetMachine == IMAGE_FILE_MACHINE_I386) {
  1012. InitTypeRead(Address, nt!_KIDTENTRY);
  1013. Address = ReadField(ExtendedOffset) & 0xFFFFFFFF;
  1014. Address <<= 16;
  1015. Address |= ReadField(Offset) & 0xFFFF;
  1016. Address |= 0xFFFFFFFF00000000;
  1017. bTaskGate = (ReadField(Access) & 0x1F00) == 0x0500;
  1018. } else if (TargetMachine == IMAGE_FILE_MACHINE_AMD64) {
  1019. InitTypeRead(Address, nt!_KIDTENTRY64);
  1020. Address = ReadField(OffsetHigh) & 0xFFFFFFFF;
  1021. Address <<= 16;
  1022. Address |= ReadField(OffsetMiddle) & 0xFFFF;
  1023. Address <<= 16;
  1024. Address |= ReadField(OffsetLow) & 0xFFFF;
  1025. }
  1026. if ((Address >= unexpectedStart) && (Address <= unexpectedEnd))
  1027. {
  1028. if (!bShowAll)
  1029. {
  1030. continue;
  1031. }
  1032. }
  1033. dprintf("%x:", currentIdt);
  1034. if (bTaskGate)
  1035. {
  1036. dprintf("\tTask Selector = 0x%04X\n", ReadField(Selector));
  1037. continue;
  1038. }
  1039. //
  1040. // Work backwards from the code to the containing interrupt
  1041. // object.
  1042. //
  1043. Address -= DispatchCodeOffset;
  1044. firstIntObj = Address;
  1045. idtChainCount = 0;
  1046. InitTypeRead(Address, nt!_KINTERRUPT);
  1047. dprintf("\t%p ", Address + DispatchCodeOffset);
  1048. if (ReadField(Type) != interruptObjectType)
  1049. {
  1050. GetSymbol(Address + DispatchCodeOffset, buffer, &displacement);
  1051. if (buffer[0] != '\0') {
  1052. if (displacement != 0) {
  1053. dprintf("%s+0x%I64X", buffer, displacement);
  1054. } else {
  1055. dprintf("%s", buffer);
  1056. }
  1057. }
  1058. dprintf("\n");
  1059. continue;
  1060. }
  1061. while (TRUE) {
  1062. GetSymbol(ReadField(ServiceRoutine), buffer, &displacement);
  1063. if (buffer[0] != '\0') {
  1064. if (displacement != 0) {
  1065. dprintf("%s+0x%I64X (KINTERRUPT %p)\n", buffer, displacement, Address);
  1066. } else {
  1067. dprintf("%s (KINTERRUPT %p)\n", buffer, Address);
  1068. }
  1069. } else {
  1070. dprintf("%p (KINTERRUPT %p)\n", ReadField(ServiceRoutine), Address);
  1071. }
  1072. InitTypeRead(ListEntryOffset + Address, nt!_LIST_ENTRY);
  1073. flink = ReadField(Flink);
  1074. if (flink == 0 ||
  1075. flink == (firstIntObj + ListEntryOffset)) {
  1076. break;
  1077. }
  1078. Address = flink - ListEntryOffset;
  1079. InitTypeRead(Address, nt!_KINTERRUPT);
  1080. if (CheckControlC()) {
  1081. return E_ABORT;
  1082. }
  1083. if (idtChainCount++ > 50) {
  1084. //
  1085. // We are clearly going nowhere.
  1086. //
  1087. break;
  1088. }
  1089. dprintf("\t\t ");
  1090. }
  1091. }
  1092. dprintf("\n");
  1093. return S_OK;
  1094. }
  1095. DECLARE_API( ivt )
  1096. {
  1097. ULONG64 Pkpcr;
  1098. ULONG64 Address;
  1099. ULONG64 idtEntry;
  1100. ULONG DispatchCodeOffset;
  1101. ULONG ListEntryOffset;
  1102. ULONG InterruptRoutineOffset;
  1103. ULONG64 unexpectedInterrupt;
  1104. ULONG64 chainedDispatch;
  1105. ULONG64 PcrInterruptRoutineAddress;
  1106. ULONG currentIdt, endIdt;
  1107. BOOL argsPresent = FALSE;
  1108. ULONG64 firstIntObj;
  1109. ULONG idtEntrySize;
  1110. CHAR buffer[100];
  1111. ULONG processor;
  1112. ULONG idtChainCount;
  1113. HRESULT Hr;
  1114. ULONG64 displacement;
  1115. ULONG result;
  1116. USHORT interruptObjectType;
  1117. if ( IMAGE_FILE_MACHINE_IA64 != TargetMachine) {
  1118. dprintf("Don't know how to dump the IVT on anything but IA64, use !idt on x86\n");
  1119. return E_INVALIDARG;
  1120. }
  1121. INIT_API();
  1122. GetCurrentProcessor(Client, &processor, NULL);
  1123. Hr = g_ExtData->ReadProcessorSystemData(processor,
  1124. DEBUG_DATA_KPCR_OFFSET,
  1125. &Pkpcr,
  1126. sizeof(Pkpcr),
  1127. NULL);
  1128. EXIT_API();
  1129. if (Hr != S_OK)
  1130. {
  1131. dprintf("Cannot get PCR address\n");
  1132. return E_INVALIDARG;
  1133. }
  1134. unexpectedInterrupt = GetExpression("nt!KxUnexpectedInterrupt");
  1135. if (unexpectedInterrupt == 0) {
  1136. dprintf("\n\nCan't read kernel symbols.\n");
  1137. return E_INVALIDARG;
  1138. }
  1139. chainedDispatch = GetExpression("nt!KiChainedDispatch");
  1140. interruptObjectType = (USHORT)GetExpression("val nt!InterruptObject");
  1141. GetFieldOffset("nt!_KINTERRUPT", "DispatchCode", &DispatchCodeOffset);
  1142. GetFieldOffset("nt!_KINTERRUPT", "InterruptListEntry", &ListEntryOffset);
  1143. GetFieldOffset("nt!_KPCR", "InterruptRoutine", &InterruptRoutineOffset);
  1144. unexpectedInterrupt += DispatchCodeOffset;
  1145. idtEntrySize = GetTypeSize("nt!PKINTERRUPT_ROUTINE");
  1146. if (argsPresent = strlen(args) ? TRUE : FALSE) {
  1147. currentIdt = strtoul(args, NULL, 16);
  1148. endIdt = currentIdt+1;
  1149. if (currentIdt >= MAXIMUM_IA64_VECTOR) {
  1150. dprintf("\n\nInvalid argument \"%s\", maximum vector = %d\n", args, MAXIMUM_IA64_VECTOR);
  1151. return E_INVALIDARG;
  1152. }
  1153. } else {
  1154. currentIdt = 0;
  1155. endIdt = MAXIMUM_IA64_VECTOR;
  1156. }
  1157. dprintf("\nDumping IA64 IVT:\n\n");
  1158. PcrInterruptRoutineAddress = Pkpcr + InterruptRoutineOffset;
  1159. for (; currentIdt < endIdt; currentIdt++) {
  1160. if (CheckControlC()) {
  1161. break;
  1162. }
  1163. Address = (ULONG64)(PcrInterruptRoutineAddress + (currentIdt * idtEntrySize));
  1164. if (!ReadMemory(Address, &idtEntry, sizeof(idtEntry), &result)) {
  1165. dprintf( "Can't read entry for vector %02X at %p - result=%lu\n",
  1166. currentIdt, Address, result);
  1167. break;
  1168. }
  1169. Address = idtEntry;
  1170. if (Address == unexpectedInterrupt) {
  1171. //
  1172. // IDT entry contains "unexpected interrupt." This
  1173. // means that this vector isn't interesting.
  1174. //
  1175. if (argsPresent) {
  1176. //
  1177. // The user was specifying a specific vector.
  1178. //
  1179. dprintf("Vector %x not connected\n", currentIdt);
  1180. }
  1181. continue;
  1182. }
  1183. dprintf("\n%x:\n", currentIdt);
  1184. //
  1185. // Work backwards from the code to the containing interrupt
  1186. // object.
  1187. //
  1188. Address -= DispatchCodeOffset;
  1189. firstIntObj = Address;
  1190. idtChainCount = 0;
  1191. InitTypeRead(Address, nt!_KINTERRUPT);
  1192. if (ReadField(Type) != interruptObjectType)
  1193. {
  1194. GetSymbol(Address + DispatchCodeOffset, buffer, &displacement);
  1195. if (buffer[0] != '\0') {
  1196. if (displacement != 0) {
  1197. dprintf("\t%s+0x%I64X\n", buffer, displacement);
  1198. } else {
  1199. dprintf("\t%s\n", buffer);
  1200. }
  1201. } else {
  1202. dprintf("\t%p\n", Address + DispatchCodeOffset);
  1203. }
  1204. continue;
  1205. }
  1206. while (TRUE) {
  1207. GetSymbol(ReadField(ServiceRoutine), buffer, &displacement);
  1208. if (buffer[0] != '\0') {
  1209. if (displacement != 0) {
  1210. dprintf("\t%s+0x%I64X (%p)\n", buffer, displacement, Address);
  1211. } else {
  1212. dprintf("\t%s (%p)\n", buffer, Address);
  1213. }
  1214. } else {
  1215. dprintf("\t%p (%p)\n", ReadField(ServiceRoutine), Address);
  1216. }
  1217. if (ReadField(DispatchAddress) != chainedDispatch) {
  1218. break;
  1219. }
  1220. InitTypeRead(ListEntryOffset + Address, nt!_LIST_ENTRY);
  1221. if (ReadField(Flink) == (firstIntObj + ListEntryOffset)) {
  1222. break;
  1223. }
  1224. Address = ReadField(Flink) - ListEntryOffset;
  1225. InitTypeRead(Address, nt!_KINTERRUPT);
  1226. if (CheckControlC()) {
  1227. return E_ABORT;
  1228. }
  1229. if (idtChainCount++ > 50) {
  1230. //
  1231. // We are clearly going nowhere.
  1232. //
  1233. break;
  1234. }
  1235. }
  1236. }
  1237. dprintf("\n");
  1238. return S_OK;
  1239. }
  1240. //
  1241. // MCA MSR architecture definitions
  1242. //
  1243. //
  1244. // MSR addresses for Pentium Style Machine Check Exception
  1245. //
  1246. #define MCE_MSR_MC_ADDR 0x0
  1247. #define MCE_MSR_MC_TYPE 0x1
  1248. //
  1249. // MSR addresses for Pentium Pro Style Machine Check Architecture
  1250. //
  1251. //
  1252. // Global capability, status and control register addresses
  1253. //
  1254. #define MCA_MSR_MCG_CAP 0x179
  1255. #define MCA_MSR_MCG_STATUS 0x17a
  1256. #define MCA_MSR_MCG_CTL 0x17b
  1257. #define MCA_MSR_MCG_EAX 0x180
  1258. #define MCA_MSR_MCG_EFLAGS 0x188
  1259. #define MCA_MSR_MCG_EIP 0x189
  1260. //
  1261. // Control, Status, Address, and Misc register address for
  1262. // bank 0. Other bank registers are at a stride of MCA_NUM_REGS
  1263. // from corresponding bank 0 register.
  1264. //
  1265. #define MCA_NUM_REGS 4
  1266. #define MCA_MSR_MC0_CTL 0x400
  1267. #define MCA_MSR_MC0_STATUS 0x401
  1268. #define MCA_MSR_MC0_ADDR 0x402
  1269. #define MCA_MSR_MC0_MISC 0x403
  1270. //
  1271. // Flags used to determine if the MCE or MCA feature is
  1272. // available. Used with HalpFeatureBits.
  1273. //
  1274. #define HAL_MCA_PRESENT 0x4
  1275. #define HAL_MCE_PRESENT 0x8
  1276. //
  1277. // Flags to decode errors in MCI_STATUS register of MCA banks
  1278. //
  1279. #define MCA_EC_NO_ERROR 0x0000
  1280. #define MCA_EC_UNCLASSIFIED 0x0001
  1281. #define MCA_EC_ROMPARITY 0x0002
  1282. #define MCA_EC_EXTERN 0x0003
  1283. #define MCA_EC_FRC 0x0004
  1284. #include "pshpack1.h"
  1285. //
  1286. // Global Machine Check Capability Register
  1287. //
  1288. typedef struct _MCA_MCG_CAPABILITY {
  1289. union {
  1290. struct {
  1291. ULONG McaCnt:8;
  1292. ULONG McaCntlPresent:1;
  1293. ULONG McaExtPresent:1;
  1294. ULONG Reserved_1: 6;
  1295. ULONG McaExtCnt: 8;
  1296. ULONG Reserved_2: 8;
  1297. ULONG Reserved_3;
  1298. } hw;
  1299. ULONGLONG QuadPart;
  1300. } u;
  1301. } MCA_MCG_CAPABILITY, *PMCA_MCG_CAPABILITY;
  1302. //
  1303. // Global Machine Check Status Register
  1304. //
  1305. typedef struct _MCA_MCG_STATUS {
  1306. union {
  1307. struct {
  1308. ULONG RestartIPValid:1;
  1309. ULONG ErrorIPValid:1;
  1310. ULONG McCheckInProgress:1;
  1311. ULONG Reserved_1:29;
  1312. ULONG Reserved_2;
  1313. } hw;
  1314. ULONGLONG QuadPart;
  1315. } u;
  1316. } MCA_MCG_STATUS, *PMCA_MCG_STATUS;
  1317. //
  1318. // MCA COD field in status register for interpreting errors
  1319. //
  1320. typedef struct _MCA_COD {
  1321. union {
  1322. struct {
  1323. USHORT Level:2;
  1324. USHORT Type:2;
  1325. USHORT Request:4;
  1326. USHORT BusErrInfo:4;
  1327. USHORT Other:4;
  1328. } hw;
  1329. USHORT ShortPart;
  1330. } u;
  1331. } MCA_COD, *PMCA_COD;
  1332. //
  1333. // STATUS register for each MCA bank.
  1334. //
  1335. typedef struct _MCA_MCI_STATUS {
  1336. union {
  1337. struct {
  1338. MCA_COD McaCod;
  1339. USHORT MsCod;
  1340. ULONG OtherInfo:25;
  1341. ULONG Damage:1;
  1342. ULONG AddressValid:1;
  1343. ULONG MiscValid:1;
  1344. ULONG Enabled:1;
  1345. ULONG UnCorrected:1;
  1346. ULONG OverFlow:1;
  1347. ULONG Valid:1;
  1348. } hw;
  1349. ULONGLONG QuadPart;
  1350. } u;
  1351. } MCA_MCI_STATUS, *PMCA_MCI_STATUS;
  1352. //
  1353. // ADDR register for each MCA bank
  1354. //
  1355. typedef struct _MCA_MCI_ADDR{
  1356. union {
  1357. struct {
  1358. ULONG Address;
  1359. ULONG Reserved;
  1360. } hw;
  1361. ULONGLONG QuadPart;
  1362. } u;
  1363. } MCA_MCI_ADDR, *PMCA_MCI_ADDR;
  1364. #include "poppack.h"
  1365. //
  1366. // Machine Check Error Description
  1367. //
  1368. // Any Reserved/Generic entry
  1369. CHAR Reserved[] = "Reserved";
  1370. CHAR Generic[] = "Generic";
  1371. // Transaction Types
  1372. CHAR TransInstruction[] = "Instruction";
  1373. CHAR TransData[] = "Data";
  1374. static CHAR *TransType[] = {TransInstruction,
  1375. TransData,
  1376. Generic,
  1377. Reserved
  1378. };
  1379. // Level Encodings
  1380. CHAR Level0[] = "Level 0";
  1381. CHAR Level1[] = "Level 1";
  1382. CHAR Level2[] = "Level 2";
  1383. static CHAR *Level[] = {
  1384. Level0,
  1385. Level1,
  1386. Level2,
  1387. Generic
  1388. };
  1389. // Request Encodings
  1390. CHAR ReqGenericRead[] = "Generic Read";
  1391. CHAR ReqGenericWrite[] = "Generic Write";
  1392. CHAR ReqDataRead[] = "Data Read";
  1393. CHAR ReqDataWrite[] = "Data Write";
  1394. CHAR ReqInstrFetch[] = "Instruction Fetch";
  1395. CHAR ReqPrefetch[] = "Prefetch";
  1396. CHAR ReqEviction[] = "Eviction";
  1397. CHAR ReqSnoop[] = "Snoop";
  1398. static CHAR *Request[] = {
  1399. Generic,
  1400. ReqGenericRead,
  1401. ReqGenericWrite,
  1402. ReqDataRead,
  1403. ReqDataWrite,
  1404. ReqInstrFetch,
  1405. ReqPrefetch,
  1406. ReqEviction,
  1407. ReqSnoop,
  1408. Reserved,
  1409. Reserved,
  1410. Reserved,
  1411. Reserved,
  1412. Reserved,
  1413. Reserved,
  1414. Reserved
  1415. };
  1416. // Memory Hierarchy Error Encodings
  1417. CHAR MemHierMemAccess[] = "Memory Access";
  1418. CHAR MemHierIO[] = "I/O";
  1419. CHAR MemHierOther[] = "Other Transaction";
  1420. static CHAR *MemoryHierarchy[] = {
  1421. MemHierMemAccess,
  1422. Reserved,
  1423. MemHierIO,
  1424. MemHierOther
  1425. };
  1426. // Time Out Status
  1427. CHAR TimeOut[] = "Timed Out";
  1428. CHAR NoTimeOut[] = "Did Not Time Out";
  1429. static CHAR *TimeOutCode[] = {
  1430. NoTimeOut,
  1431. TimeOut
  1432. };
  1433. // Participation Status
  1434. CHAR PartSource[] = "Source";
  1435. CHAR PartResponds[] = "Responds";
  1436. CHAR PartObserver[] = "Observer";
  1437. static CHAR *ParticipCode[] = {
  1438. PartSource,
  1439. PartResponds,
  1440. PartObserver,
  1441. Generic
  1442. };
  1443. //
  1444. // Register names for registers starting at MCA_MSR_MCG_EAX
  1445. //
  1446. char *RegNames[] = {
  1447. "eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", "esp",
  1448. "eflags", "eip", "misc"
  1449. };
  1450. VOID
  1451. DecodeError (
  1452. IN MCA_MCI_STATUS MciStatus
  1453. )
  1454. /*++
  1455. Routine Description:
  1456. Decode the machine check error logged to the status register
  1457. Model specific errors are not decoded.
  1458. Arguments:
  1459. MciStatus: Contents of Machine Check Status register
  1460. Return Value:
  1461. None
  1462. --*/
  1463. {
  1464. MCA_COD McaCod;
  1465. McaCod = MciStatus.u.hw.McaCod;
  1466. //
  1467. // Decode Errors: First identify simple errors and then
  1468. // handle compound errors as default case
  1469. //
  1470. switch(McaCod.u.ShortPart) {
  1471. case MCA_EC_NO_ERROR:
  1472. dprintf("\t\tNo Error\n");
  1473. break;
  1474. case MCA_EC_UNCLASSIFIED:
  1475. dprintf("\t\tUnclassified Error\n");
  1476. break;
  1477. case MCA_EC_ROMPARITY:
  1478. dprintf("\t\tMicrocode ROM Parity Error\n");
  1479. break;
  1480. case MCA_EC_EXTERN:
  1481. dprintf("\t\tExternal Error\n");
  1482. break;
  1483. case MCA_EC_FRC:
  1484. dprintf("\t\tFRC Error\n");
  1485. break;
  1486. default: // check for complex error conditions
  1487. if (McaCod.u.hw.BusErrInfo == 0x4) {
  1488. dprintf("\t\tInternal Unclassified Error\n");
  1489. } else if (McaCod.u.hw.BusErrInfo == 0) {
  1490. // TLB Unit Error
  1491. dprintf("\t\t%s TLB %s Error\n",
  1492. TransType[McaCod.u.hw.Type],
  1493. Level[McaCod.u.hw.Level]);
  1494. } else if (McaCod.u.hw.BusErrInfo == 1) {
  1495. // Memory Unit Error
  1496. dprintf("\t\t%s Cache %s %s Error\n",
  1497. TransType[McaCod.u.hw.Type],
  1498. Level[McaCod.u.hw.Level],
  1499. Request[McaCod.u.hw.Request]);
  1500. } else if (McaCod.u.hw.BusErrInfo >= 8) {
  1501. // Bus/Interconnect Error
  1502. dprintf("\t\tBus %s, Local Processor: %s, %s Error\n",
  1503. Level[McaCod.u.hw.Level],
  1504. ParticipCode[((McaCod.u.hw.BusErrInfo & 0x6)>>1)],
  1505. Request[McaCod.u.hw.Request]);
  1506. dprintf("%s Request %s\n",
  1507. MemoryHierarchy[McaCod.u.hw.Type],
  1508. TimeOutCode[McaCod.u.hw.BusErrInfo & 0x1]);
  1509. } else {
  1510. dprintf("\t\tUnresolved compound error code\n");
  1511. }
  1512. break;
  1513. }
  1514. }
  1515. HRESULT
  1516. McaX86(
  1517. PCSTR args
  1518. )
  1519. /*++
  1520. Routine Description:
  1521. Dumps X86 processors machine check architecture registers
  1522. and interprets any logged errors
  1523. Arguments:
  1524. args
  1525. Return Value:
  1526. HRESULT
  1527. --*/
  1528. {
  1529. MCA_MCG_CAPABILITY Capabilities;
  1530. MCA_MCG_STATUS McgStatus;
  1531. MCA_MCI_STATUS MciStatus;
  1532. MCA_MCI_ADDR MciAddress;
  1533. ULONGLONG MciControl;
  1534. ULONGLONG MciMisc;
  1535. ULONG Index,i;
  1536. ULONG FeatureBits = 0;
  1537. ULONG Cr4Value;
  1538. BOOLEAN Cr4MCEnabled = FALSE;
  1539. BOOLEAN RegsValid = FALSE;
  1540. ULONGLONG MachineCheckAddress, MachineCheckType;
  1541. ULARGE_INTEGER RegValue;
  1542. //
  1543. // Quick sanity check for Machine Check availability.
  1544. // Support included for both Pentium Style MCE and Pentium
  1545. // Pro Style MCA.
  1546. //
  1547. i = (ULONG) GetExpression(args);
  1548. if (i != 1) {
  1549. i = (ULONG) GetExpression("hal!HalpFeatureBits");
  1550. if (!i) {
  1551. dprintf ("HalpFeatureBits not found\n");
  1552. return E_INVALIDARG;
  1553. }
  1554. FeatureBits = 0;
  1555. ReadMemory(i, &FeatureBits, sizeof(i), &i);
  1556. if (FeatureBits == -1 ||
  1557. (!(FeatureBits & HAL_MCA_PRESENT) &&
  1558. !(FeatureBits & HAL_MCE_PRESENT))) {
  1559. dprintf ("Machine Check feature not present\n");
  1560. return E_INVALIDARG;
  1561. }
  1562. }
  1563. //
  1564. // Read cr4 to determine if CR4.MCE is enabled.
  1565. // This enables the Machine Check exception reporting
  1566. //
  1567. Cr4Value = (ULONG) GetExpression("@Cr4");
  1568. if (Cr4Value & CR4_MCE_X86) {
  1569. Cr4MCEnabled = TRUE;
  1570. }
  1571. if (FeatureBits & HAL_MCE_PRESENT) {
  1572. // Read P5_MC_ADDR Register and P5_MC_TYPE Register
  1573. ReadMsr(MCE_MSR_MC_ADDR, &MachineCheckAddress);
  1574. ReadMsr(MCE_MSR_MC_TYPE, &MachineCheckType);
  1575. dprintf ("MCE: %s, Cycle Address: 0x%.8x%.8x, Type: 0x%.8x%.8x\n\n",
  1576. (Cr4MCEnabled ? "Enabled" : "Disabled"),
  1577. (ULONG)(MachineCheckAddress >> 32),
  1578. (ULONG)(MachineCheckAddress),
  1579. (ULONG)(MachineCheckType >> 32),
  1580. (ULONG)(MachineCheckType));
  1581. }
  1582. Capabilities.u.QuadPart = (ULONGLONG)0;
  1583. if (FeatureBits & HAL_MCA_PRESENT) {
  1584. //
  1585. // Dump MCA registers
  1586. //
  1587. ReadMsr(MCA_MSR_MCG_CAP, &Capabilities.u.QuadPart);
  1588. ReadMsr(MCA_MSR_MCG_STATUS, &McgStatus.u.QuadPart);
  1589. dprintf ("MCA: %s, Banks %d, Control Reg: %s, Machine Check: %s.\n",
  1590. (Cr4MCEnabled ? "Enabled" : "Disabled"),
  1591. Capabilities.u.hw.McaCnt,
  1592. Capabilities.u.hw.McaCntlPresent ? "Supported" : "Not Supported",
  1593. McgStatus.u.hw.McCheckInProgress ? "In Progress" : "None"
  1594. );
  1595. if (McgStatus.u.hw.McCheckInProgress && McgStatus.u.hw.ErrorIPValid) {
  1596. dprintf ("MCA: Error IP Valid\n");
  1597. }
  1598. if (McgStatus.u.hw.McCheckInProgress && McgStatus.u.hw.RestartIPValid) {
  1599. dprintf ("MCA: Restart IP Valid\n");
  1600. }
  1601. //
  1602. // Scan all the banks to check if any machines checks have been
  1603. // logged and decode the errors if any.
  1604. //
  1605. dprintf ("Bank Error Control Register Status Register\n");
  1606. for (Index=0; Index < (ULONG) Capabilities.u.hw.McaCnt; Index++) {
  1607. ReadMsr(MCA_MSR_MC0_CTL+MCA_NUM_REGS*Index, &MciControl);
  1608. ReadMsr(MCA_MSR_MC0_STATUS+MCA_NUM_REGS*Index, &MciStatus.u.QuadPart);
  1609. dprintf (" %2d. %s 0x%.8x%.8x 0x%.8x%.8x\n",
  1610. Index,
  1611. (MciStatus.u.hw.Valid ? "Valid" : "None "),
  1612. (ULONG) (MciControl >> 32),
  1613. (ULONG) (MciControl),
  1614. (ULONG) (MciStatus.u.QuadPart>>32),
  1615. (ULONG) (MciStatus.u.QuadPart)
  1616. );
  1617. if (MciStatus.u.hw.Valid) {
  1618. DecodeError(MciStatus);
  1619. }
  1620. if (MciStatus.u.hw.AddressValid) {
  1621. ReadMsr(MCA_MSR_MC0_ADDR+MCA_NUM_REGS*Index, &MciAddress.u.QuadPart);
  1622. dprintf ("\t\tAddress Reg 0x%.8x%.8x ",
  1623. (ULONG) (MciAddress.u.QuadPart>>32),
  1624. (ULONG) (MciAddress.u.QuadPart)
  1625. );
  1626. }
  1627. if (MciStatus.u.hw.MiscValid) {
  1628. ReadMsr(MCA_MSR_MC0_MISC+MCA_NUM_REGS*Index, &MciMisc);
  1629. dprintf ("\t\tMisc Reg 0x%.8x%.8x ",
  1630. (ULONG) (MciMisc >> 32),
  1631. (ULONG) (MciMisc)
  1632. );
  1633. }
  1634. dprintf("\n");
  1635. }
  1636. }
  1637. if (Capabilities.u.hw.McaExtPresent && Capabilities.u.hw.McaExtCnt) {
  1638. dprintf ("Registers Saved: %d.", Capabilities.u.hw.McaExtCnt);
  1639. RegsValid = FALSE;
  1640. for (i = 0; i < Capabilities.u.hw.McaExtCnt; i++) {
  1641. if (i % 2 == 0) {
  1642. dprintf("\n");
  1643. }
  1644. ReadMsr(MCA_MSR_MCG_EAX+i, &RegValue.QuadPart);
  1645. if ((i == MCA_MSR_MCG_EFLAGS-MCA_MSR_MCG_EAX) && RegValue.LowPart) {
  1646. RegsValid = TRUE;
  1647. }
  1648. if (i < sizeof(RegNames)/sizeof(RegNames[0])) {
  1649. dprintf("%7s: 0x%08x 0x%08x", RegNames[i], RegValue.HighPart, RegValue.LowPart);
  1650. } else {
  1651. dprintf(" Reg%02d: 0x%08x 0x%08x", i, RegValue.HighPart, RegValue.LowPart);
  1652. }
  1653. }
  1654. dprintf("\n");
  1655. if (!RegsValid) {
  1656. dprintf("(Register state does not appear to be valid.)\n");
  1657. }
  1658. dprintf("\n");
  1659. } else {
  1660. dprintf("No register state available.\n\n");
  1661. }
  1662. return S_OK;
  1663. } // McaX86()
  1664. typedef enum _ERROR_SECTION_HEADER_TYPE_IA64 {
  1665. ERROR_SECTION_UNKNOWN = 0,
  1666. ERROR_SECTION_PROCESSOR,
  1667. ERROR_SECTION_MEMORY,
  1668. ERROR_SECTION_PCI_BUS,
  1669. ERROR_SECTION_PCI_COMPONENT,
  1670. ERROR_SECTION_SYSTEM_EVENT_LOG,
  1671. ERROR_SECTION_SMBIOS,
  1672. ERROR_SECTION_PLATFORM_SPECIFIC,
  1673. ERROR_SECTION_PLATFORM_BUS,
  1674. ERROR_SECTION_PLATFORM_HOST_CONTROLLER
  1675. } ERROR_SECTION_HEADER_TYPE_IA64;
  1676. GUID gErrorProcessorGuid;
  1677. GUID gErrorMemoryGuid;
  1678. GUID gErrorPciBusGuid;
  1679. GUID gErrorPciComponentGuid;
  1680. GUID gErrorSystemEventLogGuid;
  1681. GUID gErrorSmbiosGuid;
  1682. GUID gErrorPlatformSpecificGuid;
  1683. GUID gErrorPlatformBusGuid;
  1684. GUID gErrorPlatformHostControllerGuid;
  1685. //
  1686. // _HALP_SAL_PAL_DATA.Flags definitions
  1687. // <extracted from i64fw.h>
  1688. //
  1689. #ifndef HALP_SALPAL_FIX_MCE_LOG_ID
  1690. #define HALP_SALPAL_FIX_MCE_LOG_ID 0x1
  1691. #define HALP_SALPAL_MCE_PROCESSOR_CPUIDINFO_OMITTED 0x2
  1692. #define HALP_SALPAL_MCE_PROCESSOR_STATICINFO_PARTIAL 0x4
  1693. #endif // !HALP_SALPAL_FIX_MCE_LOG_ID
  1694. USHORT gHalpSalPalDataFlags = 0;
  1695. //
  1696. // The following are also in mce.h and are defined
  1697. // by the SAL specification.
  1698. //
  1699. // #define PciBusUnknownError ((UCHAR)0)
  1700. // #define PciBusDataParityError ((UCHAR)1)
  1701. // #define PciBusSystemError ((UCHAR)2)
  1702. // #define PciBusMasterAbort ((UCHAR)3)
  1703. // #define PciBusTimeOut ((UCHAR)4)
  1704. // #define PciMasterDataParityError ((UCHAR)5)
  1705. // #define PciAddressParityError ((UCHAR)6)
  1706. // #define PciCommandParityError ((UCHAR)7)
  1707. #define PciMaxErrorType ((UCHAR)8)
  1708. PCHAR PciBusErrorTypeStrings[] = {
  1709. "Unknown or OEM System Specific Error",
  1710. "Data Parity Error",
  1711. "System Error",
  1712. "Master Abort",
  1713. "Bus Time Our or No Device Present",
  1714. "Master Data Parity Error",
  1715. "Address Parity Error",
  1716. "Command Parity Error"
  1717. };
  1718. ULONG64
  1719. ReadUlong64(
  1720. ULONG64 Address
  1721. )
  1722. {
  1723. ULONG64 RemoteValue = 0;
  1724. ReadMemory( Address, &RemoteValue, sizeof( ULONG64 ), NULL );
  1725. return RemoteValue;
  1726. }
  1727. VOID
  1728. ExecCommand(
  1729. IN PCSTR Cmd
  1730. )
  1731. {
  1732. if (g_ExtClient && (ExtQuery(g_ExtClient) == S_OK)) {
  1733. g_ExtControl->Execute(DEBUG_OUTCTL_AMBIENT, Cmd, DEBUG_EXECUTE_DEFAULT );
  1734. }
  1735. } // ExecCommand()
  1736. BOOLEAN /* TRUE: Error was found, FALSE: successful */
  1737. SetErrorDeviceGuid(
  1738. PCSTR DeviceGuidString,
  1739. GUID * DeviceGuid
  1740. )
  1741. {
  1742. ULONG64 guidAddress;
  1743. guidAddress = GetExpression( DeviceGuidString );
  1744. if ( guidAddress ) {
  1745. GUID devGuid;
  1746. ULONG cbRead;
  1747. if ( ReadMemory( guidAddress, &devGuid, sizeof(devGuid), &cbRead ) &&
  1748. (cbRead == sizeof(devGuid)) ) {
  1749. *DeviceGuid = devGuid;
  1750. return FALSE;
  1751. }
  1752. dprintf("%s memory-read failed", DeviceGuidString );
  1753. } else {
  1754. dprintf("%s not found", DeviceGuidString );
  1755. return FALSE;
  1756. }
  1757. return TRUE;
  1758. } // SetErrorDeviceGuid()
  1759. //
  1760. // Sets up globals for the error guids for
  1761. // future comparison of error record types.
  1762. //
  1763. // Returns TRUE if successful, FALSE if an error
  1764. //
  1765. BOOLEAN
  1766. SetErrorDeviceGuids(
  1767. VOID
  1768. )
  1769. {
  1770. BOOLEAN errorFound;
  1771. ULONG errorDeviceGuidSize;
  1772. errorFound = FALSE;
  1773. errorDeviceGuidSize = GetTypeSize( "hal!_ERROR_DEVICE_GUID" );
  1774. if ( errorDeviceGuidSize == 0 ) {
  1775. // pre-SAL 3.0 check-in hal
  1776. dprintf("!mca: ERROR_DEVICE_GUID size = 0...\n");
  1777. return FALSE;
  1778. }
  1779. //
  1780. // Initialize extension-global Error Device Guids.
  1781. //
  1782. errorFound |= SetErrorDeviceGuid("hal!HalpErrorProcessorGuid", &gErrorProcessorGuid);
  1783. errorFound |= SetErrorDeviceGuid("hal!HalpErrorMemoryGuid", &gErrorMemoryGuid);
  1784. errorFound |= SetErrorDeviceGuid("hal!HalpErrorPciBusGuid", &gErrorPciBusGuid);
  1785. errorFound |= SetErrorDeviceGuid("hal!HalpErrorPciComponentGuid", &gErrorPciComponentGuid);
  1786. errorFound |= SetErrorDeviceGuid("hal!HalpErrorSystemEventLogGuid", &gErrorSystemEventLogGuid);
  1787. errorFound |= SetErrorDeviceGuid("hal!HalpErrorSmbiosGuid", &gErrorSmbiosGuid);
  1788. errorFound |= SetErrorDeviceGuid("hal!HalpErrorPlatformSpecificGuid", &gErrorPlatformSpecificGuid);
  1789. errorFound |= SetErrorDeviceGuid("hal!HalpErrorPlatformBusGuid", &gErrorPlatformBusGuid);
  1790. errorFound |= SetErrorDeviceGuid("hal!HalpErrorPlatformHostControllerGuid", &gErrorPlatformHostControllerGuid);
  1791. if ( errorFound ) {
  1792. dprintf("\n");
  1793. return FALSE;
  1794. }
  1795. return TRUE;
  1796. } // SetErrorDeviceGuids()
  1797. typedef struct _TYPED_SYMBOL_HANDLE {
  1798. ULONG64 Module;
  1799. ULONG TypeId;
  1800. ULONG Spare;
  1801. BOOLEAN Found;
  1802. CHAR Name[MAX_PATH];
  1803. } TYPED_SYMBOL_HANDLE, *PTYPED_SYMBOL_HANDLE;
  1804. __inline
  1805. VOID
  1806. InitTypedSymbol(
  1807. PTYPED_SYMBOL_HANDLE Handle,
  1808. ULONG64 Module,
  1809. ULONG TypeId,
  1810. BOOLEAN Found
  1811. )
  1812. {
  1813. Handle->Module = Module;
  1814. Handle->TypeId = TypeId;
  1815. Handle->Found = Found;
  1816. Handle->Name[0] = '\0';
  1817. return;
  1818. } // InitTypedSymbol()
  1819. __inline
  1820. BOOLEAN
  1821. IsTypedSymbolFound(
  1822. PTYPED_SYMBOL_HANDLE Handle
  1823. )
  1824. {
  1825. return Handle->Found;
  1826. } // IsTypedSymbolFound()
  1827. __inline
  1828. HRESULT
  1829. GetTypedSymbolName(
  1830. PTYPED_SYMBOL_HANDLE Handle,
  1831. ULONG64 Value
  1832. )
  1833. {
  1834. if ( !IsTypedSymbolFound( Handle ) ) {
  1835. return E_INVALIDARG;
  1836. }
  1837. return( g_ExtSymbols->GetConstantName( Handle->Module,
  1838. Handle->TypeId,
  1839. Value,
  1840. Handle->Name,
  1841. sizeof(Handle->Name),
  1842. NULL) );
  1843. } // GetTypedSymbolName()
  1844. TYPED_SYMBOL_HANDLE gErrorSeverity;
  1845. __inline
  1846. VOID
  1847. SetTypedSymbol(
  1848. PTYPED_SYMBOL_HANDLE Handle,
  1849. PCSTR Symbol
  1850. )
  1851. {
  1852. HRESULT hr;
  1853. ULONG typeId;
  1854. ULONG64 module;
  1855. hr = g_ExtSymbols->GetSymbolTypeId( Symbol, &typeId, &module);
  1856. if ( SUCCEEDED(hr) ) {
  1857. InitTypedSymbol( Handle, module, typeId, TRUE );
  1858. }
  1859. return;
  1860. } // SetTypedSymbol()
  1861. #define SetErrorTypedSymbol( _Handle, _Symbol ) SetTypedSymbol( &(_Handle), #_Symbol )
  1862. #define SetErrorSeverityValues() SetErrorTypedSymbol( gErrorSeverity, hal!_ERROR_SEVERITY_VALUE )
  1863. PCSTR
  1864. ErrorSeverityValueString(
  1865. ULONG SeverityValue
  1866. )
  1867. {
  1868. HRESULT hr;
  1869. hr = GetTypedSymbolName( &gErrorSeverity, SeverityValue );
  1870. if ( SUCCEEDED( hr ) ) {
  1871. return gErrorSeverity.Name;
  1872. } else {
  1873. dprintf("Couldn't find hal!_ERROR_SEVERITY_VALUE\n");
  1874. }
  1875. //
  1876. // Fall back to known values...
  1877. //
  1878. switch( SeverityValue ) {
  1879. case ErrorRecoverable_IA64:
  1880. return("ErrorRecoverable");
  1881. case ErrorFatal_IA64:
  1882. return("ErrorFatal");
  1883. case ErrorCorrected_IA64:
  1884. return("ErrorCorrected");
  1885. default:
  1886. return("ErrorOthers");
  1887. } // switch( SeverityValue )
  1888. } // ErrorSeverityValueString()
  1889. BOOLEAN
  1890. CompareTypedErrorDeviceGuid(
  1891. GUID * RefGuid
  1892. )
  1893. {
  1894. if ( ( RefGuid->Data1 == (ULONG) ReadField(Guid.Data1) ) &&
  1895. ( RefGuid->Data2 == (USHORT) ReadField(Guid.Data2) ) &&
  1896. ( RefGuid->Data3 == (USHORT) ReadField(Guid.Data3) ) &&
  1897. ( RefGuid->Data4[0] == (UCHAR) ReadField(Guid.Data4[0]) ) &&
  1898. ( RefGuid->Data4[1] == (UCHAR) ReadField(Guid.Data4[1]) ) &&
  1899. ( RefGuid->Data4[2] == (UCHAR) ReadField(Guid.Data4[2]) ) &&
  1900. ( RefGuid->Data4[3] == (UCHAR) ReadField(Guid.Data4[3]) ) &&
  1901. ( RefGuid->Data4[4] == (UCHAR) ReadField(Guid.Data4[4]) ) &&
  1902. ( RefGuid->Data4[5] == (UCHAR) ReadField(Guid.Data4[5]) ) &&
  1903. ( RefGuid->Data4[6] == (UCHAR) ReadField(Guid.Data4[6]) ) &&
  1904. ( RefGuid->Data4[7] == (UCHAR) ReadField(Guid.Data4[7]) ) ) {
  1905. return TRUE;
  1906. }
  1907. return FALSE;
  1908. } // CompareTypedErrorDeviceGuid()
  1909. UCHAR gZeroedOemPlatformId[16] = { 0 };
  1910. BOOLEAN
  1911. CompareTypedOemPlatformId(
  1912. UCHAR RefOemPlatformId[]
  1913. )
  1914. {
  1915. ULONG i;
  1916. for ( i = 0; i < 16; i++ ) {
  1917. if (RefOemPlatformId[i] != (UCHAR) ReadField(OemPlatformId[i]) ) {
  1918. return FALSE;
  1919. }
  1920. }
  1921. return TRUE;
  1922. } // CompareTypedOemPlatformId()
  1923. ERROR_SECTION_HEADER_TYPE_IA64
  1924. GetTypedErrorSectionType(
  1925. VOID
  1926. )
  1927. {
  1928. if ( CompareTypedErrorDeviceGuid( &gErrorProcessorGuid ) ) {
  1929. return ERROR_SECTION_PROCESSOR;
  1930. }
  1931. if ( CompareTypedErrorDeviceGuid( &gErrorMemoryGuid ) ) {
  1932. return ERROR_SECTION_MEMORY;
  1933. }
  1934. if ( CompareTypedErrorDeviceGuid( &gErrorPciBusGuid ) ) {
  1935. return ERROR_SECTION_PCI_BUS;
  1936. }
  1937. if ( CompareTypedErrorDeviceGuid( &gErrorPciComponentGuid ) ) {
  1938. return ERROR_SECTION_PCI_COMPONENT;
  1939. }
  1940. if ( CompareTypedErrorDeviceGuid( &gErrorSystemEventLogGuid ) ) {
  1941. return ERROR_SECTION_SYSTEM_EVENT_LOG;
  1942. }
  1943. if ( CompareTypedErrorDeviceGuid( &gErrorSmbiosGuid ) ) {
  1944. return ERROR_SECTION_SMBIOS;
  1945. }
  1946. if ( CompareTypedErrorDeviceGuid( &gErrorPlatformSpecificGuid ) ) {
  1947. return ERROR_SECTION_PLATFORM_SPECIFIC;
  1948. }
  1949. if ( CompareTypedErrorDeviceGuid( &gErrorPlatformBusGuid ) ) {
  1950. return ERROR_SECTION_PLATFORM_BUS;
  1951. }
  1952. if ( CompareTypedErrorDeviceGuid( &gErrorPlatformHostControllerGuid ) ) {
  1953. return ERROR_SECTION_PLATFORM_HOST_CONTROLLER;
  1954. }
  1955. return ERROR_SECTION_UNKNOWN;
  1956. } // GetTypedErrorSectionType()
  1957. PCSTR
  1958. ErrorSectionTypeString(
  1959. ERROR_SECTION_HEADER_TYPE_IA64 ErrorSectionType
  1960. )
  1961. {
  1962. switch( ErrorSectionType ) {
  1963. case ERROR_SECTION_PROCESSOR:
  1964. return( "Processor" );
  1965. case ERROR_SECTION_MEMORY:
  1966. return( "Memory" );
  1967. case ERROR_SECTION_PCI_BUS:
  1968. return( "PciBus" );
  1969. case ERROR_SECTION_PCI_COMPONENT:
  1970. return( "PciComponent" );
  1971. case ERROR_SECTION_SYSTEM_EVENT_LOG:
  1972. return( "SystemEventLog" );
  1973. case ERROR_SECTION_SMBIOS:
  1974. return( "Smbios" );
  1975. case ERROR_SECTION_PLATFORM_SPECIFIC:
  1976. return( "PlatformSpecific" );
  1977. case ERROR_SECTION_PLATFORM_BUS:
  1978. return( "PlatformBus" );
  1979. case ERROR_SECTION_PLATFORM_HOST_CONTROLLER:
  1980. return( "PlatformHostController" );
  1981. default:
  1982. return( "Unknown Error Device" );
  1983. } // switch( ErrorSectionType )
  1984. } // ErrorSectionTypeString()
  1985. VOID
  1986. DtCacheCheck(
  1987. ULONG64 CheckInfoStart
  1988. )
  1989. {
  1990. ULONG errorCacheCheckSize;
  1991. CHAR cmd[MAX_PATH];
  1992. errorCacheCheckSize = GetTypeSize( "hal!_ERROR_CACHE_CHECK" );
  1993. if ( !errorCacheCheckSize ) {
  1994. dprintf( "Unable to get hal!_ERROR_CACHE_CHECK type size.\n");
  1995. return;
  1996. }
  1997. dprintf( " CheckInfo: \n\n" );
  1998. sprintf(cmd, "dt -o -r hal!_ERROR_CACHE_CHECK 0x%I64x", CheckInfoStart);
  1999. ExecCommand(cmd);
  2000. dprintf( "\n" );
  2001. // We need to do more analysis here
  2002. }
  2003. VOID
  2004. DtTlbCheck(
  2005. ULONG64 CheckInfoStart
  2006. )
  2007. {
  2008. ULONG errorTlbCheckSize;
  2009. CHAR cmd[MAX_PATH];
  2010. errorTlbCheckSize = GetTypeSize( "hal!_ERROR_TLB_CHECK" );
  2011. if ( !errorTlbCheckSize ) {
  2012. dprintf( "Unable to get hal!_ERROR_TLB_CHECK type size.\n");
  2013. return;
  2014. }
  2015. dprintf( " CheckInfo: \n\n" );
  2016. sprintf(cmd, "dt -o -r hal!_ERROR_TLB_CHECK 0x%I64x", CheckInfoStart);
  2017. ExecCommand(cmd);
  2018. dprintf( "\n" );
  2019. // We need to do more analysis here
  2020. }
  2021. VOID
  2022. DtBusCheck(
  2023. ULONG64 CheckInfoStart
  2024. )
  2025. {
  2026. ULONG errorBusCheckSize;
  2027. CHAR cmd[MAX_PATH];
  2028. errorBusCheckSize = GetTypeSize( "hal!_ERROR_BUS_CHECK" );
  2029. if ( !errorBusCheckSize ) {
  2030. dprintf( "Unable to get hal!_ERROR_BUS_CHECK type size.\n");
  2031. return;
  2032. }
  2033. dprintf( " CheckInfo: \n\n" );
  2034. sprintf(cmd, "dt -o -r hal!_ERROR_BUS_CHECK 0x%I64x", CheckInfoStart);
  2035. ExecCommand(cmd);
  2036. dprintf( "\n" );
  2037. // We need to do more analysis here
  2038. }
  2039. VOID
  2040. DtRegFileCheck(
  2041. ULONG64 CheckInfoStart
  2042. )
  2043. {
  2044. ULONG errorRegfileCheckSize;
  2045. CHAR cmd[MAX_PATH];
  2046. errorRegfileCheckSize = GetTypeSize( "hal!_ERROR_REGFILE_CHECK" );
  2047. if ( !errorRegfileCheckSize ) {
  2048. dprintf( "Unable to get hal!_ERROR_REGFILE_CHECK type size.\n");
  2049. return;
  2050. }
  2051. dprintf( " CheckInfo: \n\n" );
  2052. sprintf(cmd, "dt -o -r hal!_ERROR_REGFILE_CHECK 0x%I64x", CheckInfoStart);
  2053. ExecCommand(cmd);
  2054. dprintf( "\n" );
  2055. // We need to do more analysis here
  2056. }
  2057. VOID DtMsCheck(
  2058. ULONG64 CheckInfoStart
  2059. )
  2060. {
  2061. ULONG errorMsCheckSize;
  2062. CHAR cmd[MAX_PATH];
  2063. errorMsCheckSize = GetTypeSize( "hal!_ERROR_MS_CHECK" );
  2064. if ( !errorMsCheckSize ) {
  2065. dprintf( "Unable to get hal!_ERROR_MS_CHECK type size.\n");
  2066. return;
  2067. }
  2068. dprintf( " CheckInfo: \n\n" );
  2069. sprintf(cmd, "dt -o -r hal!_ERROR_MS_CHECK 0x%I64x", CheckInfoStart);
  2070. ExecCommand(cmd);
  2071. dprintf( "\n" );
  2072. // We need to do more analysis here
  2073. }
  2074. ULONG64
  2075. DtErrorModInfos(
  2076. ULONG64 ModInfo,
  2077. ULONG CheckNum,
  2078. ULONG ModInfoSize,
  2079. PCSTR ModInfoName,
  2080. CHECK_TYPES CheckType
  2081. )
  2082. {
  2083. ULONG64 modInfo;
  2084. ULONG modInfoNum;
  2085. ULONG64 modInfoMax;
  2086. ULONG modInfoValidSize;
  2087. CHAR cmd[MAX_PATH];
  2088. ULONG64 checkInfoStart;
  2089. ULONG checkInfoOffset;
  2090. modInfo = ModInfo;
  2091. modInfoMax = modInfo + ( CheckNum * ModInfoSize );
  2092. modInfoNum = 0;
  2093. modInfoValidSize = GetTypeSize( "hal!_ERROR_MODINFO_VALID" );
  2094. while( modInfo < modInfoMax ) {
  2095. dprintf("\n %s[%ld]:\n\n", ModInfoName, modInfoNum);
  2096. if ( modInfoValidSize ) {
  2097. sprintf( cmd, "dt -o -r hal!_ERROR_MODINFO_VALID 0x%I64x", modInfo );
  2098. ExecCommand( cmd );
  2099. InitTypeRead( modInfo, hal!_ERROR_MODINFO );
  2100. dprintf( " CheckInfo : 0x%I64x\n", (ULONG64) ReadField(CheckInfo.CheckInfo) );
  2101. dprintf( " RequestorId : 0x%I64x\n", (ULONG64) ReadField(RequestorId) );
  2102. dprintf( " ResponderId : 0x%I64x\n", (ULONG64) ReadField(ResponderId) );
  2103. dprintf( " TargetIp : 0x%I64x\n", (ULONG64) ReadField(TargetIp) );
  2104. dprintf( " PreciseIp : 0x%I64x\n\n", (ULONG64) ReadField(PreciseIp) );
  2105. checkInfoStart = 0;
  2106. GetFieldOffset("hal!_ERROR_MODINFO" , "CheckInfo", &checkInfoOffset );
  2107. checkInfoStart = modInfo + checkInfoOffset;
  2108. switch (CheckType) {
  2109. case CACHE_CHECK_TYPE:
  2110. DtCacheCheck( checkInfoStart );
  2111. break;
  2112. case TLB_CHECK_TYPE:
  2113. DtTlbCheck( checkInfoStart );
  2114. break;
  2115. case BUS_CHECK_TYPE:
  2116. DtBusCheck( checkInfoStart );
  2117. break;
  2118. case REG_FILE_CHECK_TYPE:
  2119. DtRegFileCheck( checkInfoStart );
  2120. break;
  2121. case MS_CHECK_TYPE:
  2122. DtMsCheck( checkInfoStart );
  2123. break;
  2124. } // switch (CheckType)
  2125. } // if ( modInfoValidSize )
  2126. modInfo += (ULONG64)ModInfoSize;
  2127. modInfoNum++;
  2128. } // while( modInfo < modInfoMax )
  2129. return( modInfo );
  2130. } // DtErrorModInfos()
  2131. ULONG64
  2132. DtErrorProcessorStaticInfo(
  2133. ULONG64 StaticInfo,
  2134. ULONG64 SectionMax
  2135. )
  2136. {
  2137. ULONG offset;
  2138. ULONG64 valid;
  2139. CHAR cmd[MAX_PATH];
  2140. ULONG i;
  2141. HRESULT hr;
  2142. ULONG64 moduleValid;
  2143. ULONG typeIdValid;
  2144. CHAR field[MAX_PATH];
  2145. hr = g_ExtSymbols->GetSymbolTypeId( "hal!_ERROR_PROCESSOR_STATIC_INFO_VALID",
  2146. &typeIdValid,
  2147. &moduleValid);
  2148. if ( !SUCCEEDED(hr) ) {
  2149. dprintf("Unable to get hal!_ERROR_PROCESSOR_STATIC_INFO_VALID type. Stop processing...\n");
  2150. return( 0 );
  2151. }
  2152. //
  2153. //
  2154. // Display the valid structure.
  2155. //
  2156. offset = 0;
  2157. GetFieldOffset("hal!_ERROR_PROCESSOR_STATIC_INFO" , "Valid", &offset );
  2158. valid = StaticInfo + (ULONG64)offset;
  2159. dprintf(" Valid @ 0x%I64x\n\n", valid);
  2160. sprintf(cmd, "dt -o -r hal!_ERROR_PROCESSOR_STATIC_INFO_VALID 0x%I64x", valid );
  2161. ExecCommand( cmd );
  2162. dprintf( "\n" );
  2163. //
  2164. // Pass through all the valid _ERROR_PROCESSOR_STATIC_INFO fields and dump them.
  2165. //
  2166. for (i=0; ;i++) {
  2167. //
  2168. // Get a field name from the _ERROR_PROCESSOR_STATIC_INFO structure
  2169. // that corresponds to i
  2170. //
  2171. hr = g_ExtSymbols->GetFieldName(moduleValid, typeIdValid, i, field, sizeof(field), NULL);
  2172. if ( hr == S_OK) {
  2173. ULONG64 val;
  2174. ULONG size = 0;
  2175. //
  2176. // Get this field's value
  2177. //
  2178. GetFieldValue(valid, "hal!_ERROR_PROCESSOR_STATIC_INFO_VALID", field, val);
  2179. //
  2180. // Read the offset of the start of the field with the same name in
  2181. // the _ERROR_PROCESSOR_STATIC_INFO structure
  2182. //
  2183. GetFieldOffsetEx("hal!_ERROR_PROCESSOR_STATIC_INFO", field, &offset, &size);
  2184. if (val && offset ) { // Valid is the first entry. Don't print it.
  2185. ULONG64 fieldAddress, fieldAddressMax;
  2186. fieldAddress = StaticInfo + (ULONG64)offset;
  2187. fieldAddressMax = fieldAddress + (ULONG64)size - sizeof(ULONG64);
  2188. dprintf(" %s @ 0x%I64x 0x%I64x\n\n", field, fieldAddress, fieldAddressMax);
  2189. if ( fieldAddressMax > SectionMax ) {
  2190. dprintf("\t\tInvalid Entry: %s size greater than SectionMax 0x%I64x",
  2191. field, SectionMax);
  2192. }
  2193. if ( !strcmp(field, "MinState") && size ) {
  2194. //
  2195. // We will dump MinState with a structure
  2196. //
  2197. if ( GetTypeSize( "hal!_PAL_MINI_SAVE_AREA" ) ) {
  2198. sprintf(cmd, "dt -o -r hal!_PAL_MINI_SAVE_AREA 0x%I64x", fieldAddress );
  2199. ExecCommand( cmd );
  2200. dprintf( "\n" );
  2201. } else {
  2202. dprintf( "Unable to get hal!_PAL_MINI_SAVE_AREA type.\n\n");
  2203. }
  2204. } else {
  2205. //
  2206. // All the others get dumped with dqs
  2207. //
  2208. sprintf(cmd, "dqs 0x%I64x 0x%I64x", fieldAddress, fieldAddressMax );
  2209. ExecCommand( cmd );
  2210. dprintf( "\n" );
  2211. }
  2212. }
  2213. } else if (hr == E_INVALIDARG) {
  2214. // All Fields done
  2215. break;
  2216. } else {
  2217. dprintf("GetFieldName Failed %lx\n", hr);
  2218. break;
  2219. }
  2220. } // for (i=0; ;i++)
  2221. // XXTF: Later we should set to length of _ERROR_PROCESSOR_STATIC_INFO if success
  2222. return 0;
  2223. } // DtErrorProcessorStaticInfo()
  2224. HRESULT
  2225. DtErrorSectionProcessor(
  2226. IN ULONG64 Section
  2227. )
  2228. {
  2229. ULONG64 sectionMax;
  2230. ULONG sectionSize;
  2231. ULONG sectionLength;
  2232. ULONG modInfoSize;
  2233. ULONG cacheModInfos, tlbModInfos;
  2234. ULONG busModInfos, regFileModInfos, msModInfos;
  2235. ULONG64 modInfo;
  2236. ULONG64 cpuidInfo;
  2237. ULONG cpuidInfoSize;
  2238. ULONG64 staticInfo;
  2239. ULONG staticInfoSize;
  2240. ULONG64 tmpMax;
  2241. CHAR cmd[MAX_PATH];
  2242. sectionSize = GetTypeSize( "hal!_ERROR_PROCESSOR" );
  2243. if ( sectionSize == 0 ) {
  2244. dprintf( "Unable to get HAL!_ERROR_PROCESSOR type size\n" );
  2245. return( E_FAIL );
  2246. }
  2247. if ( InitTypeRead( Section, hal!_ERROR_PROCESSOR ) ) {
  2248. dprintf( "Unable to read HAL!_ERROR_PROCESSOR at 0x%I64x\n", Section );
  2249. return( E_FAIL );
  2250. }
  2251. sprintf(cmd, "dt -o -r hal!_ERROR_PROCESSOR 0x%I64x", Section);
  2252. ExecCommand( cmd );
  2253. sectionLength = (ULONG) ReadField(Header.Length);
  2254. sectionMax = Section + (ULONG64)sectionLength;
  2255. cacheModInfos = (ULONG) ReadField(Valid.CacheCheckNum);
  2256. tlbModInfos = (ULONG) ReadField(Valid.TlbCheckNum);
  2257. busModInfos = (ULONG) ReadField(Valid.BusCheckNum);
  2258. regFileModInfos = (ULONG) ReadField(Valid.RegFileCheckNum);
  2259. msModInfos = (ULONG) ReadField(Valid.MsCheckNum);
  2260. //
  2261. // Check if _ERROR_MODINFO a known type?
  2262. //
  2263. modInfo = Section + (ULONG64)sectionSize;
  2264. modInfoSize = GetTypeSize( "hal!_ERROR_MODINFO" );
  2265. if (!modInfoSize ) {
  2266. dprintf( "Unable to get HAL!_ERROR_MODINFO type size");
  2267. return( E_FAIL );
  2268. }
  2269. //
  2270. // Dump Cache ModInfo structures if any
  2271. //
  2272. if ( cacheModInfos ) {
  2273. tmpMax = modInfo + ( modInfoSize * cacheModInfos );
  2274. if ( tmpMax > sectionMax ) {
  2275. dprintf( "Invalid Mca Log Length = %ld. <= Error Cache Modinfo = %ld. Stop processing...\n\n",
  2276. sectionMax,
  2277. tmpMax );
  2278. return( E_FAIL );
  2279. } else {
  2280. modInfo = DtErrorModInfos( modInfo,
  2281. cacheModInfos,
  2282. modInfoSize,
  2283. "CacheErrorInfo",
  2284. CACHE_CHECK_TYPE
  2285. );
  2286. }
  2287. }
  2288. //
  2289. // Dump TLB ModInfo structures if any
  2290. //
  2291. if ( tlbModInfos ) {
  2292. tmpMax = modInfo + ( modInfoSize * cacheModInfos );
  2293. if ( tmpMax > sectionMax ) {
  2294. dprintf( "Invalid Mca Log Length = %ld. <= Error Tlb Modinfo = %ld. Stop processing...\n\n",
  2295. sectionMax,
  2296. tmpMax );
  2297. return( E_FAIL );
  2298. } else {
  2299. modInfo = DtErrorModInfos( modInfo,
  2300. tlbModInfos,
  2301. modInfoSize,
  2302. "TlbErrorInfo",
  2303. TLB_CHECK_TYPE
  2304. );
  2305. }
  2306. }
  2307. //
  2308. // Dump BUS ModInfo structures if any
  2309. //
  2310. if ( busModInfos ) {
  2311. tmpMax = modInfo + ( modInfoSize * cacheModInfos );
  2312. if ( tmpMax > sectionMax ) {
  2313. dprintf( "Invalid Mca Log Length = %ld. <= Error Bus Modinfo = %ld. Stop processing...\n\n",
  2314. sectionMax,
  2315. tmpMax );
  2316. return( E_FAIL );
  2317. } else {
  2318. modInfo = DtErrorModInfos( modInfo,
  2319. busModInfos,
  2320. modInfoSize,
  2321. "BusErrorInfo",
  2322. BUS_CHECK_TYPE
  2323. );
  2324. }
  2325. }
  2326. //
  2327. // Dump REGISTERS FILES ModInfo structures if any
  2328. //
  2329. if ( regFileModInfos ) {
  2330. tmpMax = modInfo + ( modInfoSize * cacheModInfos );
  2331. if ( tmpMax > sectionMax ) {
  2332. dprintf( "Invalid Mca Log Length = %ld. <= Error Regfile Modinfo = %ld. Stop processing...\n\n",
  2333. sectionMax,
  2334. tmpMax );
  2335. return( E_FAIL );
  2336. } else {
  2337. modInfo = DtErrorModInfos( modInfo,
  2338. regFileModInfos,
  2339. modInfoSize,
  2340. "RegFileErrorInfo",
  2341. REG_FILE_CHECK_TYPE
  2342. );
  2343. }
  2344. }
  2345. //
  2346. // Dump MS ModInfo structures if any
  2347. //
  2348. if ( msModInfos ) {
  2349. tmpMax = modInfo + ( modInfoSize * cacheModInfos );
  2350. if ( tmpMax > sectionMax ) {
  2351. dprintf( "Invalid Mca Log Length = %ld. <= Error Ms Modinfo = %ld. Stop processing...\n\n",
  2352. sectionMax,
  2353. tmpMax );
  2354. return( E_FAIL );
  2355. } else {
  2356. modInfo = DtErrorModInfos( modInfo,
  2357. msModInfos,
  2358. modInfoSize,
  2359. "MsErrorInfo",
  2360. MS_CHECK_TYPE
  2361. );
  2362. }
  2363. }
  2364. //
  2365. // Dump CPUID Info
  2366. //
  2367. cpuidInfo = modInfo;
  2368. /* We should see any of these for now
  2369. if ( gHalpSalPalDataFlags & HALP_SALPAL_MCE_PROCESSOR_CPUIDINFO_OMITTED ) {
  2370. dprintf("\tCpuIdInfo @ 0x%I64x FW-omitted\n", cpuidInfo);
  2371. cpuidInfoSize = 0;
  2372. } else {
  2373. */
  2374. cpuidInfoSize = GetTypeSize( "hal!_ERROR_PROCESSOR_CPUID_INFO" );
  2375. if ( cpuidInfoSize ) {
  2376. if ( (cpuidInfo + cpuidInfoSize) > sectionMax ) {
  2377. dprintf("\nInvalid ERROR_PROCESSOR: (cpuidInfo+cpuidInfoSize) > sectionMax\n");
  2378. return E_FAIL;
  2379. }
  2380. if ( ReadField( Valid.CpuIdInfo ) ) {
  2381. dprintf(" CpuIdInfo @ 0x%I64x 0x%I64x\n\n", cpuidInfo, (cpuidInfo + (ULONG64)cpuidInfoSize));
  2382. sprintf(cmd, "dt -o -r hal!_ERROR_PROCESSOR_CPUID_INFO 0x%I64x", cpuidInfo );
  2383. ExecCommand( cmd );
  2384. dprintf("\n");
  2385. }
  2386. }
  2387. else {
  2388. dprintf( "Unable to get HAL!_ERROR_PROCESSOR_CPUID_INFO type size\n" );
  2389. }
  2390. /*
  2391. }
  2392. */
  2393. //
  2394. // Dump Processor Static Info
  2395. //
  2396. staticInfo = cpuidInfo + cpuidInfoSize;
  2397. staticInfoSize = GetTypeSize( "hal!_ERROR_PROCESSOR_STATIC_INFO" );
  2398. if ( staticInfoSize ) {
  2399. if ( !(gHalpSalPalDataFlags & HALP_SALPAL_MCE_PROCESSOR_STATICINFO_PARTIAL) &&
  2400. ((staticInfo + staticInfoSize) > sectionMax) ) {
  2401. dprintf("\nInvalid ERROR_PROCESSOR: (staticInfo+staticInfoSize) > sectionMax\n");
  2402. return E_FAIL;
  2403. }
  2404. dprintf(" StaticInfo @ 0x%I64x 0x%I64x\n\n", staticInfo, (staticInfo + (ULONG64)staticInfoSize));
  2405. (VOID) DtErrorProcessorStaticInfo( staticInfo, sectionMax );
  2406. }
  2407. else {
  2408. dprintf( "Unable to get HAL!_ERROR_PROCESSOR_STATIC_INFO type size\n" );
  2409. }
  2410. return S_OK;
  2411. } // DtErrrorSectionProcessor()
  2412. ULONG64
  2413. DtErrorOemData(
  2414. ULONG64 OemData,
  2415. ULONG64 SectionMax
  2416. )
  2417. {
  2418. ULONG oemDataSize;
  2419. CHAR cmd[MAX_PATH];
  2420. USHORT length = 0;
  2421. oemDataSize = GetTypeSize("hal!_ERROR_OEM_DATA");
  2422. if ( !oemDataSize ) {
  2423. dprintf( "Unable to get hal!_ERROR_OEM_DATA type\n\n" );
  2424. } else {
  2425. GetFieldValue( OemData, "hal!_ERROR_OEM_DATA", "Length", length );
  2426. if ( length > sizeof(length) ) {
  2427. //
  2428. // We have some data, print it
  2429. //
  2430. dprintf(" OemData @ 0x%I64x 0x%I64x\n\n", OemData, (OemData + length) );
  2431. dprintf(" Data Length = 0x%x\n", length - sizeof(length) );
  2432. dprintf(" Data:\n" );
  2433. if ( ( OemData + length ) <= SectionMax ) {
  2434. sprintf( cmd, "db 0x%I64x l 0x%x\n",
  2435. OemData + sizeof(length),
  2436. length - sizeof(length)
  2437. );
  2438. ExecCommand(cmd);
  2439. dprintf( "\n" );
  2440. } else {
  2441. dprintf( "OemData exceeds Section end\n\n" );
  2442. }
  2443. }
  2444. }
  2445. return( OemData + (ULONG64)length );
  2446. } // DtErrorOemData()
  2447. VOID
  2448. DtErrorOemDevicePath(
  2449. ULONG64 OemDevicePath,
  2450. ULONG64 OemDevicePathMax
  2451. )
  2452. {
  2453. CHAR cmd[MAX_PATH];
  2454. dprintf( " OemDevicePath @ 0x%I64x 0x%I64x\n", OemDevicePath, OemDevicePathMax );
  2455. sprintf( cmd, "db 0x%I64x l 0x%I64x\n", OemDevicePath, OemDevicePathMax - OemDevicePath );
  2456. ExecCommand( cmd );
  2457. return;
  2458. } // DtErrorOemDevicePath()
  2459. HRESULT
  2460. DtErrorSectionPlatformSpecific(
  2461. IN ULONG64 Section
  2462. )
  2463. {
  2464. ULONG sectionSize;
  2465. ULONG64 oemData;
  2466. ULONG64 devicePath;
  2467. ULONG sectionLength;
  2468. ULONG validBit;
  2469. ULONG tmpUlong;
  2470. sectionSize = GetTypeSize( "hal!_ERROR_PLATFORM_SPECIFIC" );
  2471. if ( sectionSize ) {
  2472. CHAR cmd[MAX_PATH];
  2473. sprintf(cmd, "dt -r -o hal!_ERROR_PLATFORM_SPECIFIC 0x%I64x", Section);
  2474. ExecCommand( cmd );
  2475. //
  2476. // Print the OEM data if there is any
  2477. //
  2478. GetFieldValue( Section, "hal!_ERROR_PLATFORM_SPECIFIC", "Header.Length", sectionLength );
  2479. GetFieldValue( Section, "hal!_ERROR_PLATFORM_SPECIFIC", "Valid.OemData", validBit);
  2480. GetFieldOffset("hal!_ERROR_PLATFORM_SPECIFIC", "OemData", &tmpUlong);
  2481. if ( validBit ) {
  2482. devicePath = DtErrorOemData( Section + tmpUlong, Section + sectionLength );
  2483. } else {
  2484. //
  2485. // Set up a pointer to the OEM Device path
  2486. //
  2487. devicePath = Section + tmpUlong + sizeof( USHORT );
  2488. }
  2489. //
  2490. // If the OEM device path is valid then print it
  2491. //
  2492. GetFieldValue( Section, "hal!_ERROR_PLATFORM_SPECIFIC", "Valid.OemDevicePath", validBit);
  2493. if ( validBit ) {
  2494. DtErrorOemDevicePath( devicePath, Section + (ULONG64)sectionLength );
  2495. }
  2496. }
  2497. else {
  2498. dprintf( "Unable to get hal!_ERROR_PLATFORM_SPECIFIC type. Stop processing ...\n\n" );
  2499. return E_FAIL;
  2500. }
  2501. return S_OK;
  2502. } // DtErrorSectionPlatformSpecific()
  2503. HRESULT
  2504. DtErrorSectionMemory(
  2505. IN ULONG64 Section
  2506. )
  2507. {
  2508. ULONG sectionSize;
  2509. ULONG validBit;
  2510. ULONG sectionLength;
  2511. ULONG tmpUlong;
  2512. sectionSize = GetTypeSize( "hal!_ERROR_MEMORY" );
  2513. if ( sectionSize ) {
  2514. CHAR cmd[MAX_PATH];
  2515. sprintf(cmd, "dt -r -o hal!_ERROR_MEMORY 0x%I64x", Section);
  2516. ExecCommand( cmd );
  2517. dprintf("\n");
  2518. //
  2519. // If the OEM device path is valid then print it
  2520. //
  2521. GetFieldValue( Section, "hal!_ERROR_MEMORY", "Header.Length", sectionLength );
  2522. GetFieldValue( Section, "hal!_ERROR_MEMORY", "Valid.OemDevicePath", validBit);
  2523. if ( validBit ) {
  2524. GetFieldOffset("hal!_ERROR_MEMORY", "OemId", &tmpUlong);
  2525. DtErrorOemDevicePath( Section + tmpUlong, Section + (ULONG64)sectionLength );
  2526. }
  2527. //
  2528. // Print the OEM data if there is any
  2529. //
  2530. GetFieldValue( Section, "hal!_ERROR_MEMORY", "Valid.OemData", validBit);
  2531. if ( validBit ) {
  2532. GetFieldOffset("hal!_ERROR_MEMORY", "OemData", &tmpUlong);
  2533. DtErrorOemData( Section + tmpUlong, Section + sectionLength );
  2534. }
  2535. }
  2536. else {
  2537. dprintf( "Unable to get hal!_ERROR_MEMORY type. Stop processing ...\n\n" );
  2538. return E_FAIL;
  2539. }
  2540. return S_OK;
  2541. } // DtErrorSectionMemory()
  2542. HRESULT
  2543. DtErrorSectionPciComponent(
  2544. IN ULONG64 Section
  2545. )
  2546. {
  2547. ULONG sectionSize;
  2548. ULONG64 tmpOffset;
  2549. ULONG tmpUlong;
  2550. ULONG numRegisterPairs;
  2551. ULONG sectionLength;
  2552. sectionSize = GetTypeSize( "hal!_ERROR_PCI_COMPONENT" );
  2553. if ( sectionSize ) {
  2554. CHAR cmd[MAX_PATH];
  2555. sprintf(cmd, "dt -r -o hal!_ERROR_PCI_COMPONENT 0x%I64x", Section);
  2556. ExecCommand( cmd );
  2557. dprintf("\n");
  2558. //
  2559. // Print out the MemoryMappedRegistersPairs and
  2560. // ProgrammedIORegistersPairs if there are any
  2561. //
  2562. numRegisterPairs = 0;
  2563. GetFieldValue( Section, "hal!_ERROR_PCI_COMPONENT", "Header.Length", sectionLength );
  2564. GetFieldValue( Section, "hal!_ERROR_PCI_COMPONENT", "Valid.MemoryMappedRegistersPairs", tmpUlong );
  2565. if ( tmpUlong ) {
  2566. GetFieldValue( Section, "hal!_ERROR_PCI_COMPONENT", "MemoryMappedRegistersPairs", numRegisterPairs );
  2567. }
  2568. GetFieldValue( Section, "hal!_ERROR_PCI_COMPONENT", "Valid.ProgrammedIORegistersPairs", tmpUlong );
  2569. if ( tmpUlong ) {
  2570. GetFieldValue( Section, "hal!_ERROR_PCI_COMPONENT", "ProgrammedIORegistersPairs", tmpUlong );
  2571. }
  2572. numRegisterPairs += tmpUlong;
  2573. GetFieldOffset("hal!_ERROR_PCI_COMPONENT", "ProgrammedIORegistersPairs", &tmpUlong);
  2574. tmpOffset = Section + tmpUlong + sizeof(ULONG); // Where the register pairs start
  2575. if ( numRegisterPairs ) {
  2576. dprintf( " Register Pairs\n\n" );
  2577. //
  2578. // Make sure we don't overrun the section
  2579. //
  2580. tmpUlong = numRegisterPairs * sizeof( ULONG64) * 2;
  2581. if ( ( tmpOffset + tmpUlong ) <= ( Section + sectionLength ) ) {
  2582. for ( tmpUlong = 0; tmpUlong < numRegisterPairs; tmpUlong ++ ) {
  2583. dprintf( " %016I64x %016I64x\n",
  2584. ReadUlong64(tmpOffset),
  2585. ReadUlong64(tmpOffset + sizeof(ULONG64))
  2586. );
  2587. tmpOffset += sizeof(ULONG64) * 2;
  2588. }
  2589. } else {
  2590. dprintf( " Register Pair section exceeds Section end\n\n" );
  2591. }
  2592. }
  2593. //
  2594. // Print out any OEM Data there might be
  2595. //
  2596. GetFieldValue( Section, "hal!_ERROR_PCI_COMPONENT", "Valid.OemData", tmpUlong );
  2597. if ( tmpUlong ) {
  2598. DtErrorOemData( tmpOffset, Section + sectionLength );
  2599. }
  2600. } else {
  2601. dprintf( "Unable to get hal!_ERROR_PCI_COMPONENT type. Stop processing ...\n\n" );
  2602. return E_FAIL;
  2603. }
  2604. return S_OK;
  2605. } // DtErrorSectionPciComponent()
  2606. HRESULT
  2607. DtErrorSectionPciBus(
  2608. IN ULONG64 Section
  2609. )
  2610. {
  2611. ULONG sectionSize;
  2612. ULONG tmpUlong;
  2613. sectionSize = GetTypeSize( "hal!_ERROR_PCI_BUS" );
  2614. if ( sectionSize ) {
  2615. CHAR cmd[MAX_PATH];
  2616. sprintf(cmd, "dt -r -o hal!_ERROR_PCI_BUS 0x%I64x", Section);
  2617. ExecCommand( cmd );
  2618. dprintf("\n\n");
  2619. //
  2620. // Decode the type if it is valid
  2621. //
  2622. GetFieldValue( Section, "hal!_ERROR_PCI_BUS", "Valid.CmdType", tmpUlong );
  2623. if ( tmpUlong ) {
  2624. GetFieldValue( Section, "hal!_ERROR_PCI_BUS", "CmdType", tmpUlong );
  2625. if ( tmpUlong < PciMaxErrorType ) {
  2626. dprintf( " Error Type = %s\n\n", PciBusErrorTypeStrings[tmpUlong] );
  2627. }
  2628. }
  2629. } else {
  2630. dprintf( "Unable to get hal!_ERROR_PCI_BUS type. Stop processing ...\n\n" );
  2631. return E_FAIL;
  2632. }
  2633. return S_OK;
  2634. } // DtErrorSectionPciBus()
  2635. HRESULT
  2636. DtErrorSectionPlatformBus(
  2637. IN ULONG64 Section
  2638. )
  2639. {
  2640. ULONG sectionSize;
  2641. ULONG64 oemData;
  2642. ULONG64 devicePath;
  2643. ULONG sectionLength;
  2644. sectionSize = GetTypeSize( "hal!_ERROR_PLATFORM_BUS" );
  2645. if ( sectionSize ) {
  2646. CHAR cmd[MAX_PATH];
  2647. sprintf(cmd, "dt -r -o hal!_ERROR_PLATFORM_BUS 0x%I64x", Section);
  2648. ExecCommand( cmd );
  2649. GetFieldValue( Section, "hal!_ERROR_PLATFORM_BUS", "Header.Length", sectionLength );
  2650. oemData = Section + (ULONG64)sectionSize;
  2651. devicePath = DtErrorOemData( oemData, Section + sectionLength );
  2652. DtErrorOemDevicePath( devicePath, Section + (ULONG64)sectionLength );
  2653. } else {
  2654. dprintf( "Unable to get hal!_ERROR_PLATFORM_BUS type. Stop processing ...\n\n" );
  2655. return E_FAIL;
  2656. }
  2657. return S_OK;
  2658. } // DtErrorSectionPlatformBus()
  2659. HRESULT
  2660. DtErrorSectionSystemEventLog(
  2661. IN ULONG64 Section
  2662. )
  2663. {
  2664. ULONG sectionSize;
  2665. sectionSize = GetTypeSize( "hal!_ERROR_SYSTEM_EVENT_LOG" );
  2666. if ( sectionSize ) {
  2667. CHAR cmd[MAX_PATH];
  2668. sprintf(cmd, "dt -r -o hal!_ERROR_SYSTEM_EVENT_LOG 0x%I64x", Section);
  2669. ExecCommand( cmd );
  2670. dprintf("\n");
  2671. } else {
  2672. dprintf( "Unable to get hal!_ERROR_SYSTEM_EVENT_LOG type. Stop processing ...\n\n" );
  2673. return E_FAIL;
  2674. }
  2675. return S_OK;
  2676. } // DtErrorSectionSystemEventLog()
  2677. HRESULT
  2678. DtErrorSectionPlatformHostController(
  2679. IN ULONG64 Section
  2680. )
  2681. {
  2682. ULONG sectionSize;
  2683. ULONG64 oemData;
  2684. ULONG64 devicePath;
  2685. ULONG sectionLength;
  2686. dprintf("Platform Host Controller Error Record at 0x%I64x\n", Section);
  2687. sectionSize = GetTypeSize( "hal!_ERROR_PLATFORM_HOST_CONTROLLER" );
  2688. if ( sectionSize ) {
  2689. CHAR cmd[MAX_PATH];
  2690. sprintf(cmd, "dt -r -o hal!_ERROR_PLATFORM_HOST_CONTROLLER 0x%I64x", Section);
  2691. ExecCommand( cmd );
  2692. GetFieldValue( Section, "hal!_ERROR_PLATFORM_HOST_CONTROLLER", "Header.Length", sectionLength );
  2693. oemData = Section + (ULONG64)sectionSize;
  2694. devicePath = DtErrorOemData( oemData, Section + sectionLength );
  2695. DtErrorOemDevicePath( devicePath, Section + (ULONG64)sectionLength );
  2696. } else {
  2697. dprintf( "Unable to get hal!_ERROR_PLATFORM_HOST_CONTROLLER type. Stop processing ...\n\n" );
  2698. return E_FAIL;
  2699. }
  2700. return S_OK;
  2701. } // DtErrorSectionPlatformHostController()
  2702. ULONGLONG gMceProcNumberMaskTimeStamp = 0;
  2703. HRESULT
  2704. DtMcaLog(
  2705. IN ULONG64 McaLog,
  2706. IN ULONG RecordHeaderSize,
  2707. IN ULONG64 Flags
  2708. )
  2709. {
  2710. ULONG mcaLogLength;
  2711. USHORT recordRevision;
  2712. ULONG64 section;
  2713. ULONG64 sectionMax;
  2714. ULONG errorSeverity;
  2715. ULONG sectionHeaderSize;
  2716. CHAR procNumberString[64];
  2717. ULONGLONG timeStamp;
  2718. HRESULT hr;
  2719. CHAR cmd[MAX_PATH];
  2720. UCHAR minorRevision, majorRevision;
  2721. //
  2722. // Check to see if we have SAL 3.0 records. These are currently
  2723. // the only records understood by this extension.
  2724. //
  2725. recordRevision = (USHORT)ReadField(Revision);
  2726. //
  2727. // Split the revision into minor and major fields
  2728. //
  2729. majorRevision = (UCHAR) (recordRevision >> 8) ;
  2730. minorRevision = (UCHAR) (recordRevision & 0x00ff);
  2731. if (!( majorRevision == 0 && minorRevision >= 0x2 )) {
  2732. dprintf( "MCA Record revision not supported by this extension. Major Revision = %d, Minor Revision = %d\n", majorRevision, minorRevision );
  2733. return E_FAIL;
  2734. }
  2735. //
  2736. // If HAL added the processor number to the ERROR_RECORD_HEADER,
  2737. // consider this here.
  2738. //
  2739. procNumberString[0] = '\0';
  2740. timeStamp = ReadField(TimeStamp);
  2741. if ( gMceProcNumberMaskTimeStamp ) {
  2742. ULONG procNumber;
  2743. procNumber = (ULONG) ReadField(TimeStamp.Reserved);
  2744. (void)sprintf(procNumberString, " ProcNumber: %ld", procNumber);
  2745. timeStamp &= gMceProcNumberMaskTimeStamp;
  2746. }
  2747. //
  2748. // Back to standard processing here.
  2749. //
  2750. mcaLogLength = (ULONG)ReadField(Length);
  2751. errorSeverity = (ULONG)ReadField(ErrorSeverity);
  2752. if ( mcaLogLength <= RecordHeaderSize ) {
  2753. dprintf( "Invalid Mca Log Length = %ld. <= Error Header Size = %ld. Stop processing...\n\n",
  2754. mcaLogLength,
  2755. RecordHeaderSize );
  2756. return( E_FAIL );
  2757. }
  2758. dprintf("MCA Error Record Header @ 0x%I64x 0x%I64x\n", McaLog, (McaLog + (ULONG64)mcaLogLength));
  2759. sprintf(cmd, "dt -o -r hal!_ERROR_RECORD_HEADER 0x%I64x", McaLog);
  2760. ExecCommand(cmd);
  2761. dprintf("\n%s\n Severity : %s\n\n", procNumberString, ErrorSeverityValueString( errorSeverity ));
  2762. //
  2763. // Initialize Error Sections processing.
  2764. //
  2765. if (!SetErrorDeviceGuids()) {
  2766. return( E_FAIL );
  2767. }
  2768. //
  2769. // Pass through all the record sections.
  2770. //
  2771. sectionHeaderSize = GetTypeSize( "hal!_ERROR_SECTION_HEADER" );
  2772. if ( sectionHeaderSize == 0 ) {
  2773. dprintf( "Unable to get HAL!_ERROR_SECTION_HEADER type size\n\n" );
  2774. return( E_FAIL );
  2775. }
  2776. section = McaLog + (ULONG64)RecordHeaderSize;
  2777. sectionMax = McaLog + mcaLogLength;
  2778. hr = S_OK;
  2779. while( (section < sectionMax) /* successful or not, we proceed... && SUCCEEDED(hr) */ ) {
  2780. ULONG sectionLength;
  2781. ERROR_SECTION_HEADER_TYPE_IA64 sectionType;
  2782. if ( sectionMax <= (section + sectionHeaderSize) ) { // This should not happen...
  2783. dprintf("Invalid MCA Log Length = %ld. SectionMax < (Section + Section Header Size). Stop processing...\n\n",
  2784. mcaLogLength);
  2785. return( E_FAIL );
  2786. }
  2787. if ( InitTypeRead( section, hal!_ERROR_SECTION_HEADER ) ) {
  2788. dprintf( "Unable to read HAL!_ERROR_SECTION_HEADER at 0x%I64x. Stop processing...\n\n", section );
  2789. return( E_FAIL );
  2790. }
  2791. sectionLength = (ULONG)ReadField( Length );
  2792. sectionType = GetTypedErrorSectionType();
  2793. dprintf("MCA Error Section Header @ 0x%I64x 0x%I64x [%s]\n",
  2794. section,
  2795. (section + sectionLength),
  2796. ErrorSectionTypeString( sectionType )
  2797. );
  2798. if ( ( section + sectionLength ) > sectionMax ) {
  2799. //
  2800. // Invalid log
  2801. //
  2802. dprintf( "\n\n Invalid MCA Log Length. Stop processing...\n\n" );
  2803. return ( E_FAIL );
  2804. }
  2805. switch( sectionType ) {
  2806. case ERROR_SECTION_PROCESSOR:
  2807. if ( Flags & ERROR_SECTION_PROCESSOR_FLAG ) {
  2808. hr = DtErrorSectionProcessor( section );
  2809. } else {
  2810. dprintf( "Skipping ERROR_SECTION_PROCESSOR\n\n" );
  2811. }
  2812. break;
  2813. case ERROR_SECTION_PLATFORM_SPECIFIC:
  2814. if ( Flags & ERROR_SECTION_PLATFORM_SPECIFIC_FLAG ) {
  2815. hr = DtErrorSectionPlatformSpecific( section );
  2816. } else {
  2817. dprintf( "Skipping ERROR_SECTION_PLATFORM_SPECIFIC\n\n" );
  2818. }
  2819. break;
  2820. case ERROR_SECTION_MEMORY:
  2821. if ( Flags & ERROR_SECTION_MEMORY_FLAG ) {
  2822. hr = DtErrorSectionMemory( section );
  2823. } else {
  2824. dprintf( "Skipping ERROR_SECTION_MEMORY\n\n" );
  2825. }
  2826. break;
  2827. case ERROR_SECTION_PCI_COMPONENT:
  2828. if ( Flags & ERROR_SECTION_PCI_COMPONENT_FLAG ) {
  2829. hr = DtErrorSectionPciComponent( section );
  2830. } else {
  2831. dprintf( "Skipping ERROR_SECTION_PCI_COMPONENT\n\n" );
  2832. }
  2833. break;
  2834. case ERROR_SECTION_PCI_BUS:
  2835. if ( Flags & ERROR_SECTION_PCI_BUS_FLAG ) {
  2836. hr = DtErrorSectionPciBus( section );
  2837. } else {
  2838. dprintf( "Skipping ERROR_SECTION_PCI_BUS\n\n" );
  2839. }
  2840. break;
  2841. case ERROR_SECTION_SYSTEM_EVENT_LOG:
  2842. if ( Flags & ERROR_SECTION_SYSTEM_EVENT_LOG_FLAG ) {
  2843. hr = DtErrorSectionSystemEventLog( section );
  2844. } else {
  2845. dprintf( "Skipping ERROR_SECTION_SYSTEM_EVENT_LOG\n\n" );
  2846. }
  2847. break;
  2848. case ERROR_SECTION_PLATFORM_HOST_CONTROLLER:
  2849. if ( Flags & ERROR_SECTION_PLATFORM_HOST_CONTROLLER_FLAG ) {
  2850. hr = DtErrorSectionPlatformHostController( section );
  2851. } else {
  2852. dprintf( "Skipping ERROR_SECTION_PLATFORM_HOST_CONTROLLER\n\n" );
  2853. }
  2854. break;
  2855. case ERROR_SECTION_PLATFORM_BUS:
  2856. if ( Flags & ERROR_SECTION_PLATFORM_BUS_FLAG ) {
  2857. hr = DtErrorSectionPlatformBus( section );
  2858. } else {
  2859. dprintf( "Skipping ERROR_SECTION_PLATFORM_BUS_FLAG\n\n" );
  2860. }
  2861. break;
  2862. case ERROR_SECTION_UNKNOWN:
  2863. default: // includes all the section types with incomplete processing...
  2864. sprintf(cmd, "dt -o -r hal!_ERROR_SECTION_HEADER 0x%I64x", section);
  2865. ExecCommand(cmd);
  2866. hr = S_OK;
  2867. break;
  2868. }
  2869. if ( sectionLength ) {
  2870. dprintf( "\n" );
  2871. }
  2872. else {
  2873. // Prevents looping on the same section...
  2874. dprintf("Invalid section Length = 0. Stop processing...\n\n");
  2875. return( E_FAIL );
  2876. }
  2877. section += sectionLength;
  2878. }
  2879. return( hr );
  2880. } // DtMcaLog()
  2881. #define LOW2HIGH FALSE
  2882. #define HIGH2LOW TRUE
  2883. HRESULT
  2884. DtBitMapEnum(
  2885. ULONG64 Module,
  2886. ULONG TypeId,
  2887. UINT BitMap, // Enums are unsigned ints
  2888. BOOLEAN HighToLow
  2889. )
  2890. /*++
  2891. Routine Description:
  2892. This function dumps out a bitmap value composed of enums
  2893. Arugments:
  2894. Module -
  2895. TypeId -
  2896. BitMap -
  2897. Return Value:
  2898. HRESULT
  2899. --*/
  2900. {
  2901. ULONG size;
  2902. HRESULT hr;
  2903. hr = g_ExtSymbols->GetTypeSize( Module, TypeId, &size );
  2904. if ( SUCCEEDED(hr) ) {
  2905. CHAR name[MAX_PATH];
  2906. if ( BitMap ) {
  2907. ULONG map = (ULONG)BitMap;
  2908. ULONG i = 0;
  2909. BOOLEAN first = TRUE;
  2910. size *= 8;
  2911. dprintf("[");
  2912. while( map && (i <size) ) {
  2913. ULONG val;
  2914. val = (HighToLow) ? ((ULONG)0x80000000 >> i) : (0x1 << i);
  2915. if ( map & val ) {
  2916. hr = g_ExtSymbols->GetConstantName( Module,
  2917. TypeId,
  2918. (ULONG64)val,
  2919. name,
  2920. sizeof(name),
  2921. NULL );
  2922. if ( first ) {
  2923. first = FALSE;
  2924. }
  2925. else {
  2926. dprintf("|");
  2927. }
  2928. if ( SUCCEEDED(hr) ) {
  2929. dprintf("%s", name);
  2930. if ( !strcmp(name, "HAL_MCE_PROCNUMBER") ) {
  2931. gMceProcNumberMaskTimeStamp = (ULONGLONG)(LONG)~val;
  2932. }
  2933. }
  2934. else {
  2935. dprintf("0x%lx", val);
  2936. }
  2937. map &= ~val;
  2938. }
  2939. i++;
  2940. }
  2941. dprintf("]");
  2942. }
  2943. else {
  2944. // BitMap = 0
  2945. hr = g_ExtSymbols->GetConstantName( Module,
  2946. TypeId,
  2947. (ULONG64)BitMap,
  2948. name,
  2949. sizeof(name),
  2950. NULL
  2951. );
  2952. if ( SUCCEEDED(hr) ) {
  2953. dprintf("[%s]", name);
  2954. }
  2955. }
  2956. }
  2957. return hr;
  2958. } // DtBitMapEnum()
  2959. VOID
  2960. InitMcaIa64(
  2961. PCSTR args
  2962. )
  2963. //
  2964. // IA-64 !mca extension global initializations
  2965. //
  2966. {
  2967. USHORT flags;
  2968. ULONG64 halpSalPalDataAddress;
  2969. halpSalPalDataAddress = GetExpression("hal!HalpSalPalData");
  2970. if ( !InitTypeRead( halpSalPalDataAddress, hal!_HALP_SAL_PAL_DATA) ) {
  2971. gHalpSalPalDataFlags = (USHORT)ReadField( Flags );
  2972. }
  2973. // TF 04/27/01 TEMPTEMP
  2974. // Added the feature to force gHalpSalPalDataFlags to a known value to
  2975. // handle IA64 developers-release Firmware, without rebuilding the target hal.
  2976. flags = 0;
  2977. if (args && *args) {
  2978. flags = (USHORT)GetExpression( args );
  2979. dprintf("hal!HalpSalPalDataFlags is forced to 0x%lx - was 0x%lx\n\n", flags, gHalpSalPalDataFlags);
  2980. gHalpSalPalDataFlags = flags;
  2981. }
  2982. SetErrorSeverityValues();
  2983. return;
  2984. } // InitMcaIa64()
  2985. HRESULT
  2986. McaIa64(
  2987. PCSTR args
  2988. )
  2989. /*++
  2990. Routine Description:
  2991. Dumps processors IA64 Machine Check record and interprets any logged errors
  2992. Arguments:
  2993. PCSTR args
  2994. Return Value:
  2995. None
  2996. --*/
  2997. {
  2998. HRESULT status;
  2999. ULONG64 mcaLog;
  3000. ULONG recordHeaderSize;
  3001. ULONG featureBits;
  3002. ULONG64 flags;
  3003. // Thierry: 10/01/2000
  3004. // Very simple processing for now. We will be adding features with time.
  3005. // As a first enhancement, we could access the fist mca log address directly from
  3006. // _KPCR.OsMcaResource.EventPool.
  3007. //
  3008. status = S_OK;
  3009. if (!GetExpressionEx(args,&mcaLog, &args)) {
  3010. dprintf("USAGE: !mca <address> <Flags>\n");
  3011. dprintf("Where Flags = (Applies to Itanium Architecture Only)\n");
  3012. dprintf(" Dump Processor Section 0x01\n");
  3013. dprintf(" Dump Platform Specific Section 0x02\n");
  3014. dprintf(" Dump Memory Section 0x04\n");
  3015. dprintf(" Dump PCI Component Section 0x08\n");
  3016. dprintf(" Dump PCI Bus Section 0x10\n");
  3017. dprintf(" Dump SystemEvent Log Section 0x20\n");
  3018. dprintf(" Dump Platform Host Controller Section 0x40\n");
  3019. dprintf(" Dump Platform Bus Section 0x80\n");
  3020. dprintf(" Dump All Sections Present in Log 0xFF\n");
  3021. return E_INVALIDARG;
  3022. }
  3023. //
  3024. // Get the flags argument if there is one
  3025. // If no flag, then we dump entire mca log
  3026. //
  3027. if (!GetExpressionEx(args, &flags, &args)) {
  3028. flags = 0xff;
  3029. }
  3030. //
  3031. // Present HAL Feature Bits
  3032. //
  3033. featureBits = GetUlongValue("hal!HalpFeatureBits");
  3034. if ( featureBits ) {
  3035. ULONG typeId;
  3036. ULONG64 module;
  3037. dprintf("hal!HalpFeatureBits: 0x%lx ", featureBits);
  3038. status = g_ExtSymbols->GetSymbolTypeId("hal!_HALP_FEATURE", &typeId, &module);
  3039. if ( SUCCEEDED(status) ) {
  3040. DtBitMapEnum( module, typeId, featureBits, LOW2HIGH );
  3041. } else {
  3042. dprintf ("GetSymbolTypeId failed for hal!_HALP_FEATURE. status = %x.\n\n", (ULONG) status);
  3043. }
  3044. dprintf("\n\n");
  3045. } else {
  3046. dprintf ("hal!HalpFeatureBits not found... sympath problems? status = %x.\n\n", (ULONG) status);
  3047. }
  3048. //
  3049. // Global initializations for record processing functions.
  3050. //
  3051. InitMcaIa64( args );
  3052. //
  3053. // Does our HAL pdb file have knowledge of IA64 Error formats?
  3054. //
  3055. recordHeaderSize = GetTypeSize( "hal!_ERROR_RECORD_HEADER" );
  3056. if (recordHeaderSize) {
  3057. InitTypeRead( mcaLog, hal!_ERROR_RECORD_HEADER );
  3058. status = DtMcaLog( mcaLog, recordHeaderSize, flags );
  3059. if (!SUCCEEDED(status)) {
  3060. dprintf ("DtMcaLog failed. status = %x.\n\n", (ULONG) status);
  3061. }
  3062. } else {
  3063. dprintf ("hal!_ERROR_RECORD_HEADER not found.\n\n");
  3064. status = E_FAIL;
  3065. }
  3066. return status;
  3067. } // McaIa64()
  3068. DECLARE_API( mca )
  3069. /*++
  3070. Routine Description:
  3071. Dumps processors machine check architecture registers
  3072. and interprets any logged errors
  3073. Arguments:
  3074. PDEBUG_CLIENT Client
  3075. PCSTR args
  3076. Return Value:
  3077. None
  3078. --*/
  3079. {
  3080. HRESULT status;
  3081. ULONG processor = 0;
  3082. INIT_API();
  3083. GetCurrentProcessor(Client, &processor, NULL);
  3084. //
  3085. // Simply dispatch to the right target machine handler.
  3086. //
  3087. switch( TargetMachine ) {
  3088. case IMAGE_FILE_MACHINE_I386:
  3089. // Display architectural MCA information.
  3090. status = McaX86( args );
  3091. // Finally, Display stepping information for current processor.
  3092. DumpCpuInfoX86( processor, TRUE );
  3093. break;
  3094. case IMAGE_FILE_MACHINE_IA64:
  3095. // Display architectural MCA information.
  3096. status = McaIa64( args );
  3097. // Finally, Display stepping information for current processor.
  3098. if (SUCCEEDED(status)) {
  3099. DumpCpuInfoIA64( processor, TRUE );
  3100. }
  3101. break;
  3102. default:
  3103. dprintf("!mca is not supported for this target machine:%ld\n", TargetMachine);
  3104. status = E_INVALIDARG;
  3105. }
  3106. EXIT_API();
  3107. return status;
  3108. } // !mca
  3109. DECLARE_API( fwver )
  3110. /*++
  3111. Routine Description:
  3112. Dumps the firmware version information on IA64 platforms
  3113. Arguments:
  3114. PDEBUG_CLIENT Client
  3115. PCSTR args
  3116. Return Value:
  3117. None
  3118. --*/
  3119. {
  3120. HRESULT status;
  3121. ULONG processor = 0;
  3122. ULONG64 halpSalPalDataAddress;
  3123. USHORT salRevision;
  3124. UCHAR palRevision;
  3125. UCHAR palModel;
  3126. ULONG64 smbiosString;
  3127. ULONG64 sstHeader;
  3128. UCHAR tmpUchar;
  3129. UNREFERENCED_PARAMETER (args);
  3130. INIT_API();
  3131. status = S_OK;
  3132. GetCurrentProcessor(Client, &processor, NULL);
  3133. //
  3134. // Simply dispatch to the right target machine handler.
  3135. //
  3136. if ( TargetMachine == IMAGE_FILE_MACHINE_IA64 ) {
  3137. halpSalPalDataAddress = GetExpression("hal!HalpSalPalData");
  3138. if ( !InitTypeRead( halpSalPalDataAddress, hal!_HALP_SAL_PAL_DATA) ) {
  3139. dprintf( "\nFirmware Version\n\n" );
  3140. //
  3141. // Print the SAL revision
  3142. //
  3143. sstHeader = ReadField( SalSystemTable );
  3144. GetFieldValue( sstHeader, "hal!_SST_HEADER", "SalRev", salRevision );
  3145. dprintf( " Sal Revision: %x\n", salRevision );
  3146. GetFieldValue( sstHeader, "hal!_SST_HEADER", "Sal_A_Version", salRevision );
  3147. dprintf( " SAL_A_VERSION: %x\n", salRevision );
  3148. GetFieldValue( sstHeader, "hal!_SST_HEADER", "Sal_B_Version", salRevision );
  3149. dprintf( " SAL_B_VERSION: %x\n", salRevision );
  3150. //
  3151. // Print the PAL revision
  3152. //
  3153. palRevision = (UCHAR)ReadField( PalVersion.PAL_A_Revision );
  3154. palModel = (UCHAR)ReadField( PalVersion.PAL_A_Model );
  3155. dprintf( " PAL_A_VERSION: %x%x\n", palModel, palRevision );
  3156. palRevision = (UCHAR)ReadField( PalVersion.PAL_B_Revision );
  3157. palModel = (UCHAR)ReadField( PalVersion.PAL_B_Model );
  3158. dprintf( " PAL_B_VERSION: %x%x\n", palModel, palRevision );
  3159. //
  3160. // Print the SMBIOS string
  3161. //
  3162. smbiosString = ReadField( SmBiosVersion );
  3163. if ( smbiosString ) {
  3164. dprintf( " smbiosString: " );
  3165. //
  3166. // Iterate through the SMBIOS string printing it a
  3167. // character at a time. We have to do this because
  3168. // the 32-bit extension dll print routines don't
  3169. // handle 64-bit string pointers.
  3170. //
  3171. ReadMemory( smbiosString, &tmpUchar, sizeof( UCHAR ), NULL );
  3172. while ( tmpUchar ) {
  3173. dprintf( "%c", tmpUchar);
  3174. smbiosString += 1;
  3175. ReadMemory( smbiosString, &tmpUchar, sizeof( UCHAR ), NULL );
  3176. }
  3177. }
  3178. dprintf( "\n" );
  3179. } else {
  3180. dprintf( "Unable to get hal!HalpSalPalData\n\n" );
  3181. status = E_FAIL;
  3182. }
  3183. } else {
  3184. dprintf( "This is only supported on IA64 systems\n\n" );
  3185. status = E_FAIL;
  3186. }
  3187. if ( SUCCEEDED( status ) ) {
  3188. dprintf( "\n" );
  3189. }
  3190. EXIT_API();
  3191. return status;
  3192. } // !mca
  3193. VOID
  3194. DumpAffinity(
  3195. ULONG64 AffinityMask,
  3196. ULONG NumberOfBits
  3197. )
  3198. {
  3199. CHAR Buffer[65];
  3200. ULONG64 CurrentBit;
  3201. ULONG i;
  3202. CurrentBit = 1;
  3203. i = 0;
  3204. while (i < NumberOfBits) {
  3205. if (AffinityMask & CurrentBit) {
  3206. Buffer[i] = '*';
  3207. } else {
  3208. Buffer[i] = '-';
  3209. }
  3210. i++;
  3211. CurrentBit <<= 1;
  3212. }
  3213. Buffer[i] = '\0';
  3214. dprintf(Buffer);
  3215. }
  3216. DECLARE_API( smt )
  3217. /*++
  3218. Routine Description:
  3219. Dumps processor data structures related to SMT.
  3220. Arguments:
  3221. PDEBUG_CLIENT Client
  3222. PCSTR args
  3223. Return Value:
  3224. None
  3225. --*/
  3226. {
  3227. HRESULT status;
  3228. ULONG64 activeProcessors, idleSummary;
  3229. ULONG64 Address;
  3230. ULONG i, physicalProcessors;
  3231. INIT_API();
  3232. if (TargetMachine != IMAGE_FILE_MACHINE_I386) {
  3233. dprintf("SMT functionality is only supported on x86 targets\n");
  3234. EXIT_API();
  3235. return E_INVALIDARG;
  3236. }
  3237. dprintf("SMT Summary:\n");
  3238. dprintf("------------\n");
  3239. activeProcessors = GetUlongValue ("KeActiveProcessors");
  3240. dprintf(" KeActiveProcessors: ");
  3241. DumpAffinity(activeProcessors, 32);
  3242. dprintf(" (%08I64x)\n", activeProcessors);
  3243. idleSummary = GetUlongValue ("KiIdleSummary");
  3244. dprintf(" KiIdleSummary: ");
  3245. DumpAffinity(idleSummary, 32);
  3246. dprintf(" (%08I64x)\n", idleSummary);
  3247. dprintf("No PRCB Set Master SMT Set IAID #LP\n");
  3248. physicalProcessors = 0;
  3249. for (i = 0; i < 32; i++) {
  3250. if (activeProcessors & (1 << i)) {
  3251. status = g_ExtData->ReadProcessorSystemData(i,
  3252. DEBUG_DATA_KPRCB_OFFSET,
  3253. &Address,
  3254. sizeof(Address),
  3255. NULL);
  3256. if (status != S_OK) {
  3257. dprintf("unable to read data for processor %d\n", i);
  3258. continue;
  3259. }
  3260. if (InitTypeRead(Address, nt!_KPRCB) )
  3261. {
  3262. dprintf("Unable to read PRCB for processor %d\n", i);
  3263. continue;
  3264. }
  3265. dprintf("%2d %08x ",
  3266. (ULONG) ReadField(Number),
  3267. (ULONG) Address);
  3268. if (Address == ReadField(MultiThreadSetMaster)) {
  3269. dprintf(" Master ");
  3270. physicalProcessors++;
  3271. } else {
  3272. dprintf(" %08x ", (ULONG) ReadField(MultiThreadSetMaster));
  3273. }
  3274. DumpAffinity(ReadField(MultiThreadProcessorSet), 32);
  3275. dprintf(" (%08x) %02X %3d\n",
  3276. (ULONG) ReadField(MultiThreadProcessorSet),
  3277. (ULONG) ReadField(InitialApicId),
  3278. (ULONG) ReadField(LogicalProcessorsPerPhysicalProcessor));
  3279. }
  3280. }
  3281. dprintf("\n Number of licensed physical processors: %d\n", physicalProcessors);
  3282. status = STATUS_SUCCESS;
  3283. EXIT_API();
  3284. return status;
  3285. }
  3286. NTSTATUS
  3287. DumpKNODE(
  3288. IN ULONG64 Address,
  3289. IN ULONG Node
  3290. )
  3291. /*++
  3292. Routine Description:
  3293. This dumps the a KNODE structure that defines a NUMA node
  3294. from the kernel perspective.
  3295. Arguments:
  3296. Address -- Address of the table
  3297. Node -- Node number this KNODE structure should have.
  3298. Return Value:
  3299. NTSTATUS
  3300. --*/
  3301. {
  3302. ULONG Offset;
  3303. if (InitTypeRead(Address, nt!_KNODE) )
  3304. {
  3305. dprintf("Unable to read KNODE for processor %d\n", Node);
  3306. return STATUS_UNSUCCESSFUL;
  3307. }
  3308. if (ReadField(NodeNumber) != Node) {
  3309. dprintf("WARNING: Expected node number and actual node number differ\n");
  3310. }
  3311. dprintf(" NODE %d (%016I64X):\n", Node, Address);
  3312. dprintf("\tProcessorMask : ");
  3313. DumpAffinity(ReadField(ProcessorMask), GetTypeSize("nt!KAFFINITY") * 8);
  3314. dprintf("\n\tColor : 0x%08X\n\tMmShiftedColor : 0x%08X\n\tSeed : 0x%08X\n",
  3315. (ULONG) ReadField(Color),
  3316. (ULONG) ReadField(MmShiftedColor),
  3317. (ULONG) ReadField(Seed));
  3318. GetFieldOffset("nt!_KNODE", "FreeCount", &Offset);
  3319. Address += Offset;
  3320. dprintf("\tZeroed Page Count: 0x%016I64X\n",
  3321. GetPointerFromAddress(Address));
  3322. Address += GetTypeSize("nt!PFN_NUMBER");
  3323. dprintf("\tFree Page Count : 0x%016I64X\n",
  3324. GetPointerFromAddress(Address));
  3325. return STATUS_SUCCESS;
  3326. }
  3327. DECLARE_API( numa )
  3328. {
  3329. ULONG64 activeProcessors;
  3330. ULONG64 address;
  3331. ULONG numberNodes;
  3332. ULONG i;
  3333. HRESULT status = STATUS_UNSUCCESSFUL;
  3334. INIT_API();
  3335. address = GetExpression("nt!KeNumberNodes");
  3336. if (!address) {
  3337. dprintf("No NUMA information found\n");
  3338. goto out;
  3339. }
  3340. numberNodes = (ULONG) GetByteValue("nt!KeNumberNodes");
  3341. dprintf("NUMA Summary:\n");
  3342. dprintf("------------\n");
  3343. dprintf(" Number of NUMA nodes : %d\n", numberNodes);
  3344. dprintf(" Number of Processors : %d\n", (ULONG) GetByteValue("nt!KeNumberProcessors"));
  3345. dprintf(" MmAvailablePages : 0x%08X\n", GetUlongValue("nt!MmAvailablePages"));
  3346. address = GetExpression("nt!KeActiveProcessors");
  3347. if (!address) {
  3348. dprintf("Could not get processor configuration, exiting.\n");
  3349. goto out;
  3350. }
  3351. if (ReadPtr(address, &activeProcessors) || (activeProcessors == 0)) {
  3352. dprintf("Unable to get active processor set. Cannot continue.\n");
  3353. goto out;
  3354. }
  3355. dprintf(" KeActiveProcessors : ");
  3356. DumpAffinity(activeProcessors, GetTypeSize("nt!KAFFINITY") * 8);
  3357. dprintf(" (%016I64x)\n", activeProcessors);
  3358. address = GetExpression("nt!KeNodeBlock");
  3359. if (!address) {
  3360. dprintf("Unable to get KeNodeBlock. Cannot continue.\n");
  3361. goto out;
  3362. }
  3363. for (i = 0; i < numberNodes; i++) {
  3364. if (CheckControlC()) {
  3365. break;
  3366. }
  3367. dprintf("\n");
  3368. DumpKNODE(GetPointerFromAddress(address), i);
  3369. address += GetTypeSize("nt!PKNODE");
  3370. }
  3371. status = STATUS_SUCCESS;
  3372. out:
  3373. EXIT_API();
  3374. return status;
  3375. }