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

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