1 /* Intel and AMD x86 CPUID display program v 3.3 (1 Jan 2002)
2 * Copyright 2002 Phil Karn, KA9Q
3 * Updated 24 Apr 2001 to latest Intel CPUID spec
4 * Updated 22 Dec 2001 to decode Intel flag 28, hyper threading
5 * Updated 1 Jan 2002 to cover AMD Duron, Athlon
6 * May be used under the terms of the GNU Public License (GPL)
9 * ftp://download.intel.com/design/pro/applnots/24161809.pdf (AP-485)
10 * http://developer.intel.com/design/Pentium4/manuals/24547103.pdf
11 * http://developer.intel.com/design/pentiumiii/applnots/24512501.pdf (AP-909)
12 * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/20734.pdf
18 void decode_intel_tlb(int);
19 void decode_cyrix_tlb(int);
20 void dointel(int),doamd(int),docyrix(int);
21 void printregs(int eax
,int ebx
,int ecx
,int edx
);
24 char *Brands
[MAXBRANDS
] = {
27 "Pentium III processor",
28 "Intel Pentium III Xeon processor",
33 "Intel Pentium 4 processor",
36 #define cpuid(in,a,b,c,d)\
37 asm("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (in));
41 unsigned long li
,maxi
,maxei
,ebx
,ecx
,edx
,unused
;
43 /* Insert code here to test if CPUID instruction is available */
45 /* Dump all the CPUID results in raw hex */
46 cpuid(0,maxi
,unused
,unused
,unused
);
47 maxi
&= 0xffff; /* The high-order word is non-zero on some Cyrix CPUs */
48 printf(" eax in eax ebx ecx edx\n");
50 unsigned long eax
,ebx
,ecx
,edx
;
52 cpuid(i
,eax
,ebx
,ecx
,edx
);
53 printf("%08x %08lx %08lx %08lx %08lx\n",i
,eax
,ebx
,ecx
,edx
);
55 cpuid(0x80000000,maxei
,unused
,unused
,unused
);
56 for(li
=0x80000000;li
<=maxei
;li
++){
57 unsigned long eax
,ebx
,ecx
,edx
;
59 cpuid(li
,eax
,ebx
,ecx
,edx
);
60 printf("%08lx %08lx %08lx %08lx %08lx\n",li
,eax
,ebx
,ecx
,edx
);
64 /* Vendor ID and max CPUID level supported */
65 cpuid(0,unused
,ebx
,ecx
,edx
);
66 printf("Vendor ID: \"");
68 putchar(ebx
>> (8*i
));
70 putchar(edx
>> (8*i
));
72 putchar(ecx
>> (8*i
));
73 printf("\"; CPUID level %ld\n\n",maxi
);
76 case 0x756e6547: /* Intel */
79 case 0x68747541: /* AMD */
82 case 0x69727943: /* Cyrix */
86 printf("Unknown vendor\n");
92 char *Intel_feature_flags
[] = {
93 "FPU Floating Point Unit",
94 "VME Virtual 8086 Mode Enhancements",
95 "DE Debugging Extensions",
96 "PSE Page Size Extensions",
97 "TSC Time Stamp Counter",
98 "MSR Model Specific Registers",
99 "PAE Physical Address Extension",
100 "MCE Machine Check Exception",
101 "CX8 COMPXCHG8B Instruction",
102 "APIC On-chip Advanced Programmable Interrupt Controller present and enabled",
104 "SEP Fast System Call",
105 "MTRR Memory Type Range Registers",
106 "PGE PTE Global Flag",
107 "MCA Machine Check Architecture",
108 "CMOV Conditional Move and Compare Instructions",
109 "FGPAT Page Attribute Table",
110 "PSE-36 36-bit Page Size Extension",
111 "PN Processor Serial Number present and enabled",
112 "CLFSH CFLUSH instruction",
115 "ACPI Thermal Monitor and Clock Ctrl",
116 "MMX MMX instruction set",
117 "FXSR Fast FP/MMX Streaming SIMD Extensions save/restore",
118 "SSE Streaming SIMD Extensions instruction set",
119 "SSE2 SSE2 extensions",
121 "HT Hyper Threading",
122 "TM Thermal monitor",
127 /* Intel-specific information */
128 void dointel(int maxi
){
129 printf("Intel-specific functions:\n");
132 /* Family/model/type etc */
133 int clf
,apic_id
,feature_flags
;
134 int extended_model
= -1,extended_family
= -1;
135 unsigned long eax
,ebx
,edx
,unused
;
136 int stepping
,model
,family
,type
,reserved
,brand
,siblings
;
139 cpuid(1,eax
,ebx
,unused
,edx
);
140 printf("Version %08lx:\n",eax
);
141 stepping
= eax
& 0xf;
142 model
= (eax
>> 4) & 0xf;
143 family
= (eax
>> 8) & 0xf;
144 type
= (eax
>> 12) & 0x3;
145 reserved
= eax
>> 14;
146 clf
= (ebx
>> 8) & 0xff;
147 apic_id
= (ebx
>> 24) & 0xff;
148 siblings
= (ebx
>> 16) & 0xff;
151 printf("Type %d - ",type
);
154 printf("Original OEM");
160 printf("Dual-capable");
168 printf("Family %d - ",family
);
180 printf("Pentium Pro");
187 extended_family
= (eax
>> 20) & 0xff;
188 printf("Extended family %d\n",extended_family
);
190 printf("Model %d - ",model
);
213 printf("write-back enhanced DX2");
229 printf("for 486 system");
239 printf("Pentium Pro");
242 printf("Pentium II Model 3");
245 printf("Pentium II Model 5/Xeon/Celeron");
251 printf("Pentium III/Pentium III Xeon - external L2 cache");
254 printf("Pentium III/Pentium III Xeon - internal L2 cache");
263 extended_model
= (eax
>> 16) & 0xf;
264 printf("Extended model %d\n",extended_model
);
266 printf("Stepping %d\n",stepping
);
268 printf("Reserved %d\n\n",reserved
);
272 printf("Brand index: %d [",brand
);
273 if(brand
< MAXBRANDS
){
274 printf("%s]\n",Brands
[brand
]);
276 printf("not in table]\n");
279 cpuid(0x80000000,eax
,ebx
,unused
,edx
);
280 if(eax
& 0x80000000){
281 /* Extended feature/signature bits supported */
283 if(maxe
>= 0x80000004){
286 printf("Extended brand string: \"");
287 for(i
=0x80000002;i
<=0x80000004;i
++){
288 unsigned long eax
,ebx
,ecx
,edx
;
290 cpuid(i
,eax
,ebx
,ecx
,edx
);
291 printregs(eax
,ebx
,ecx
,edx
);
297 printf("CLFLUSH instruction cache line size: %d\n",clf
);
300 printf("Initial APIC ID: %d\n",apic_id
);
302 if(feature_flags
& (1<<28)){
303 printf("Hyper threading siblings: %d\n",siblings
);
306 printf("\nFeature flags %08x:\n",feature_flags
);
308 if(feature_flags
& (1<<i
)){
309 printf("%s\n",Intel_feature_flags
[i
]);
315 /* Decode TLB and cache info */
319 printf("TLB and cache info:\n");
321 unsigned long eax
,ebx
,ecx
,edx
;
323 cpuid(2,eax
,ebx
,ecx
,edx
);
325 decode_intel_tlb(eax
>> 8);
326 decode_intel_tlb(eax
>> 16);
327 decode_intel_tlb(eax
>> 24);
329 if((ebx
& 0x80000000) == 0){
330 decode_intel_tlb(ebx
);
331 decode_intel_tlb(ebx
>> 8);
332 decode_intel_tlb(ebx
>> 16);
333 decode_intel_tlb(ebx
>> 24);
335 if((ecx
& 0x80000000) == 0){
336 decode_intel_tlb(ecx
);
337 decode_intel_tlb(ecx
>> 8);
338 decode_intel_tlb(ecx
>> 16);
339 decode_intel_tlb(ecx
>> 24);
341 if((edx
& 0x80000000) == 0){
342 decode_intel_tlb(edx
);
343 decode_intel_tlb(edx
>> 8);
344 decode_intel_tlb(edx
>> 16);
345 decode_intel_tlb(edx
>> 24);
350 /* Pentium III CPU serial number */
351 unsigned long signature
,unused
,ecx
,edx
;
353 cpuid(1,signature
,unused
,unused
,unused
);
354 cpuid(3,unused
,unused
,ecx
,edx
);
355 printf("Processor serial: ");
356 printf("%04lX",signature
>> 16);
357 printf("-%04lX",signature
& 0xffff);
358 printf("-%04lX",edx
>> 16);
359 printf("-%04lX",edx
& 0xffff);
360 printf("-%04lX",ecx
>> 16);
361 printf("-%04lX\n",ecx
& 0xffff);
364 void printregs(int eax
,int ebx
,int ecx
,int edx
){
370 string
[j
] = eax
>> (8*j
);
371 string
[j
+4] = ebx
>> (8*j
);
372 string
[j
+8] = ecx
>> (8*j
);
373 string
[j
+12] = edx
>> (8*j
);
379 /* Decode Intel TLB and cache info descriptors */
380 void decode_intel_tlb(int x
){
388 printf("Instruction TLB: 4KB pages, 4-way set assoc, 32 entries\n");
391 printf("Instruction TLB: 4MB pages, 4-way set assoc, 2 entries\n");
394 printf("Data TLB: 4KB pages, 4-way set assoc, 64 entries\n");
397 printf("Data TLB: 4MB pages, 4-way set assoc, 8 entries\n");
400 printf("1st-level instruction cache: 8KB, 4-way set assoc, 32 byte line size\n");
403 printf("1st-level instruction cache: 16KB, 4-way set assoc, 32 byte line size\n");
406 printf("1st-level data cache: 8KB, 2-way set assoc, 32 byte line size\n");
409 printf("1st-level data cache: 16KB, 4-way set assoc, 32 byte line size\n");
412 printf("No 2nd-level cache, or if 2nd-level cache exists, no 3rd-level cache\n");
415 printf("2nd-level cache: 128KB, 4-way set assoc, 32 byte line size\n");
418 printf("2nd-level cache: 256KB, 4-way set assoc, 32 byte line size\n");
421 printf("2nd-level cache: 512KB, 4-way set assoc, 32 byte line size\n");
424 printf("2nd-level cache: 1MB, 4-way set assoc, 32 byte line size\n");
427 printf("2nd-level cache: 2MB, 4-way set assoc, 32 byte line size\n");
430 printf("Instruction TLB: 4KB and 2MB or 4MB pages, 64 entries\n");
433 printf("Instruction TLB: 4KB and 2MB or 4MB pages, 128 entries\n");
436 printf("Instruction TLB: 4KB and 2MB or 4MB pages, 256 entries\n");
439 printf("Data TLB: 4KB and 4MB pages, 64 entries\n");
442 printf("Data TLB: 4KB and 4MB pages, 128 entries\n");
445 printf("Data TLB: 4KB and 4MB pages, 256 entries\n");
448 printf("1st-level data cache: 8KB, 4-way set assoc, 64 byte line size\n");
451 printf("1st-level data cache: 16KB, 4-way set assoc, 64 byte line size\n");
454 printf("1st-level data cache: 32KB, 4-way set assoc, 64 byte line size\n");
457 printf("Trace cache: 12K-micro-op, 4-way set assoc\n");
460 printf("Trace cache: 16K-micro-op, 4-way set assoc\n");
463 printf("Trace cache: 32K-micro-op, 4-way set assoc\n");
466 printf("2nd-level cache: 128KB, 8-way set assoc, sectored, 64 byte line size\n");
469 printf("2nd-level cache: 256KB, 8-way set assoc, sectored, 64 byte line size\n");
472 printf("2nd-level cache: 512KB, 8-way set assoc, sectored, 64 byte line size\n");
475 printf("2nd-level cache: 1MB, 8-way set assoc, sectored, 64 byte line size\n");
478 printf("2nd-level cache: 256KB, 8-way set assoc, 32 byte line size\n");
481 printf("2nd-level cache: 512KB, 8-way set assoc 32 byte line size\n");
484 printf("2nd-level cache: 1MB, 8-way set assoc, 32 byte line size\n");
487 printf("2nd-level cache: 2MB, 8-way set assoc, 32 byte line size\n");
490 printf("unknown TLB/cache descriptor\n");
494 char *AMD_feature_flags
[] = {
495 "Floating Point Unit",
496 "Virtual Mode Extensions",
497 "Debugging Extensions",
498 "Page Size Extensions",
499 "Time Stamp Counter (with RDTSC and CR4 disable bit)",
500 "Model Specific Registers with RDMSR & WRMSR",
501 "PAE - Page Address Extensions",
502 "Machine Check Exception",
503 "COMPXCHG8B Instruction",
506 "SYSCALL/SYSRET or SYSENTER/SYSEXIT instructions",
507 "MTRR - Memory Type Range Registers",
508 "Global paging extension",
509 "Machine Check Architecture",
510 "Conditional Move Instruction",
511 "PAT - Page Attribute Table",
512 "PSE-36 - Page Size Extensions",
517 "AMD MMX Instruction Extensions",
525 "3DNow! Instruction Extensions",
526 "3DNow instructions",
550 /* AMD-specific information */
551 void doamd(int maxi
){
552 unsigned long maxei
,unused
;
555 printf("AMD-specific functions\n");
557 /* Do standard stuff */
559 unsigned long eax
,ebx
,edx
,unused
;
560 int stepping
,model
,reserved
;
562 cpuid(1,eax
,ebx
,unused
,edx
);
563 stepping
= eax
& 0xf;
564 model
= (eax
>> 4) & 0xf;
565 family
= (eax
>> 8) & 0xf;
566 reserved
= eax
>> 12;
568 printf("Version %08lx:\n",eax
);
569 printf("Family: %d Model: %d [",family
,model
);
572 printf("486 model %d",model
);
582 printf("K6 Model %d",model
);
585 printf("K6-2 Model 8");
588 printf("K6-III Model 9");
591 printf("K5/K6 model %d",model
);
600 printf("Athlon model %d",model
);
603 printf("Duron model 3");
606 printf("Athlon MP/Mobile Athlon model 6");
609 printf("Mobile Duron Model 7");
612 printf("Duron/Athlon model %d",model
);
622 printf("Standard feature flags %08lx:\n",edx
);
624 if(family
== 5 && model
== 0){
626 printf("Global Paging Extensions\n");
628 printf("13 - reserved\n");
631 printf("%s\n",AMD_feature_flags
[i
]);
637 /* Check for presence of extended info */
638 cpuid(0x80000000,maxei
,unused
,unused
,unused
);
642 if(maxei
>= 0x80000001){
643 unsigned long eax
,ebx
,ecx
,edx
;
644 int stepping
,model
,generation
,reserved
;
647 cpuid(0x80000001,eax
,ebx
,ecx
,edx
);
648 stepping
= eax
& 0xf;
649 model
= (eax
>> 4) & 0xf;
650 generation
= (eax
>> 8) & 0xf;
651 reserved
= eax
>> 12;
653 printf("Generation: %d Model: %d\n",generation
,model
);
654 printf("Extended feature flags %08lx:\n",edx
);
656 if(family
== 5 && model
== 0 && i
== 9){
657 printf("Global Paging Extensions\n");
660 printf("%s\n",AMD_feature_flags
[i
]);
666 if(maxei
>= 0x80000002){
667 /* Processor identification string */
669 printf("Processor name string: ");
670 for(j
=0x80000002;j
<=0x80000004;j
++){
671 unsigned long eax
,ebx
,ecx
,edx
;
673 cpuid(j
,eax
,ebx
,ecx
,edx
);
674 printregs(eax
,ebx
,ecx
,edx
);
678 if(maxei
>= 0x80000005){
679 /* TLB and cache info */
680 unsigned long eax
,ebx
,ecx
,edx
;
682 cpuid(0x80000005,eax
,ebx
,ecx
,edx
);
683 printf("L1 Cache Information:\n");
685 printf("2/4-MB Pages:\n");
686 printf(" Data TLB: associativity %ld-way #entries %ld\n",
687 (eax
>> 24) & 0xff,(eax
>> 16) & 0xff);
688 printf(" Instruction TLB: associativity %ld-way #entries %ld\n",
689 (eax
>> 8) & 0xff,eax
& 0xff);
691 printf("4-KB Pages:\n");
692 printf(" Data TLB: associativity %ld-way #entries %ld\n",
693 (ebx
>> 24) & 0xff,(ebx
>> 16) & 0xff);
694 printf(" Instruction TLB: associativity %ld-way #entries %ld\n",
695 (ebx
>> 8) & 0xff,ebx
& 0xff);
697 printf("L1 Data cache:\n");
698 printf(" size %ld KB associativity %lx-way lines per tag %ld line size %ld\n",
699 ecx
>> 24,(ecx
>>16) & 0xff,(ecx
>> 8)&0xff,ecx
&0xff);
701 printf("L1 Instruction cache:\n");
702 printf(" size %ld KB associativity %lx-way lines per tag %ld line size %ld\n",
703 edx
>> 24,(edx
>>16) & 0xff,(edx
>> 8)&0xff,edx
&0xff);
707 /* check K6-III (and later?) on-chip L2 cache size */
708 if (maxei
>= 0x80000006) {
709 unsigned long eax
,ebx
,ecx
,unused
;
712 cpuid(0x80000006,eax
,ebx
,ecx
,unused
);
713 printf("L2 Cache Information:\n");
715 printf("2/4-MB Pages:\n");
716 assoc
= (eax
>> 24) & 0xff;
719 printf(" Data TLB: associativity %s #entries %ld\n",
720 Assoc
[(eax
>> 24) & 0xf],(eax
>> 16) & 0xff);
721 assoc
= (eax
>> 16) & 0xff;
722 printf(" Instruction TLB: associativity %s #entries %ld\n",
723 Assoc
[(eax
>> 8) & 0xf],eax
& 0xff);
725 printf("4-KB Pages:\n");
726 printf(" Data TLB: associativity %s #entries %ld\n",
727 Assoc
[(ebx
>> 24) & 0xf],(ebx
>> 16) & 0xff);
728 printf(" Instruction TLB: associativity %s #entries %ld\n",
729 Assoc
[(ebx
>> 8) & 0xf],ebx
& 0xff);
731 printf(" size %ld KB associativity %s lines per tag %ld line size %ld\n",
732 ecx
>> 24,Assoc
[(ecx
>>16) & 0xf],(ecx
>> 8)&0xff,ecx
&0xff);
736 /* Check power management feature flags */
737 if(maxei
>= 0x80000007){
738 unsigned long unused
,edx
;
740 printf("Advanced Power Management Feature Flags\n");
741 cpuid(0x80000007,unused
,unused
,unused
,edx
);
743 printf("Has temperature sensing diode\n");
745 printf("Supports Frequency ID control\n");
747 printf("Supports Voltage ID control\n");
749 /* Check phys address & linear address size */
750 if(maxei
>= 0x80000008){
751 unsigned long unused
,eax
;
753 cpuid(0x80000008,eax
,unused
,unused
,unused
);
754 printf("Maximum linear address: %ld; maximum phys address %ld\n",
755 (eax
>>8) & 0xff,eax
&0xff);
759 char *Cyrix_standard_feature_flags_5
[] = {
760 "FPU Floating Point Unit",
761 "V86 Virtual Mode Extensions",
764 "Time Stamp Counter",
765 "RDMSR/WRMSR (Model Specific Registers)",
767 "Machine Check Exception",
768 "COMPXCHG8B Instruction",
769 "APIC - On-chip Advanced Programmable Interrupt Controller present and enabled",
772 "MTRR Memory Type Range Registers",
775 "CMOV Conditional Move Instruction",
793 char *Cyrix_standard_feature_flags_not5
[] = {
794 "FPU Floating Point Unit",
795 "V86 Virtual Mode Extensions",
798 "Time Stamp Counter",
799 "RDMSR/WRMSR (Model Specific Registers)",
801 "Machine Check Exception",
802 "COMPXCHG8B Instruction",
803 "APIC - On-chip Advanced Programmable Interrupt Controller present and enabled",
806 "MTRR Memory Type Range Registers",
807 "Global Paging Extension",
809 "CMOV Conditional Move Instruction",
828 char *Cyrix_extended_feature_flags
[] = {
829 "FPU Floating Point Unit",
830 "V86 Virtual Mode Extensions",
832 "Page Size Extensions",
833 "Time Stamp Counter",
860 "3DNow instructions",
863 /* Cyrix-specific information */
864 void docyrix(int maxi
){
865 unsigned long maxei
,unused
;
868 printf("Cyrix-specific functions\n");
869 cpuid(0x80000000,maxei
,unused
,unused
,unused
);
870 /* Dump extended info, if any, in raw hex */
871 for(i
=0x80000000;i
<=maxei
;i
++){
872 unsigned long eax
,ebx
,ecx
,edx
;
874 cpuid(i
,eax
,ebx
,ecx
,edx
);
875 printf("eax in: 0x%x, eax = %08lx ebx = %08lx ecx = %08lx edx = %08lx\n",i
,eax
,ebx
,ecx
,edx
);
878 /* Do standard stuff */
880 unsigned long eax
,unused
,edx
;
881 int stepping
,model
,family
,reserved
;
883 cpuid(1,eax
,unused
,unused
,edx
);
884 stepping
= eax
& 0xf;
885 model
= (eax
>> 4) & 0xf;
886 family
= (eax
>> 8) & 0xf;
887 reserved
= eax
>> 12;
889 printf("Family: %d Model: %d [",family
,model
);
917 if(family
== 5 && model
== 0){
922 printf("%s\n",Cyrix_standard_feature_flags_5
[i
]);
930 printf("%s\n",Cyrix_standard_feature_flags_not5
[i
]);
936 /* TLB and L1 Cache info */
941 unsigned long eax
,edx
,unused
;
943 cpuid(2,eax
,unused
,unused
,edx
);
945 decode_cyrix_tlb(eax
>> 8);
946 decode_cyrix_tlb(eax
>> 16);
947 decode_cyrix_tlb(eax
>> 24);
949 /* ebx and ecx are reserved */
951 if((edx
& 0x80000000) == 0){
952 decode_cyrix_tlb(edx
);
953 decode_cyrix_tlb(edx
>> 8);
954 decode_cyrix_tlb(edx
>> 16);
955 decode_cyrix_tlb(edx
>> 24);
960 /* Check for presence of extended info */
961 if(maxei
< 0x80000000)
964 printf("\nExtended info:\n");
965 if(maxei
>= 0x80000001){
966 unsigned long eax
,ebx
,ecx
,edx
;
967 int stepping
,model
,family
,reserved
,i
;
969 cpuid(0x80000001,eax
,ebx
,ecx
,edx
);
970 stepping
= eax
& 0xf;
971 model
= (eax
>> 4) & 0xf;
972 family
= (eax
>> 8) & 0xf;
973 reserved
= eax
>> 12;
974 printf("Family: %d Model: %d [",family
,model
);
987 printf("Extended feature flags:\n");
990 printf("%s\n",Cyrix_extended_feature_flags
[i
]);
995 if(maxei
>= 0x80000002){
996 /* Processor identification string */
997 char namestring
[49],*cp
;
1000 printf("Processor name string: ");
1001 for(j
=0x80000002;j
<=0x80000004;j
++){
1002 unsigned long eax
,ebx
,ecx
,edx
;
1004 cpuid(j
,eax
,ebx
,ecx
,edx
);
1005 printregs(eax
,ebx
,ecx
,edx
);
1008 if(maxei
>= 0x80000005){
1009 /* TLB and L1 Cache info */
1013 for(i
=0;i
<ntlb
;i
++){
1014 unsigned long eax
,ebx
,ecx
,unused
;
1016 cpuid(0x80000005,eax
,ebx
,ecx
,unused
);
1018 decode_cyrix_tlb(ebx
>> 8);
1019 decode_cyrix_tlb(ebx
>> 16);
1020 decode_cyrix_tlb(ebx
>> 24);
1022 /* eax and edx are reserved */
1024 if((ecx
& 0x80000000) == 0){
1025 decode_cyrix_tlb(ecx
);
1026 decode_cyrix_tlb(ecx
>> 8);
1027 decode_cyrix_tlb(ecx
>> 16);
1028 decode_cyrix_tlb(ecx
>> 24);
1035 /* Decode Cyrix TLB and cache info descriptors */
1036 void decode_cyrix_tlb(int x
){
1041 printf("TLB: 32 entries 4-way associative 4KB pages\n");
1044 printf("L1 Cache: 16KB 4-way associative 16 bytes/line\n");