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.

996 lines
30 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. cpuid.c
  5. Abstract:
  6. Originally written to test the fix to an OS bug but indended to be
  7. expanded as time allows to dump out as much useful stuff as we can.
  8. Author:
  9. Peter L Johnston (peterj) July 14, 1999.
  10. Revision History:
  11. Notes:
  12. --*/
  13. #include <windows.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <winbase.h>
  17. VOID
  18. PrintFeatures(
  19. ULONG_PTR Result,
  20. PUCHAR FeatureBitDescription[]
  21. );
  22. #if defined(_X86_)
  23. typedef enum {
  24. CPU_NONE,
  25. CPU_INTEL,
  26. CPU_AMD,
  27. CPU_CYRIX,
  28. CPU_UNKNOWN
  29. } CPU_VENDORS;
  30. PUCHAR X86FeatureBitDescription[] = {
  31. /* 0 */ "FPU 387 (Floating Point) instructions",
  32. /* 1 */ "VME Virtual 8086 Mode Enhancements",
  33. /* 2 */ "DE Debugging Extensions",
  34. /* 3 */ "PSE Page Size Extensions (4MB pages)",
  35. /* 4 */ "TSC Time Stamp Counter",
  36. /* 5 */ "MSR Model Specific Registers (RDMSR/WRMSR)",
  37. /* 6 */ "PAE Physical Address Extension (> 32 bit physical addressing)",
  38. /* 7 */ "MCE Machine Check Exception",
  39. /* 8 */ "CX8 CMPXCHG8B (compare and exchange 8 byte)",
  40. /* 9 */ "APIC Advanced Programmable Interrupt Controller",
  41. /* 10 */ "Reserved",
  42. /* 11 */ "SEP Fast System Call (SYSENTER/SYSEXIT)",
  43. /* 12 */ "MTRR Memory Type Range Registers",
  44. /* 13 */ "PGE PTE Global Flag",
  45. /* 14 */ "MCA Machine Check Architecture",
  46. /* 15 */ "CMOV Conditional Move and Compare",
  47. /* 16 */ "PAT Page Attribute Table",
  48. /* 17 */ "PSE36 4MB pages can have 36 bit physical addresses",
  49. /* 18 */ "PN 96 bit Processor Number",
  50. /* 19 */ "CLFLSH Cache Line Flush",
  51. /* 20 */ "Reserved",
  52. /* 21 */ "DTS Debug Trace Store",
  53. /* 22 */ "ACPI ACPI Thermal Throttle Registers",
  54. /* 23 */ "MMX Multi Media eXtensions",
  55. /* 24 */ "FXSR Fast Save/Restore (FXSAVE/FXRSTOR)",
  56. /* 25 */ "XMM Streaming Simd Extensions",
  57. /* 26 */ "WNI Willamette New Instructions",
  58. /* 27 */ "SLFSNP Self Snoop",
  59. /* 28 */ "JT Jackson Technology (SMT)",
  60. /* 29 */ "ATHROT Automatic Thermal Throttle",
  61. /* 30 */ "IA64 64 Bit Intel Architecture",
  62. /* 31 */ "Reserved"
  63. };
  64. PUCHAR AMDExtendedFeatureBitDescription[] = {
  65. /* 0 */ "FPU 387 (Floating Point) instructions",
  66. /* 1 */ "VME Virtual 8086 Mode Enhancements",
  67. /* 2 */ "DE Debugging Extensions",
  68. /* 3 */ "PSE Page Size Extensions (4MB pages)",
  69. /* 4 */ "TSC Time Stamp Counter",
  70. /* 5 */ "MSR Model Specific Registers (RDMSR/WRMSR)",
  71. /* 6 */ "PAE Physical Address Extension (> 32 bit physical addressing)",
  72. /* 7 */ "MCE Machine Check Exception",
  73. /* 8 */ "CX8 CMPXCHG8B (compare and exchange 8 byte)",
  74. /* 9 */ "APIC Advanced Programmable Interrupt Controller",
  75. /* 10 */ "Reserved",
  76. /* 11 */ " SYSCALL and SYSRET Instructions",
  77. /* 12 */ "MTRR Memory Type Range Registers",
  78. /* 13 */ "PGE PTE Global Flag",
  79. /* 14 */ "MCA Machine Check Architecture",
  80. /* 15 */ "CMOV Conditional Move and Compare",
  81. /* 16 */ "PAT Page Attribute Table",
  82. /* 17 */ "PSE36 4MB pages can have 36 bit physical addresses",
  83. /* 18 */ "Reserved",
  84. /* 19 */ "Reserved",
  85. /* 20 */ "Reserved",
  86. /* 21 */ "Reserved",
  87. /* 22 */ " AMD MMX Instruction Extensions",
  88. /* 23 */ "MMX Multi Media eXtensions",
  89. /* 24 */ "FXSR Fast Save/Restore (FXSAVE/FXRSTOR)",
  90. /* 25 */ "Reserved",
  91. /* 26 */ "Reserved",
  92. /* 27 */ "Reserved",
  93. /* 28 */ "Reserved",
  94. /* 29 */ "Reserved",
  95. /* 30 */ " AMD 3DNow! Instruction Extensions",
  96. /* 31 */ " 3DNow! Instructions",
  97. };
  98. // From Intel AP-485, Order Number: 241618-021, May 2002
  99. PUCHAR BrandIndex[] = {
  100. "Intel Celeron", // 0x01
  101. "Intel Pentium III", // 0x02
  102. "Intel Pentium III Xeon", // 0x03
  103. "Intel Pentium III", // 0x04
  104. "Reserved", // 0x05
  105. "Mobile Intel Pentium IIIM", // 0x06
  106. "Mobile Intel Celeron", // 0x07
  107. "Intel Pentium 4", // 0x08
  108. "Intel Pentium 4", // 0x09
  109. "Intel Celeron", // 0x0a
  110. "Intel Xeon", // 0x0b
  111. "Intel Xeon MP", // 0x0c
  112. "Reserved", // 0x0d
  113. "Mobile Intel Pentium 4M", // 0x0e
  114. "Mobile Intel Celeron", // 0x0f
  115. };
  116. VOID
  117. ExecuteCpuidFunction(
  118. IN ULONG Function,
  119. OUT PULONG Results
  120. );
  121. BOOLEAN
  122. IsCpuidPresent(
  123. VOID
  124. );
  125. PUCHAR
  126. AMD_Associativity(
  127. ULONG Descriptor
  128. )
  129. {
  130. switch (Descriptor) {
  131. case 0x0: return"L2 Off";
  132. case 0x1: return"Direct";
  133. case 0x2: return" 2 way";
  134. case 0x4: return" 4 way";
  135. case 0x6: return" 8 way";
  136. case 0x8: return"16 way";
  137. case 0xff: return" Full";
  138. default:
  139. return"Reserved";
  140. }
  141. }
  142. VOID
  143. AMD_DI_TLB(
  144. ULONG Format,
  145. ULONG TLBDesc
  146. )
  147. {
  148. UCHAR Which = 'D';
  149. ULONG AssocIndex;
  150. ULONG Entries;
  151. if ((TLBDesc >> 16) == 0) {
  152. //
  153. // Unified.
  154. //
  155. TLBDesc <<= 16;
  156. Which = ' ';
  157. }
  158. do {
  159. if (Format == 1) {
  160. AssocIndex = TLBDesc >> 24;
  161. Entries = (TLBDesc >> 16) & 0xff;
  162. } else {
  163. AssocIndex = TLBDesc >> 28;
  164. Entries = (TLBDesc >> 16) & 0xfff;
  165. }
  166. printf(" %8s %4d entry %cTLB",
  167. AMD_Associativity(AssocIndex),
  168. Entries,
  169. Which
  170. );
  171. //
  172. // Repeat for lower half of descriptor.
  173. //
  174. TLBDesc <<= 16;
  175. Which = 'I';
  176. } while (TLBDesc);
  177. printf("\n");
  178. }
  179. VOID
  180. AMD_Cache(
  181. ULONG Format,
  182. ULONG CacheDesc
  183. )
  184. {
  185. ULONG Size;
  186. ULONG AssocIndex;
  187. ULONG LinesPerTag;
  188. ULONG LineSize;
  189. if (Format == 1) {
  190. Size = CacheDesc >> 24;
  191. AssocIndex = (CacheDesc >> 16) & 0xff;
  192. LinesPerTag = (CacheDesc >> 8) & 0xff;
  193. LineSize = CacheDesc & 0xff;
  194. } else {
  195. Size = CacheDesc >> 16;
  196. AssocIndex = (CacheDesc >> 12) & 0xf;
  197. LinesPerTag = (CacheDesc >> 8) & 0xf;
  198. LineSize = CacheDesc & 0xff;
  199. }
  200. printf(" %8s %5dKB (%d L/T)%3d bytes per line.\n",
  201. AMD_Associativity(AssocIndex),
  202. Size,
  203. LinesPerTag,
  204. LineSize
  205. );
  206. }
  207. #endif
  208. #if defined(_IA64_)
  209. ULONGLONG
  210. ia64CPUID(
  211. ULONGLONG Index
  212. );
  213. PUCHAR IA64FeatureBitDescription[] = {
  214. /* 0 */ "BRL Long Branch instructions",
  215. /* 1 */ "Reserved-01",
  216. /* 2 */ "Reserved-02",
  217. /* 3 */ "Reserved-03",
  218. /* 4 */ "Reserved-04",
  219. /* 5 */ "Reserved-05",
  220. /* 6 */ "Reserved-06",
  221. /* 7 */ "Reserved-07",
  222. /* 8 */ "Reserved-08",
  223. /* 9 */ "Reserved-09",
  224. /* 10 */ "Reserved-10",
  225. /* 11 */ "Reserved-11",
  226. /* 12 */ "Reserved-12",
  227. /* 13 */ "Reserved-13",
  228. /* 14 */ "Reserved-14",
  229. /* 15 */ "Reserved-15",
  230. /* 16 */ "Reserved-16",
  231. /* 17 */ "Reserved-17",
  232. /* 18 */ "Reserved-18",
  233. /* 19 */ "Reserved-19",
  234. /* 20 */ "Reserved-20",
  235. /* 21 */ "Reserved-21",
  236. /* 22 */ "Reserved-22",
  237. /* 23 */ "Reserved-23",
  238. /* 24 */ "Reserved-24",
  239. /* 25 */ "Reserved-25",
  240. /* 26 */ "Reserved-26",
  241. /* 27 */ "Reserved-27",
  242. /* 28 */ "Reserved-28",
  243. /* 29 */ "Reserved-29",
  244. /* 30 */ "Reserved-30",
  245. /* 31 */ "Reserved-31",
  246. /* 32 */ "Reserved-32",
  247. /* 33 */ "Reserved-33",
  248. /* 34 */ "Reserved-34",
  249. /* 35 */ "Reserved-35",
  250. /* 36 */ "Reserved-36",
  251. /* 37 */ "Reserved-37",
  252. /* 38 */ "Reserved-38",
  253. /* 39 */ "Reserved-39",
  254. /* 40 */ "Reserved-40",
  255. /* 41 */ "Reserved-41",
  256. /* 42 */ "Reserved-42",
  257. /* 43 */ "Reserved-43",
  258. /* 44 */ "Reserved-44",
  259. /* 45 */ "Reserved-45",
  260. /* 46 */ "Reserved-46",
  261. /* 47 */ "Reserved-47",
  262. /* 48 */ "Reserved-48",
  263. /* 49 */ "Reserved-49",
  264. /* 50 */ "Reserved-50",
  265. /* 51 */ "Reserved-51",
  266. /* 52 */ "Reserved-52",
  267. /* 53 */ "Reserved-53",
  268. /* 54 */ "Reserved-54",
  269. /* 55 */ "Reserved-55",
  270. /* 56 */ "Reserved-56",
  271. /* 57 */ "Reserved-57",
  272. /* 58 */ "Reserved-58",
  273. /* 59 */ "Reserved-59",
  274. /* 60 */ "Reserved-60",
  275. /* 61 */ "Reserved-61",
  276. /* 62 */ "Reserved-62",
  277. /* 63 */ "Reserved-63"
  278. };
  279. #endif
  280. char *FeatureBitDescription32BitFormat = " %08x %s\n";
  281. char *FeatureBitDescription64BitFormat = " %016I64x %s\n";
  282. VOID
  283. PrintFeatures(
  284. ULONG_PTR Result,
  285. PUCHAR FeatureBitDescription[]
  286. )
  287. {
  288. ULONG_PTR temp, temp2, bit;
  289. char *format = (sizeof(ULONG_PTR) == 8) ? FeatureBitDescription64BitFormat :
  290. FeatureBitDescription32BitFormat;
  291. //
  292. // Feature bits.
  293. //
  294. temp = Result;
  295. if (temp) {
  296. printf(" Features\n");
  297. for (bit = 0, temp2 = 1; temp; bit++, temp2 <<= 1) {
  298. if ((temp2 & temp) == 0) {
  299. //
  300. // Feature bit not set.
  301. //
  302. continue;
  303. }
  304. temp ^= temp2;
  305. printf( format, temp2, FeatureBitDescription[bit]);
  306. }
  307. }
  308. return;
  309. } // PrintFeatures()
  310. __cdecl
  311. main(
  312. LONG Argc,
  313. PUCHAR *Argv
  314. )
  315. {
  316. ULONG Processor;
  317. ULONG Function;
  318. ULONG MaxFunction;
  319. ULONG Temp;
  320. ULONG Temp2, Bit;
  321. HANDLE ProcessHandle;
  322. HANDLE ThreadHandle;
  323. #if defined(_X86_)
  324. ULONG Results[5];
  325. ULONG Family = 0;
  326. ULONG Model = 0;
  327. ULONG Stepping = 0;
  328. ULONG Generation = 0;
  329. BOOLEAN CpuidPresent;
  330. CPU_VENDORS Vendor = CPU_NONE;
  331. ULONG ThreadAffinity;
  332. ULONG SystemAffinity;
  333. ULONG ProcessAffinity;
  334. #endif
  335. #if defined(_IA64_)
  336. ULONGLONG Result;
  337. ULONGLONG ThreadAffinity;
  338. ULONGLONG SystemAffinity;
  339. ULONGLONG ProcessAffinity;
  340. ULONGLONG VendorInformation[3];
  341. #endif
  342. //
  343. // Make sure this process is set to run on any processor in
  344. // the system.
  345. //
  346. ProcessHandle = GetCurrentProcess();
  347. ThreadHandle = GetCurrentThread();
  348. if (!GetProcessAffinityMask(ProcessHandle,
  349. &ProcessAffinity,
  350. &SystemAffinity)) {
  351. printf("Fatal error: Unable to determine process affinity.\n");
  352. exit(1);
  353. }
  354. if (ProcessAffinity != SystemAffinity) {
  355. if (!SetProcessAffinityMask(ProcessHandle,
  356. SystemAffinity)) {
  357. printf("Warning: Unable to run on all processors\n");
  358. printf(" System Affinity %08x\n", SystemAffinity);
  359. printf(" - Process Affinity %08x\n", ProcessAffinity);
  360. printf(" Will Try %08x\n",
  361. SystemAffinity & ProcessAffinity);
  362. SystemAffinity &= ProcessAffinity;
  363. }
  364. ProcessAffinity = SystemAffinity;
  365. }
  366. #if defined(_X86_)
  367. //
  368. // Cpuid returns 4 DWORDs of data. In some cases this is string
  369. // data in which case it needs to be NULL terminated.
  370. //
  371. Results[4] = 0;
  372. #endif
  373. //
  374. // For each CPU in the system, determine the availability of
  375. // the CPUID instruction and dump out anything useful it might
  376. // have to say.
  377. //
  378. for (ThreadAffinity = 1, Processor = 0;
  379. ThreadAffinity;
  380. ThreadAffinity <<= 1, Processor++) {
  381. if (!(ThreadAffinity & ProcessAffinity)) {
  382. //
  383. // Can't test this processor.
  384. //
  385. if (ThreadAffinity > ProcessAffinity) {
  386. //
  387. // Tested all the processors there are, we're done.
  388. //
  389. break;
  390. }
  391. continue;
  392. }
  393. //
  394. // Set affinity so this thread can only run on the processor
  395. // being tested.
  396. //
  397. if (!SetThreadAffinityMask(ThreadHandle,
  398. ThreadAffinity)) {
  399. printf(
  400. "** Could not set affinity %08x for processor %d, skipping.\n",
  401. ThreadAffinity,
  402. Processor);
  403. continue;
  404. }
  405. #if defined(_X86_)
  406. CpuidPresent = IsCpuidPresent();
  407. if (CpuidPresent) {
  408. printf("++ Processor %d\n", Processor);
  409. } else {
  410. printf("-- No CPUID support, processor %d\n", Processor);
  411. continue;
  412. }
  413. //
  414. // CPUID is present, examine basic functions.
  415. //
  416. ExecuteCpuidFunction(0, Results);
  417. MaxFunction = Results[0];
  418. //
  419. // For reasons unclear to anyone, the Vendor ID string comes
  420. // back in the order EBX, EDX, ECX,... so switch the last two
  421. // results before printing it.
  422. //
  423. Temp = Results[3];
  424. Results[3] = Results[2];
  425. Results[2] = Temp;
  426. if (strcmp((PVOID)&Results[1], "GenuineIntel") == 0) {
  427. Vendor = CPU_INTEL;
  428. } else if (strcmp((PVOID)&Results[1], "AuthenticAMD") == 0) {
  429. Vendor = CPU_AMD;
  430. } else if (strcmp((PVOID)&Results[1], "CyrixInstead") == 0) {
  431. Vendor = CPU_CYRIX;
  432. } else {
  433. Vendor = CPU_UNKNOWN;
  434. }
  435. printf(" Vendor ID '%s', Maximum Supported Function %d.\n",
  436. (PUCHAR)(&Results[1]),
  437. MaxFunction);
  438. for (Function = 0; Function <= MaxFunction; Function++) {
  439. ExecuteCpuidFunction(Function, Results);
  440. printf(" F %d raw = %08x %08x %08x %08x\n",
  441. Function,
  442. Results[0],
  443. Results[1],
  444. Results[2],
  445. Results[3]);
  446. //
  447. // Do some interpretation on the ones we know how to
  448. // deal with.
  449. //
  450. switch(Function) {
  451. case 0:
  452. //
  453. // Already handled as the main header (gave max func
  454. // and Vendor ID.
  455. //
  456. break;
  457. case 1:
  458. //
  459. // EAX = Type, Family, Model, Stepping.
  460. // EBX = Family != 0xf ?
  461. // Yes = Reserved,
  462. // No = 0xAABBCCDD where
  463. // AA = APIC ID
  464. // BB = LP per PP
  465. // CC = CLFLUSH line size (8 = 64 bytes)
  466. // DD = Brand Index
  467. // ECX = Reserved
  468. // EDX = Feature Bits
  469. //
  470. //
  471. // Family Model Stepping
  472. //
  473. Temp = Results[0];
  474. Family = (Temp >> 8) & 0xf;
  475. Model = (Temp >> 4) & 0xf;
  476. Stepping = Temp & 0xf;
  477. printf(" Type = %d, Family = %d, Model = %d, Stepping = %d\n",
  478. (Temp >> 12) & 0x3, Family, Model, Stepping);
  479. //
  480. // Willamette stuff
  481. //
  482. if ((Temp & 0xf00) == 0xf00) {
  483. Temp = Results[1] & 0xff;
  484. if (Temp) {
  485. //
  486. // Indexes are a DISGUSTING way to get this info!!
  487. //
  488. printf(" Brand Index %02Xh %s processor\n",
  489. Temp,
  490. Temp <= (sizeof(BrandIndex) / sizeof(PUCHAR)) ?
  491. BrandIndex[Temp-1] :
  492. "Unknown");
  493. }
  494. Temp = (Results[1] >> 8) & 0xff;
  495. printf(" CLFLUSH line size (%x) = %d bytes\n",
  496. Temp,
  497. Temp << 3); // ?? plj - nobasis
  498. Temp = Results[1] >> 16;
  499. printf(" LP per PP %d\n", Temp & 0xff);
  500. printf(" APIC Id %02x\n", Temp >> 8);
  501. }
  502. //
  503. // Feature bits.
  504. //
  505. PrintFeatures( Results[3], X86FeatureBitDescription );
  506. break;
  507. case 2:
  508. //
  509. // Get number of times we have to do function 2 again.
  510. // (Then replace iteration count with a NULL descr).
  511. //
  512. Temp = Results[0] & 0xff;
  513. if (Temp == 0) {
  514. //
  515. // If the count is 0, this processor doesn't do
  516. // function 2, get out.
  517. //
  518. break;
  519. }
  520. Results[0] &= 0xffffff00;
  521. do {
  522. ULONG i;
  523. for (i = 0; i < 4; i++) {
  524. Temp2 = Results[i];
  525. if (Temp2 & 0x80000000) {
  526. //
  527. // Not valid, skip.
  528. //
  529. continue;
  530. }
  531. while (Temp2) {
  532. UCHAR Descriptor = (UCHAR)(Temp2 & 0xff);
  533. ULONG K, Way, Line, Level;
  534. PUCHAR IorD = "";
  535. Temp2 >>= 8;
  536. if (((Descriptor > 0x40) && (Descriptor <= 0x47)) ||
  537. ((Descriptor > 0x78) && (Descriptor <= 0x7c)) ||
  538. ((Descriptor > 0x80) && (Descriptor <= 0x87))) {
  539. //
  540. // It's an L2 Descriptor. (The following
  541. // is peterj's wacky formula,... not
  542. // guaranteed forever but the nice people
  543. // at Intel better pray I'm dead before
  544. // they break it or I'll hunt them down).
  545. //
  546. Level = 2;
  547. Way = Descriptor >= 0x79 ? 8 : 4;
  548. K = 0x40 << (Descriptor & 0x7);
  549. Line = 32;
  550. if ((Descriptor & 0xf8) == 0x78) {
  551. Line = 128;
  552. }
  553. } else if ((Descriptor >= 0x50) &&
  554. (Descriptor <= 0x5d)) {
  555. if (Descriptor & 0x8) {
  556. IorD = "D";
  557. K = 0x40 << (Descriptor - 0x5b);
  558. } else {
  559. IorD = "I";
  560. K = 0x40 << (Descriptor - 0x50);
  561. }
  562. printf(" %02xH %sTLB %d entry\n",
  563. Descriptor,
  564. IorD,
  565. K);
  566. continue;
  567. } else {
  568. PUCHAR s = NULL;
  569. switch (Descriptor) {
  570. case 0x00:
  571. continue;
  572. case 0x01:
  573. s = "ITLB 4KB pages, 4 way, 32 entry";
  574. break;
  575. case 0x02:
  576. s = "ITLB 4MB pages, fully assoc, 2 entry";
  577. break;
  578. case 0x03:
  579. s = "DTLB 4KB pages, 4 way, 64 entry";
  580. break;
  581. case 0x04:
  582. s = "DTLB 4MB pages, 4 way, 8 entry";
  583. break;
  584. case 0x06:
  585. s = "I-Cache 8KB, 4 way, 32B line";
  586. break;
  587. case 0x08:
  588. s = "I-Cache 16KB, 4 way, 32B line";
  589. break;
  590. case 0x0a:
  591. s = "D-Cache 8KB, 2 way, 32B line";
  592. break;
  593. case 0x0c:
  594. s = "D-Cache 16KB, 2 or 4 way, 32B line";
  595. break;
  596. case 0x22:
  597. K = 512; Level = 3; Way = 4; Line = 128;
  598. break;
  599. case 0x23:
  600. K = 1024; Level = 3; Way = 8; Line = 128;
  601. break;
  602. case 0x25:
  603. K = 2048; Level = 3; Way = 8; Line = 128;
  604. break;
  605. case 0x29:
  606. K = 4096; Level = 3; Way = 8; Line = 128;
  607. break;
  608. case 0x40:
  609. s = "No L3 Cache";
  610. break;
  611. case 0x66:
  612. K = 8; Level = 1; Way = 4; Line = 64; IorD = "D";
  613. break;
  614. case 0x67:
  615. K = 16; Level = 1; Way = 4; Line = 64; IorD = "D";
  616. break;
  617. case 0x68:
  618. K = 32; Level = 1; Way = 4; Line = 64; IorD = "D";
  619. break;
  620. case 0x70:
  621. K = 12; Level = 1; Way = 8; Line = 64; IorD = "I";
  622. break;
  623. case 0x71:
  624. K = 16; Level = 1; Way = 8; Line = 64; IorD = "I";
  625. break;
  626. case 0x72:
  627. K = 32; Level = 1; Way = 8; Line = 64; IorD = "I";
  628. break;
  629. case 0x80:
  630. s = "No L2 Cache";
  631. break;
  632. default:
  633. s = "Unknown Descriptor";
  634. }
  635. if (s) {
  636. printf(" %02xH %s.\n", Descriptor, s);
  637. continue;
  638. }
  639. }
  640. printf(" %02xH L%d %sCache %dKB, %d way, %dB line\n",
  641. Descriptor,
  642. Level,
  643. IorD,
  644. K,
  645. Way,
  646. Line);
  647. } // while more bytes in this register
  648. } // for each register
  649. //
  650. // If more iterations,...
  651. //
  652. if (--Temp == 0) {
  653. break;
  654. }
  655. ExecuteCpuidFunction(2, Results);
  656. printf(" F %d raw = %08x %08x %08x %08x\n",
  657. 2,
  658. Results[0],
  659. Results[1],
  660. Results[2],
  661. Results[3]);
  662. } while (TRUE);
  663. break;
  664. }
  665. }
  666. //
  667. // Examine extended functions.
  668. //
  669. ExecuteCpuidFunction(0x80000000, Results);
  670. MaxFunction = Results[0];
  671. //
  672. // Ok, function numbers > MaxFunction (the basic one) by
  673. // definition return undefined results. But, we are told
  674. // that if extended functions are not supported, the return
  675. // value for 0x80000000 will never have the top bit set.
  676. //
  677. if ((MaxFunction & 0x80000000) == 0) {
  678. printf(" This processor does not support Extended CPUID functions.\n");
  679. continue;
  680. }
  681. printf(" Maximum Supported Extended Function 0x%x.\n",
  682. MaxFunction);
  683. for (Function = 0x80000000; Function <= MaxFunction; Function++) {
  684. ExecuteCpuidFunction(Function, Results);
  685. printf(" F 0x%08x raw = %08x %08x %08x %08x\n",
  686. Function,
  687. Results[0],
  688. Results[1],
  689. Results[2],
  690. Results[3]);
  691. switch (Function) {
  692. case 0x80000000:
  693. break;
  694. case 0x80000001:
  695. if (Vendor == CPU_AMD) {
  696. //
  697. // EAX = Generation, Model, Stepping.
  698. // EBX = Reserved
  699. // ECX = Reserved
  700. // EDX = Feature Bits
  701. //
  702. //
  703. // Generation Model Stepping
  704. //
  705. Temp = Results[0];
  706. Generation = (Temp >> 8) & 0xf;
  707. Model = (Temp >> 4) & 0xf;
  708. Stepping = Temp & 0xf;
  709. printf(" Generation = %d, Model = %d, Stepping = %d\n",
  710. Generation, Model, Stepping);
  711. //
  712. // Feature bits.
  713. //
  714. PrintFeatures( Results[3], AMDExtendedFeatureBitDescription );
  715. }
  716. break;
  717. case 0x80000002:
  718. Temp2 = 1;
  719. case 0x80000003:
  720. Temp2++;
  721. case 0x80000004:
  722. Temp2++;
  723. printf(" Processor Name[%2d-%2d] = '%s'\n",
  724. 49 - (Temp2 * 16),
  725. 64 - (Temp2 * 16),
  726. Results);
  727. Temp2 = 0;
  728. break;
  729. case 0x80000005:
  730. if (Vendor == CPU_AMD) {
  731. if (Family == 6) {
  732. //
  733. // Athlon.
  734. //
  735. printf(" Large Page TLBs :");
  736. AMD_DI_TLB(1, Results[0]);
  737. } else if (Family > 6) {
  738. printf(" Family %d is a new AMD family which this program doesn't know about.\n");
  739. break;
  740. }
  741. //
  742. // Common to K5, K6 and Athlon
  743. //
  744. printf(" 4KB Page TLBs :");
  745. AMD_DI_TLB(1, Results[1]);
  746. printf(" L1 D-Cache :");
  747. AMD_Cache(1, Results[2]);
  748. printf(" L1 I-Cache :");
  749. AMD_Cache(1, Results[3]);
  750. }
  751. break;
  752. case 0x80000006:
  753. if (Vendor == CPU_AMD) {
  754. if (Family == 6) {
  755. //
  756. // Athlon.
  757. //
  758. if (Results[0]) {
  759. printf(" Large Page L2 TLB :");
  760. AMD_DI_TLB(2, Results[0]);
  761. }
  762. if (Results[1]) {
  763. printf(" 4KB Page L2 TLB :");
  764. AMD_DI_TLB(2, Results[1]);
  765. }
  766. if ((Model == 3) && (Stepping == 0)) {
  767. Results[2] &= 0xffff;
  768. Results[2] |= 0x400000;
  769. }
  770. } else if (Family > 6) {
  771. break;
  772. }
  773. //
  774. // Common to K5, K6 and Athlon
  775. //
  776. printf(" L2 Cache :");
  777. AMD_Cache(2, Results[2]);
  778. }
  779. break;
  780. }
  781. }
  782. #endif
  783. #if defined(_IA64_)
  784. printf("++ Processor %d\n", Processor);
  785. //
  786. // On IA64, cpuid is implemented as a set of 64 bit registers.
  787. // Registers
  788. // 0 and 1 contain the Vendor Information.
  789. // 2 contains 0.
  790. // 3 most significant 24 bits are reserved, the low 5 bytes
  791. // contain-
  792. // 39-32 archrev
  793. // 31-24 family
  794. // 23-16 model
  795. // 15-08 revision
  796. // 07-00 number index of largest implemented register
  797. // 4 features
  798. //
  799. //
  800. // Until we have read register 3, set 3 as the maximum number.
  801. //
  802. MaxFunction = 3;
  803. for (Function = 0; Function <= MaxFunction; Function++) {
  804. Result = ia64CPUID(Function);
  805. printf(" F %d raw = %016I64x\n",
  806. Function,
  807. Result);
  808. //
  809. // Do some interpretation on the ones we know how to
  810. // deal with.
  811. //
  812. switch(Function) {
  813. case 0:
  814. VendorInformation[0] = Result;
  815. break;
  816. case 1:
  817. VendorInformation[1] = Result;
  818. VendorInformation[2] = 0;
  819. printf(" \"%s\"\n", (PUCHAR)VendorInformation);
  820. break;
  821. case 3:
  822. printf(" Architecture Revision = %d, Family = %d, Model = %d, Revision = %d\n",
  823. (Result >> 32) & 0xff,
  824. (Result >> 24) & 0xff,
  825. (Result >> 16) & 0xff,
  826. (Result >> 8) & 0xff);
  827. MaxFunction = (ULONG)Result & 0xff;
  828. printf(" Maximum Supported Function %d.\n",
  829. MaxFunction);
  830. break;
  831. case 4:
  832. PrintFeatures( Result, IA64FeatureBitDescription );
  833. break;
  834. }
  835. }
  836. #endif
  837. }
  838. return 0;
  839. }