3 * author : albcamus <albcamus@gmail.com>
4 * usage : gcc -m32 cpuid.c -o cpuid
6 * description : a silly program to get the information of your x86 CPU.
7 * This program is licensed under GPLv2. No warrant.
8 * revision : 0.1.1 - Fix bugs about changing eflags
10 * TODO : supporting for AMD/VIA-Cyrix/Transmeta CPUs
26 void print_cache_descriptor(unsigned char);
30 unsigned int eflags1
, eflags2
= 0;
31 unsigned int eax
, ebx
, ecx
, edx
;
32 unsigned int serial_num
= 0;
34 eax
= ebx
= ecx
= edx
= 0;
38 * eflags寄存器的第21位,如果程序可以清除/设置它,则说明CPU支持CPUID指令。否则不支持
42 asm volatile ("pushf\n\t"
48 printf("original eflags is\t\t: 0x%08x\n", eflags1
);
53 /* 把eflags的第21位取反,写回寄存器中 */
54 asm volatile ("pushl %0\n\t"
57 : "g"(eflags1
^ 0x00200000)
60 /* 检查一下现在的eflags,确认第21位和最初的值相反 */
61 asm volatile ("pushf\n\t"
67 printf("modified eflags is\t\t: 0x%08x\n", eflags2
);
69 /* 如果eflags的值没有发生改变,则说明CPU不支持cpuid指令,程序退出 */
70 if (eflags1
== eflags2
) {
71 printf("Sorry, Your CPU dosen't support CPUID instruction.\n");
76 asm volatile ("pushl %0\n\t"
82 * FIXME: Intel文档并没有说,如果不支持CPUID的话,clear/set eflags的第21位会有什么错误。
83 * 它只说,在不支持CPUID指令的CPU上,如80386,执行CPUID会产生invalid opcode错误
85 * ──我猜测,如果CPUID不被支持,只是程序无法clear/set EFLAGS[21]而已.
86 * 所以,在这里我们不处理 读/写 eflags 第21比特失败的情形
92 * eax : cpuid指令允许的最大eax输入值
98 : "=a"(eax
), "=b"(ebx
), "=c"(ecx
), "=d"(edx
)
101 printf("Maximum CPUID Input EAX\t\t: 0x%08x\n", eax
);
104 snprintf(string
, 5, "%s", (char *)&ebx
);
105 snprintf(string
+ 4, 5, "%s", (char *)&edx
);
106 snprintf(string
+ 8, 5, "%s", (char *)&ecx
);
107 printf("Vendor\t\t\t\t: %s\n", string
);
109 if (strcmp(string
, "GenuineIntel") == 0)
110 x86_vendor
= X86_VENDOR_INTEL
;
111 else if (strstr(string
, "AuthenticAMD") == 0 )
112 x86_vendor
= X86_VENDOR_AMD
;
113 else if (strstr(string
, "CyrixInstead") == 0 )
114 x86_vendor
= X86_VENDOR_CYRIX
;
115 else if ( (strcmp(string
, "GenuineTMx86") == 0) || (strcmp(string
, "TransmetaCPU") == 0) )
116 x86_vendor
= X86_VENDOR_TRANSMETA
;
118 x86_vendor
= X86_VENDOR_UNKNOWN
;
128 * eax == 1,则在eax中返回Family/Model/Stepping等信息
130 * ECX和EDX返回一些features信息
135 * EAX[12:13] processor type
136 * EAX[16:19] extended model ID
137 * EAX[20:27] extended family ID
139 * EBX[0:7] Brand index
140 * EBX[8:15] CLFLUSH. 执行clflush时作用的I-Cache line size,Pentium4引入
141 * EBX[24:31] Local APIC ID,也是Pentium4引入
142 * //FIXME: Core2的x2APIC的APIC ID已经扩展到32bit,怎么处理?
143 * //FIX: 回答:见下面ECX[21]bit的描述
146 * ECX[3] MONITOR/MWAIT
147 * ECX[4] CPL Qualified Debug Store
149 * ECX[7] EST, Enhanced SpeedStep Technology
150 * ECX[8] TM2, Thermal Monitor2
151 * ECX[9] SSSE3, Supplemental SSE3
152 * ECX[10] CNXT-ID, L1 Context ID. 如果为1,则说明L1 D-Cache可以设置为 自适应(adaptive)模式
153 * 或shared模式. 为0则说明不支持。
154 * ECX[13] CMPXCHG16B. 如果为1则说明支持该指令。
155 * ECX[14] xTPR Update Control. 为1则说明支持改变MSR寄存器IA32_MISC_ENABLES[23]的值
156 * ECX[16] PDCM, Perfmon and Debug Capability,1说明支持MSR寄存器IA32_PERF_CAPABILITIES
157 * ECX[21] x2APIC. 并且,如果该bit为1,则需要使eax==0xb && ecx==0,执行cpuid,如果ebx!=0,则CPU
158 * 支持extended topology enumeration leaf
161 * EDX[1] VME, 用CR4的VME控制
162 * EDX[2] DE, Debugging Extensions, 用CR4的DE控制
163 * EDX[3] PSE, Page Size Extensions, 用CR4的PSE控制
164 * EDX[4] TSC, 是否支持rdtsc和wrtsc指令。用CR4.TSD控制RING3是否可以访问TSC
165 * EDX[5] MSR,是否支持rdmsr和wrmsrl指令
166 * EDX[6] PAE, Physical Address Extionsion.
167 * EDX[7] MCE, Machine Check Exception. 由CR4.MCE控制MCE特性
168 * EDX[8] CX8, CMPXCHG8B指令
169 * EDX[9] APIC On-Chip. CPU是否有APIC,内存映射默认在物理地址范围0xfffe0000~0xfffe0fff,
170 * 有些CPU允许APIC被relocate
171 * EDX[11] SEP. sysenter和sysexit指令,以及相关的MSR寄存器是否可用
172 * EDX[12] MTRR. MTRRcap MSR寄存器包含一些bits,描述了支持的variable和fixed MTRR
173 * EDX[13] PGE. PTE Global Bit. PDEs(page directory entries)和PTEs中的global bit是否支持.
174 * 如果为1,则那些对不同进程都一样的TLB entries在进程切换时不用冲刷。
176 * EDX[14] MCA, Machine Check Architecture. P6开始支持,MSR寄存器MCG_CAP包含其他多少个
178 * EDX[15] CMOV, Conditional Move Instructions. 看CMOV指令是否支持。 另外,如果CPUID.FPU
179 * 支持,则FCOMI和FCOMV指令支持。
180 * EDX[16] PAT. Page Attribute Table. 类似于MTRR,但PAT指定的是线性地址范围
181 * EDX[17] PSE-36, 36位的Page Size Extension. 物理地址36bit,其中高4bit用来指定一个4M页
183 * EDX[18] PSN. Serial Number是否支持。
184 * EDX[19] CLFLUSH指令是否支持
185 * EDX[21] DS, Debug Store. 如果支持DS,就是CPU把调试信息写到一块驻留内存的buffer(
186 * memory-resident buffer). 该特性可以被BTS(Branch Trace Store)和PEBS(Precis
187 * event-based sampling)使用。见手册'Debugging and Performance Monitoring'部分
188 * EDX[22] ACPI, Thermal Monitor and Software Controlled Clock Facilities. 如果为真,则
189 * CPU支持热量控制和由软件控制CPU主频等ACPI特性。
191 * EDX[24] FXSR, FXSAVE和FXRSTOR指令。 用来快速的保存/恢复 浮点上下文。 注意:即使该指令
192 * 可用,也要看CR4.OSFXSR的设置,根据后者的不同设置,FXSAVE/FXRSTOR所作用的寄存器
196 * EDX[27] SS, Self Snoop. CPU支持对cache snooping进行管理。
197 * EDX[28] HTT, Muti-Threading
198 * EDX[29] TM, Thermal Monitor. CPU实现了热量监控电路(TCC: thermal control circuitry)
199 * EDX[31] PBE, Pending Break Enable. 如果支持,那么CPU处于Stop状态时(STPCLK# is asserted),
200 * 可以通过FERR#/PBE#针脚告诉CPU有中断正pending,唤醒它到正常状态去处理中断 * * *
202 asm volatile ("cpuid"
203 : "=a"(eax
), "=b"(ebx
), "=c"(ecx
), "=d"(edx
)
210 printf("Extended Family\t\t\t: %d\n", (0xff00000 & eax
) >> 20);
211 printf("Extended Model\t\t\t: %d\n", (0xf0000 & eax
) >> 16);
212 printf("Processor type\t\t\t: ");
213 switch( (0x3000 & eax
) >> 12 )
216 printf("Original OEM Processor\n");
219 printf("Intel OverDrive Processor\n");
222 printf("Dual Processor\n");
225 printf("Intel Reserved\n");
230 printf("Family\t\t\t\t: %d\n", (0xf00 & eax
) >> 8);
231 printf("Model\t\t\t\t: %d\n", (0xf0 & eax
) >> 4);
232 printf("Stepping:\t\t\t: %d\n", (0xf & eax
));
237 printf("Brand Index\t\t\t: %d\n", (0xff & ebx
));
238 printf("I-Cache line size with CLFLUSH\t: %d\n", (0xff00 & ebx
) >> 8 );
240 /* 我在Core 2 Duo上执行,输出有时是0,有时是1, 说明前后被调度到了不同的core上 */
241 printf("Local APIC ID\t\t\t: %d\n", (0xff000000 & ebx
) >> 24 );
247 printf("Features: ");
249 printf("\t\t\tSSE2\n");
250 if ( ecx
& (1 << 3) )
251 printf("\t\t\t\tMONITOR/MWAIT\n");
252 if ( ecx
& (1 << 4) )
253 printf("\t\t\t\tCPL\n");
254 if ( ecx
& (1 << 5) )
255 printf("\t\t\t\tVMX\n");
256 if ( ecx
& (1 << 7) )
257 printf("\t\t\t\tEST\n");
258 if ( ecx
& (1 << 8) )
259 printf("\t\t\t\tTM2\n");
260 if ( ecx
& (1 << 9) )
261 printf("\t\t\t\tSSSE3\n");
262 if ( ecx
& (1 << 10) )
263 printf("\t\t\t\tCNXT\n");
264 if ( ecx
& (1 << 13) )
265 printf("\t\t\t\tCMPXCHG16B\n");
266 if ( ecx
& (1 << 14) )
267 printf("\t\t\t\txPTR\n");
268 if ( ecx
& (1 << 16) )
269 printf("\t\t\t\tPDCM\t");
274 printf("\t\t\t\tFPU\n");
275 if ( edx
& (1 << 1) )
276 printf("\t\t\t\tVME\n");
277 if ( edx
& (1 << 2) )
278 printf("\t\t\t\tDE\n");
279 if ( edx
& (1 << 3) )
280 printf("\t\t\t\tPSE\n");
281 if ( edx
& (1 << 4) )
282 printf("\t\t\t\tTSC\n");
283 if ( edx
& (1 << 5) )
284 printf("\t\t\t\tMSR\n");
285 if ( edx
& (1 << 6) )
286 printf("\t\t\t\tPAE\n");
287 if ( edx
& (1 << 7) )
288 printf("\t\t\t\tMCE\n");
289 if ( edx
& (1 << 8) )
290 printf("\t\t\t\tCMPXCHG8B\n");
291 if ( edx
& (1 << 9) )
292 printf("\t\t\t\tAPIC\n");
293 if ( edx
& (1 << 11) )
294 printf("\t\t\t\tSEP: sysenter/sysexit\n");
295 if ( edx
& (1 << 12) )
296 printf("\t\t\t\tMTRR\n");
297 if ( edx
& (1 << 13) )
298 printf("\t\t\t\tPGE: PTE Global Bit\n");
299 if ( edx
& (1 << 14) )
300 printf("\t\t\t\tMCA: Machine Check Architecture\n");
301 if ( edx
& (1 << 15) )
302 printf("\t\t\t\tCMOV: Conditional Move Instruction\n");
303 if ( edx
& (1 << 16) )
304 printf("\t\t\t\tPAT: Page Attribute Table\n");
305 if ( edx
& (1 << 17) )
306 printf("\t\t\t\tPSE-36\n");
307 if ( edx
& (1 << 18) ) {
308 printf("\t\t\tPSN: Processor Serial Number\n");
311 if ( edx
& (1 << 19) )
312 printf("\t\t\t\tCLFLUSH\n");
313 if ( edx
& (1 << 21) )
314 printf("\t\t\t\tDS: Debug Store\n");
315 if ( edx
& (1 << 22) )
316 printf("\t\t\t\tACPI\n");
317 if ( edx
& (1 << 23) )
318 printf("\t\t\t\tMMX\n");
319 if ( edx
& (1 << 24) )
320 printf("\t\t\t\tFXSR: FXSAVE and FXRSTOR\n");
321 if ( edx
& (1 << 25) )
322 printf("\t\t\t\tSSE\n");
323 if ( edx
& (1 << 26) )
324 printf("\t\t\t\tSSE2\n");
325 if ( edx
& (1 << 27) )
326 printf("\t\t\t\tSS: Self Snoop\n");
327 if ( edx
& (1 << 28) )
328 printf("\t\t\t\tHTT: Multi-Threading\n");
329 if ( edx
& (1 << 29) )
330 printf("\t\t\t\tTM: Thermal Monitor\n");
331 if ( edx
& (1 << 31) )
332 printf("\t\t\t\tPBE: Pending Break Enable\n");
339 * edx的第18比特为1,则CPU支持serial number
340 * 为0,则不支持,或者被disabled
341 * 序列号有96位,其中最高32位即是eax的输出值。应当把它保存下来,然后
345 /* serial number supported */
346 /* edx输出中间32位的序列号,ecx输出最低32位的序列号 */
347 asm volatile ("cpuid"
348 : "=c"(ecx
), "=d"(edx
)
351 printf("Serial Number\t : %x-%x-%x-%x-%x-%x\n", eax
>> 16, (eax
<< 16) >> 16,
352 edx
>> 16, (edx
<< 16) >> 16, ecx
>> 16, (ecx
<< 16) >> 16);
354 printf("Serial Number not supported.\n");
363 * eax == 2, Cache/TLB相关信息在EAX/EBX/ECX/EDX中返回。
365 * eax[0:7] : 一个数值,表示eax==2的CPUID指令需要执行几次才能完整获取Cache/TLB的信息
366 * : 例如如果al是2,则你还要执行一次CPUID指令(with eax==2)
368 * [eax|ebx|ecx|edx][31] : 每个寄存器的第31bit,代表了该寄存器是否包含合法的信息
371 * 如果某寄存器第31bit为0,则每个字节(对EAX来说,第一次执行eax==2的cpuid指令时,[0:7]这个
372 * 字节不算)都包含一个值,根据这个值到表(Intel Manuals, Volume 2A, Table 3-17)中查找它代表
375 * 该表内容见Intel手册2A,表3-17. 也可以在print_cache_descriptor()函数中找到。
378 unsigned int count
= 0;
379 static unsigned char desc
[4][4];
382 /** AMD的CPUID指令,其eax输入值0x0000 000[4:2] 为保留 */
383 if( x86_vendor
!= X86_VENDOR_AMD
) {/*{{{*/
385 asm volatile ("cpuid"
386 : "=a"(eax
), "=b"(ebx
), "=c"(ecx
), "=d"(edx
)
390 if (count
== 0 ) /* the first pass */
391 count
= (unsigned int)(eax
& 0xff);
393 if ( !(eax
>> 31) ) {
394 if ( count
== (unsigned int)(eax
& 0xff) )
397 desc
[0][0] = (unsigned char)eax
& 0xff;
398 desc
[0][1] = (eax
& 0xff00) >> 8;
399 desc
[0][2] = (eax
& 0xff0000) >> 16;
400 desc
[0][3] = (eax
& 0xff000000) >> 24;
403 if ( !(ebx
>> 31) ) {
404 desc
[1][0] = (ebx
& 0xff);
405 desc
[1][1] = (ebx
& 0xff00) >> 8;
406 desc
[1][2] = (ebx
& 0xff0000) >> 16;
407 desc
[1][3] = (ebx
& 0xff000000) >> 24;
410 if ( !(ecx
>> 31) ) {
411 desc
[2][0] = (ecx
& 0xff);
412 desc
[2][1] = (ecx
& 0xff00) >> 8;
413 desc
[2][2] = (ecx
& 0xff0000) >> 16;
414 desc
[2][3] = (ecx
& 0xff000000) >> 24;
417 if ( !(edx
>> 31) ) {
418 desc
[3][0] = (edx
& 0xff);
419 desc
[3][1] = (edx
& 0xff00) >> 8;
420 desc
[3][2] = (edx
& 0xff0000) >> 16;
421 desc
[3][3] = (edx
& 0xff000000) >> 24;
424 printf("Cache and TLB information:\n");
426 for (i
= 0; i
< 4; i
++)
427 for(j
= 0; j
< 4; j
++) {
428 print_cache_descriptor( (unsigned char)desc
[i
][j
] );
441 * Input : eax == 4 && ecx == <index>
442 * eax ==4时的cpuid指令输出取决于ecx的输入值。
443 * 返回:Deterministic Cache Parameters Leaf
445 * ecx中的值是index,可以从0开始,一直到cpuid返回的eax[0:4]值为0.
447 * EAX[0:4] : Cache Type,Type: 0 -- 没有更多level的Cache了
450 * 3 -- 统一Cache(不分指令/数据)
451 * EAX[5:7] : Cache Level
452 * EAX[8] : Self Initializing cache level(不需要软件初试化)
453 * EAX[9] : Fully Associative cache
454 * EAX[10] : Write-Back Invalidate和Invalidate的方式
455 * 0 : 多个线程共享Cache时,当其中一个执行WBINVD/INVD指令,
456 * CPU能保证作用到lower Level的Caches
457 * 1 : 共享Cache的多个线程,若一个线程不是WBINVD/INVD指令
458 * 的发起者,CPU不保证指令能作用到lower Level的Caches
459 * EAX[11] : Cache Inclusiveness
460 * 0 : Cache is not inclusive of lower cache levels
461 * 1 : Cache is inclusive of lower cache levels
462 * EAX[14:25] : 一个物理CPU package中,多少线程共享该Cache(需加1)
463 * EAX[26:31] : 一个物理CPU package中,共有多少Cores. (需加1)
465 * EBX[00:11] : L = System Coherency Line Size(需加1)
466 * EBX[12:21] : P = physical Line Partitions(需加1)
467 * EBX[22:31] : W = ways of associativity(需加1)
469 * ECX[00:31] : Number of Set,有多少组。(需加1)
472 * (eax[31:26] + 1) 是该物理处理器package上实现的core CPUs数目
476 /* AMD CPU的[2:4]输入值是保留了的 */
477 if ( x86_vendor
!= X86_VENDOR_AMD
) {/*{{{*/
479 printf("Deterministic Cache Parameters Leaf:\n");
483 asm volatile ("cpuid"
484 : "=a"(eax
), "=b"(ebx
), "=c"(ecx
)
493 printf("Index %d :\n", index
);
494 printf("\tCache Type: ");
495 switch( (eax
& 0x1f) ) {
497 printf("Null-No more Caches\n");
500 printf("Data Cache\n");
503 printf("Instruction Cache\n");
506 printf("Unified Cache\n");
509 ;/* wrong value. we'll keep silent with this */
512 printf("\tCache Level\t: %d\n", (eax
& 0xe0) >> 5);
513 printf("\tSelf Initializing cache level: %d\n", (eax
& 0x100) >> 8);
514 printf("\tFully Associative cache: %d\n", (eax
& 0x200) >> 9);
515 printf("\tWBINVD/INVD act upon lower shared cache? %s\n", (eax
& (1<<10))?"No":"Yes" );
516 printf("\tCache Inclusiveness: %s\n", (eax
& (1<<11))?"inclusive of lower cache levels":
517 "not inclusive of lower cache levels" );
518 printf("\tMaximum number of threads sharing this cache in a physical package: %d\n",
519 ((eax
&0x3ffc000) >> 14) + 1 );
520 printf("\tMaximum number of cores in the physical package: %d\n",
525 printf("\tSystem Coherency Line Size: %d\n", (ebx
& 0xfff) + 1 );
526 printf("\tPhysical Line partitions: %d\n", ((ebx
& 0x3ff000) >> 12) +1 );
527 printf("\t%d-Ways of associativity\n", (ebx
>> 22) + 1 );
531 printf("\tNumber of Sets: %d\n", ecx
+ 1);
549 * step 2: eax == 0xb && ecx == 0
550 * ebx != 0 如果ebx!=0,则CPU支持extended topology emumeration leaf。否则不支持
552 * 注意step1执行之后发现ecx[21]==1才进行step2。
554 unsigned int has_x2apic
= 0;
555 asm volatile ("cpuid"
559 if (ecx
& 0x00200000) {
560 printf("\t\t\t x2APIC\n");
571 printf("\t\t\t Extended topology enumeration leaf\n");
584 /* XXX: eax >= 0x80000000 的输入值,是CPUID指令的扩展功能. 下面的代码是这部分功能的探测 */
594 * 如果CPU支持Brand String,则在EAX中返 >= 0x80000004的值。
596 asm volatile ("cpuid"
600 printf("CPU support Brand String?\t: %s\n", eax
>= 0x80000004? "yes":"no");
604 * 如果支持Brand String,则EAX从0x80000002到0x80000004,每次增1,CPUID指令返回:
605 * EAX : Processor Brand String
606 * EBX : Processor Brand String Continued
607 * ECX : Processor Brand String Continued
608 * EDX : Processor Brand String Continued
611 if(eax
>= 0x80000004) {
612 printf("Brand String\t\t\t: ");
615 unsigned int brands[4]; //每次的eax、ebx、ecx、edx
618 for (i = 0x80000002; i <= 0x80000004; i++) {
619 asm volatile ("cpuid"
620 : "=a"(brands[0]), "=b"(brands[1]), "=c"(brands[2]), "=d"(brands[3])
623 printf("%s", (char *)brands);
627 unsigned int bs
[] = { [0 ... 12] = 0 };
629 : "=a"(bs
[0]), "=b"(bs
[1]), "=c"(bs
[2]), "=d"(bs
[3])
633 : "=a"(bs
[4]), "=b"(bs
[5]), "=c"(bs
[6]), "=d"(bs
[7])
637 : "=a"(bs
[8]), "=b"(bs
[9]), "=c"(bs
[10]), "=d"(bs
[11])
641 printf("%s\n", (char *)bs
);
652 * 如果CPU支持NX,如果edx的第20比特为1,则说明支持NX(Non-eXecute);否则不支持。
654 * eax : extended processor signature and extended feature bits
655 * ecx[0] : LAHF/SAHF 在64位模式下有效
656 * edx[11] : SYSCALL/SYSRET在64-bit下有效
658 * edx[29] : Intel 64技术(AKA EM64T)
660 asm volatile ("cpuid"
666 printf("\t\t\t\tLAHF/SAHF available when in 64-bit mode.\n");
669 printf("\t\t\t\tSYSCALL/SYSRET available when in 64-bit mode.\n");
670 if ( edx
& 0x100000 )
671 printf("\t\t\t\tNX: Execute Disable\n");
672 if ( edx
& 0x20000000 )
673 printf("\t\t\t\tIntel 64(AKA EM64T)\n");
684 * eax == 80000006h,返回L2 Cache的信息
686 * ecx[31:16] : L2 Cache size, in Kbytes
687 * ecx[15:12] : L2 Cache Associativity
694 * 0Fh Fully associative
695 * ecx[7:0] : L2 Cache Line size in bytes
697 asm volatile ("cpuid"
701 printf("L2 Cache Size\t\t\t: %d Kbytes\n", ( ecx
>> 16 ) );
702 printf("L2 Cache Line Size\t\t: %d bytes\n", (ecx
& 0xff));
704 printf("L2 Cache Associativity\t\t: ");
705 switch ( (ecx
& 0xf000) >> 12 )
708 printf("%s\n", "disabled");
711 printf("%s\n", "direct mapped");
714 printf("%s\n", "2-Way");
717 printf("%s\n", "4-Way");
720 printf("%s\n", "8-Way");
723 printf("%s\n", "16-Way");
726 printf("Fully associative");
729 printf("No such entry...\n");
740 * EAX[0:7] : 物理地址bits
741 * EAX[8:15] : 虚拟地址bits
743 asm volatile ("cpuid"
747 printf("Physical Address Bits\t\t: %d\n", (0xff & eax
));
748 printf("Virtual Address Bits\t\t: %d\n", (0xff00 & eax
) >> 8);
760 void print_cache_descriptor(unsigned char desc
)
767 printf("\t\t\t\t: Instruction TLB: 4 KByte pages, 4-way set associative, 32 entries\n");
770 printf("\t\t\t\t: Instruction TLB: 4 MByte pages, 4-way set associative, 2 entries\n");
773 printf("\t\t\t\t: Data TLB: 4 KByte pages, 4-way set associative, 64 entries\n");
776 printf("\t\t\t\t: Data TLB: 4 MByte pages, 4-way set associative, 8 entries\n");
779 printf("\t\t\t\t: Data TLB1: 4 MByte pages, 4-way set associative, 32 entries\n");
782 printf("\t\t\t\t: 1st-level instruction cache: 8 KBytes, 4-way set associative, 32 byte line size\n");
785 printf("\t\t\t\t: 1st-level instruction cache: 16 KBytes, 4-way set associative, 32 byte line size\n");
788 printf("\t\t\t\t: 1st-level data cache: 8 KBytes, 2-way set associative, 32 byte line size\n");
791 printf("\t\t\t\t: Instruction TLB: 4 MByte pages, 4-way set associative, 4 entries\n");
794 printf("\t\t\t\t: 1st-level data cache: 16 KBytes, 4-way set associative, 32 byte line size\n");
797 printf("\t\t\t\t: 3rd-level cache: 512 KBytes, 4-way set associative, 64 byte line size, 2 lines per sector\n");
800 printf("\t\t\t\t: 3rd-level cache: 1 MBytes, 8-way set associative, 64 byte line size, 2 lines per sector\n");
803 printf("\t\t\t\t: 3rd-level cache: 2 MBytes, 8-way set associative, 64 byte line size, 2 lines per sector\n");
806 printf("\t\t\t\t: 3rd-level cache: 4 MBytes, 8-way set associative, 64 byte line size, 2 lines per sector\n");
809 printf("\t\t\t\t: 1st-level data cache: 32 KBytes, 8-way set associative, 64 byte line size\n");
812 printf("\t\t\t\t: 1st-level instruction cache: 32 KBytes, 8-way set associative, 64 byte line size\n");
815 printf("\t\t\t\t: No 2nd-level cache or, if processor contains a valid 2nd-level cache, no 3rd-level cache\n");
818 printf("\t\t\t\t: 2nd-level cache: 128 KBytes, 4-way set associative, 32 byte line size\n");
821 printf("\t\t\t\t: 2nd-level cache: 256 KBytes, 4-way set associative, 32 byte line size\n");
824 printf("\t\t\t\t: 2nd-level cache: 512 KBytes, 4-way set associative, 32 byte line size\n");
827 printf("\t\t\t\t: 2nd-level cache: 1 MByte, 4-way set associative, 32 byte line size\n");
830 printf("\t\t\t\t: 2nd-level cache: 2 MByte, 4-way set associative, 32 byte line size\n");
833 printf("\t\t\t\t: 3rd-level cache: 4 MByte, 4-way set associative, 64 byte line size\n");
836 printf("\t\t\t\t: 3rd-level cache: 8 MByte, 8-way set associative, 64 byte line size\n");
839 printf("\t\t\t\t: 2nd-level cache: 4 MByte, 16-way set associative, 64 byte line size\n");
842 printf("\t\t\t\t: Instruction TLB: 4 KByte and 2-MByte or 4-MByte pages, 64 entries\n");
845 printf("\t\t\t\t: Instruction TLB: 4 KByte and 2-MByte or 4-MByte pages, 128 entries\n");
848 printf("\t\t\t\t: Instruction TLB: 4 KByte and 2-MByte or 4-MByte pages, 256 entries\n");
851 printf("\t\t\t\t: Data TLB0: 4 MByte pages, 4-way set associative, 16 entries\n");
854 printf("\t\t\t\t: Data TLB0: 4 KByte pages, 4-way associative, 16 entries\n");
857 printf("\t\t\t\t: Data TLB: 4 KByte and 4 MByte pages, 64 entries\n");
860 printf("\t\t\t\t: Data TLB: 4 KByte and 4 MByte pages,128 entries\n");
863 printf("\t\t\t\t: Data TLB: 4 KByte and 4 MByte pages,256 entries\n");
866 printf("\t\t\t\t: 1st-level data cache: 16 KByte, 8-way set associative, 64 byte line size\n");
869 printf("\t\t\t\t: 1st-level data cache: 8 KByte, 4-way set associative, 64 byte line size\n");
872 printf("\t\t\t\t: 1st-level data cache: 16 KByte, 4-way set associative, 64 byte line size\n");
875 printf("\t\t\t\t: 1st-level data cache: 32 KByte, 4-way set associative, 64 byte line size\n");
878 printf("\t\t\t\t: Trace cache: 12 K-μop, 8-way set associative\n");
881 printf("\t\t\t\t: Trace cache: 16 K-μop, 8-way set associative\n");
884 printf("\t\t\t\t: Trace cache: 32 K-μop, 8-way set associative\n");
887 printf("\t\t\t\t: 2nd-level cache: 1 MByte, 4-way set associative, 64byte line size\n");
890 printf("\t\t\t\t: 2nd-level cache: 128 KByte, 8-way set associative, 64 byte line size, 2 lines per sector\n");
893 printf("\t\t\t\t: 2nd-level cache: 256 KByte, 8-way set associative, 64 byte line size, 2 lines per sector\n");
896 printf("\t\t\t\t: 2nd-level cache: 512 KByte, 8-way set associative, 64 byte line size, 2 lines per sector\n");
899 printf("\t\t\t\t: 2nd-level cache: 1 MByte, 8-way set associative, 64 byte line size, 2 lines per sector\n");
902 printf("\t\t\t\t: 2nd-level cache: 2 MByte, 8-way set associative, 64byte line size\n");
905 printf("\t\t\t\t: 2nd-level cache: 512 KByte, 2-way set associative, 64-byte line size\n");
908 printf("\t\t\t\t: 2nd-level cache: 256 KByte, 8-way set associative, 32 byte line size\n");
911 printf("\t\t\t\t: 2nd-level cache: 512 KByte, 8-way set associative, 32 byte line size\n");
914 printf("\t\t\t\t: 2nd-level cache: 1 MByte, 8-way set associative, 32 byte line size\n");
917 printf("\t\t\t\t: 2nd-level cache: 2 MByte, 8-way set associative, 32 byte line size\n");
920 printf("\t\t\t\t: 2nd-level cache: 512 KByte, 4-way set associative, 64 byte line size\n");
923 printf("\t\t\t\t: 2nd-level cache: 1 MByte, 8-way set associative, 64 byte line size\n");
926 printf("\t\t\t\t: Instruction TLB: 4 KByte pages, 4-way set associative, 128 entries\n");
929 printf("\t\t\t\t: Data TLB: 4 KByte pages, 4-way set associative, 128 entries\n");
932 printf("\t\t\t\t: Data TLB1: 4 KByte pages, 4-way associative, 256 entries\n");
935 printf("\t\t\t\t: 64-Byte prefetching\n");
938 printf("\t\t\t\t: 128-Byte prefetching\n");
942 ;/* invalid descriptor. We'll print nothing */