~ubuntu-branches/ubuntu/maverick/cpuid/maverick

1 by Ramakrishnan M
Import upstream version 3.3
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)
7
8
 * Reference documents:
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
13
 * 
14
 */
15
16
#include <stdio.h>
17
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);
22
23
#define MAXBRANDS 9
24
char *Brands[MAXBRANDS] = {
25
  "brand 0",
26
  "Celeron processor",
27
  "Pentium III processor",
28
  "Intel Pentium III Xeon processor",
29
  "brand 4",
30
  "brand 5",
31
  "brand 6",
32
  "brand 7",
33
  "Intel Pentium 4 processor",
34
};
35
36
#define cpuid(in,a,b,c,d)\
37
  asm("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (in));
38
39
int main(){
40
  int i;
41
  unsigned long li,maxi,maxei,ebx,ecx,edx,unused;
42
43
  /* Insert code here to test if CPUID instruction is available */
44
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");
49
  for(i=0;i<=maxi;i++){
50
    unsigned long eax,ebx,ecx,edx;
51
52
    cpuid(i,eax,ebx,ecx,edx);
53
    printf("%08x %08lx %08lx %08lx %08lx\n",i,eax,ebx,ecx,edx);
54
  }
55
  cpuid(0x80000000,maxei,unused,unused,unused);
56
  for(li=0x80000000;li<=maxei;li++){
57
    unsigned long eax,ebx,ecx,edx;
58
59
    cpuid(li,eax,ebx,ecx,edx);
60
    printf("%08lx %08lx %08lx %08lx %08lx\n",li,eax,ebx,ecx,edx);
61
  }
62
  printf("\n");
63
64
  /* Vendor ID and max CPUID level supported */
65
  cpuid(0,unused,ebx,ecx,edx);
66
  printf("Vendor ID: \"");
67
  for(i=0;i<4;i++)
68
    putchar(ebx >> (8*i));
69
  for(i=0;i<4;i++)
70
    putchar(edx >> (8*i));
71
  for(i=0;i<4;i++)
72
    putchar(ecx >> (8*i));
73
  printf("\"; CPUID level %ld\n\n",maxi);
74
75
  switch(ebx){
76
  case 0x756e6547: /* Intel */
77
    dointel(maxi);
78
    break;
79
  case 0x68747541: /* AMD */
80
    doamd(maxi);
81
    break;
82
  case 0x69727943: /* Cyrix */
83
    docyrix(maxi);
84
    break;
85
  default:
86
    printf("Unknown vendor\n");
87
    break;
88
  }
89
  exit(0);
90
}
91
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",
103
  "10     Reserved",
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",
113
  "20     reserved",
114
  "DS     Debug store",
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",
120
  "SS     Self Snoop",
121
  "HT     Hyper Threading",
122
  "TM     Thermal monitor",
123
  "30     reserved",
124
  "31     reserved",
125
};
126
127
/* Intel-specific information */
128
void dointel(int maxi){
129
  printf("Intel-specific functions:\n");
130
131
  if(maxi >= 1){
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;
137
    int i;
138
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;
149
    feature_flags = edx;
150
151
    printf("Type %d - ",type);
152
    switch(type){
153
    case 0:
154
      printf("Original OEM");
155
      break;
156
    case 1:
157
      printf("Overdrive");
158
      break;
159
    case 2:
160
      printf("Dual-capable");
161
      break;
162
    case 3:
163
      printf("Reserved");
164
      break;
165
    }
166
    printf("\n");
167
168
    printf("Family %d - ",family);
169
    switch(family){
170
    case 3:
171
      printf("i386");
172
      break;
173
    case 4:
174
      printf("i486");
175
      break;
176
    case 5:
177
      printf("Pentium");
178
      break;
179
    case 6:
180
      printf("Pentium Pro");
181
      break;
182
    case 15:
183
      printf("Pentium 4");
184
    }
185
    printf("\n");
186
    if(family == 15){
187
      extended_family = (eax >> 20) & 0xff;
188
      printf("Extended family %d\n",extended_family);
189
    }
190
    printf("Model %d - ",model);
191
    switch(family){
192
    case 3:
193
      break;
194
    case 4:
195
      switch(model){
196
      case 0:
197
      case 1:
198
	printf("DX");
199
	break;
200
      case 2:
201
	printf("SX");
202
	break;
203
      case 3:
204
	printf("487/DX2");
205
	break;
206
      case 4:
207
	printf("SL");
208
	break;
209
      case 5:
210
	printf("SX2");
211
	break;
212
      case 7:
213
	printf("write-back enhanced DX2");
214
	break;
215
      case 8:
216
	printf("DX4");
217
	break;
218
      }
219
      break;
220
    case 5:
221
      switch(model){
222
      case 1:
223
	printf("60/66");
224
	break;
225
      case 2:
226
	printf("75-200");
227
	break;
228
      case 3:
229
	printf("for 486 system");
230
	break;
231
      case 4:
232
	printf("MMX");
233
	break;
234
      }
235
      break;
236
    case 6:
237
      switch(model){
238
      case 1:
239
	printf("Pentium Pro");
240
	break;
241
      case 3:
242
	printf("Pentium II Model 3");
243
	break;
244
      case 5:
245
	printf("Pentium II Model 5/Xeon/Celeron");
246
	break;
247
      case 6:
248
	printf("Celeron");
249
	break;
250
      case 7:
251
	printf("Pentium III/Pentium III Xeon - external L2 cache");
252
	break;
253
      case 8:
254
	printf("Pentium III/Pentium III Xeon - internal L2 cache");
255
	break;
256
      }
257
      break;
258
    case 15:
259
      break;
260
    }
261
    printf("\n");
262
    if(model == 15){
263
      extended_model = (eax >> 16) & 0xf;
264
      printf("Extended model %d\n",extended_model);
265
    }
266
    printf("Stepping %d\n",stepping);
267
268
    printf("Reserved %d\n\n",reserved);
269
270
    brand = ebx & 0xff;
271
    if(brand > 0){
272
      printf("Brand index: %d [",brand);
273
      if(brand  < MAXBRANDS){
274
	printf("%s]\n",Brands[brand]);
275
      } else {
276
	printf("not in table]\n");
277
      }
278
    }
279
    cpuid(0x80000000,eax,ebx,unused,edx);
280
    if(eax & 0x80000000){
281
      /* Extended feature/signature bits supported */
282
      int maxe = eax;
283
      if(maxe >= 0x80000004){
284
	int i;
285
286
	printf("Extended brand string: \"");
287
	for(i=0x80000002;i<=0x80000004;i++){
288
	  unsigned long eax,ebx,ecx,edx;
289
290
	  cpuid(i,eax,ebx,ecx,edx);	
291
	  printregs(eax,ebx,ecx,edx);
292
	}
293
	printf("\"\n");
294
      }
295
    }
296
    if(clf)
297
      printf("CLFLUSH instruction cache line size: %d\n",clf);
298
    
299
    if(apic_id)
300
      printf("Initial APIC ID: %d\n",apic_id);
301
    
302
    if(feature_flags & (1<<28)){
303
      printf("Hyper threading siblings: %d\n",siblings);
304
    }
305
306
    printf("\nFeature flags %08x:\n",feature_flags);
307
    for(i=0;i<32;i++){
308
      if(feature_flags & (1<<i)){
309
	printf("%s\n",Intel_feature_flags[i]);
310
      }
311
    }
312
    printf("\n");
313
  }
314
  if(maxi >= 2){
315
    /* Decode TLB and cache info */
316
    int ntlb,i;
317
318
    ntlb = 255;
319
    printf("TLB and cache info:\n");
320
    for(i=0;i<ntlb;i++){
321
      unsigned long eax,ebx,ecx,edx;
322
323
      cpuid(2,eax,ebx,ecx,edx);
324
      ntlb =  eax & 0xff;
325
      decode_intel_tlb(eax >> 8);
326
      decode_intel_tlb(eax >> 16);
327
      decode_intel_tlb(eax >> 24);
328
      
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);
334
      }
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);
340
      }
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);
346
      }
347
    }
348
  }
349
  if(maxi >= 3){
350
    /* Pentium III CPU serial number */
351
    unsigned long signature,unused,ecx,edx;
352
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);
362
  }
363
}
364
void printregs(int eax,int ebx,int ecx,int edx){
365
  int j;
366
  char string[17];
367
368
  string[16] = '\0';
369
  for(j=0;j<4;j++){
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);
374
  }
375
  printf("%s",string);
376
}
377
378
      
379
/* Decode Intel TLB and cache info descriptors */
380
void decode_intel_tlb(int x){
381
  x &= 0xff;
382
  if(x != 0)
383
    printf("%02x: ",x);
384
  switch(x){
385
  case 0:
386
    break;
387
  case 0x1:
388
    printf("Instruction TLB: 4KB pages, 4-way set assoc, 32 entries\n");
389
    break;
390
  case 0x2:
391
    printf("Instruction TLB: 4MB pages, 4-way set assoc, 2 entries\n");
392
    break;
393
  case 0x3:
394
    printf("Data TLB: 4KB pages, 4-way set assoc, 64 entries\n");
395
    break;
396
  case 0x4:
397
    printf("Data TLB: 4MB pages, 4-way set assoc, 8 entries\n");
398
    break;
399
  case 0x6:
400
    printf("1st-level instruction cache: 8KB, 4-way set assoc, 32 byte line size\n");
401
    break;
402
  case 0x8:
403
    printf("1st-level instruction cache: 16KB, 4-way set assoc, 32 byte line size\n");
404
    break;
405
  case 0xa:
406
    printf("1st-level data cache: 8KB, 2-way set assoc, 32 byte line size\n");
407
    break;
408
  case 0xc:
409
    printf("1st-level data cache: 16KB, 4-way set assoc, 32 byte line size\n");
410
    break;
411
  case 0x40:
412
    printf("No 2nd-level cache, or if 2nd-level cache exists, no 3rd-level cache\n");
413
    break;
414
  case 0x41:
415
    printf("2nd-level cache: 128KB, 4-way set assoc, 32 byte line size\n");
416
    break;
417
  case 0x42:
418
    printf("2nd-level cache: 256KB, 4-way set assoc, 32 byte line size\n");
419
    break;
420
  case 0x43:
421
    printf("2nd-level cache: 512KB, 4-way set assoc, 32 byte line size\n");
422
    break;
423
  case 0x44:
424
    printf("2nd-level cache: 1MB, 4-way set assoc, 32 byte line size\n");
425
    break;
426
  case 0x45:
427
    printf("2nd-level cache: 2MB, 4-way set assoc, 32 byte line size\n");
428
    break;
429
  case 0x50:
430
    printf("Instruction TLB: 4KB and 2MB or 4MB pages, 64 entries\n");
431
    break;
432
  case 0x51:
433
    printf("Instruction TLB: 4KB and 2MB or 4MB pages, 128 entries\n");
434
    break;
435
  case 0x52:
436
    printf("Instruction TLB: 4KB and 2MB or 4MB pages, 256 entries\n");
437
    break;
438
  case 0x5b:
439
    printf("Data TLB: 4KB and 4MB pages, 64 entries\n");
440
    break;
441
  case 0x5c:
442
    printf("Data TLB: 4KB and 4MB pages, 128 entries\n");
443
    break;
444
  case 0x5d:
445
    printf("Data TLB: 4KB and 4MB pages, 256 entries\n");
446
    break;
447
  case 0x66:
448
    printf("1st-level data cache: 8KB, 4-way set assoc, 64 byte line size\n");
449
    break;
450
  case 0x67:
451
    printf("1st-level data cache: 16KB, 4-way set assoc, 64 byte line size\n");
452
    break;
453
  case 0x68:
454
    printf("1st-level data cache: 32KB, 4-way set assoc, 64 byte line size\n");
455
    break;
456
  case 0x70:
457
    printf("Trace cache: 12K-micro-op, 4-way set assoc\n");
458
    break;
459
  case 0x71:
460
    printf("Trace cache: 16K-micro-op, 4-way set assoc\n");
461
    break;
462
  case 0x72:
463
    printf("Trace cache: 32K-micro-op, 4-way set assoc\n");
464
    break;
465
  case 0x79:
466
    printf("2nd-level cache: 128KB, 8-way set assoc, sectored, 64 byte line size\n");
467
    break;
468
  case 0x7a:
469
    printf("2nd-level cache: 256KB, 8-way set assoc, sectored, 64 byte line size\n");    
470
    break;
471
  case 0x7b:
472
    printf("2nd-level cache: 512KB, 8-way set assoc, sectored, 64 byte line size\n");
473
    break;
474
  case 0x7c:
475
    printf("2nd-level cache: 1MB, 8-way set assoc, sectored, 64 byte line size\n");    
476
    break;
477
  case 0x82:
478
    printf("2nd-level cache: 256KB, 8-way set assoc, 32 byte line size\n");
479
    break;
480
  case 0x83:
481
    printf("2nd-level cache: 512KB, 8-way set assoc 32 byte line size\n");
482
    break;
483
  case 0x84:
484
    printf("2nd-level cache: 1MB, 8-way set assoc, 32 byte line size\n");
485
    break;
486
  case 0x85:
487
    printf("2nd-level cache: 2MB, 8-way set assoc, 32 byte line size\n");
488
    break;
489
   default:
490
    printf("unknown TLB/cache descriptor\n");
491
    break;
492
  }
493
}
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",
504
  "APIC",
505
  "10 - Reserved",
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",
513
  "18 - reserved",
514
  "19 - reserved",
515
  "20 - reserved",
516
  "21 - reserved",
517
  "AMD MMX Instruction Extensions",
518
  "MMX instructions",
519
  "FXSAVE/FXRSTOR",
520
  "25 - reserved",
521
  "26 - reserved",
522
  "27 - reserved",
523
  "28 - reserved",
524
  "29 - reserved",
525
  "3DNow! Instruction Extensions",
526
  "3DNow instructions",
527
};
528
529
char *Assoc[] = {
530
  "L2 off",
531
  "Direct mapped",
532
  "2-way",
533
  "reserved",
534
  "4-way",
535
  "reserved",
536
  "8-way",
537
  "reserved",
538
  "16-way",
539
  "reserved",
540
  "reserved",
541
  "reserved",
542
  "reserved",
543
  "reserved",
544
  "reserved",
545
  "full",
546
};
547
548
549
550
/* AMD-specific information */
551
void doamd(int maxi){
552
  unsigned long maxei,unused;
553
  int family = 0;
554
555
  printf("AMD-specific functions\n");
556
557
  /* Do standard stuff */
558
  if(maxi >= 1){
559
    unsigned long eax,ebx,edx,unused;
560
    int stepping,model,reserved;
561
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;
567
568
    printf("Version %08lx:\n",eax);
569
    printf("Family: %d Model: %d [",family,model);
570
    switch(family){
571
    case 4:
572
      printf("486 model %d",model);
573
      break;
574
    case 5:
575
      switch(model){
576
      case 0:
577
      case 1:
578
      case 2:
579
      case 3:
580
      case 6:
581
      case 7:
582
	printf("K6 Model %d",model);
583
	break;
584
      case 8:
585
	printf("K6-2 Model 8");
586
	break;
587
      case 9:
588
	printf("K6-III Model 9");
589
	break;
590
      default:
591
	printf("K5/K6 model %d",model);
592
	break;
593
      }
594
      break;
595
    case 6:
596
      switch(model){
597
      case 1:
598
      case 2:
599
      case 4:
600
	printf("Athlon model %d",model);
601
	break;
602
      case 3:
603
	printf("Duron model 3");
604
	break;
605
      case 6:
606
	printf("Athlon MP/Mobile Athlon model 6");
607
	break;
608
      case 7:
609
	printf("Mobile Duron Model 7");
610
	break;
611
      default:
612
	printf("Duron/Athlon model %d",model);
613
	break;
614
      }
615
616
      break;
617
    }
618
    printf("]\n\n");
619
    {
620
      int i;
621
622
      printf("Standard feature flags %08lx:\n",edx);
623
      for(i=0;i<32;i++){
624
	if(family == 5 && model == 0){
625
	  if(i == 9)
626
	    printf("Global Paging Extensions\n");
627
	  else if(i == 13)
628
	    printf("13 - reserved\n");
629
	} else {
630
	  if(edx & (1<<i)){
631
	    printf("%s\n",AMD_feature_flags[i]);
632
	  }
633
	}
634
      }
635
    }
636
  }
637
  /* Check for presence of extended info */
638
  cpuid(0x80000000,maxei,unused,unused,unused);
639
  if(maxei == 0)
640
    return;
641
642
  if(maxei >= 0x80000001){
643
    unsigned long eax,ebx,ecx,edx;
644
    int stepping,model,generation,reserved;
645
    int i;
646
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;
652
653
    printf("Generation: %d Model: %d\n",generation,model);
654
    printf("Extended feature flags %08lx:\n",edx);
655
    for(i=0;i<32;i++){
656
      if(family == 5 && model == 0 && i == 9){
657
	printf("Global Paging Extensions\n");
658
      } else {
659
	if(edx & (1<<i)){
660
	  printf("%s\n",AMD_feature_flags[i]);
661
	}
662
      }
663
    }
664
  }
665
  printf("\n");
666
  if(maxei >= 0x80000002){
667
    /* Processor identification string */
668
    int j;
669
    printf("Processor name string: ");
670
    for(j=0x80000002;j<=0x80000004;j++){
671
      unsigned long eax,ebx,ecx,edx;
672
673
      cpuid(j,eax,ebx,ecx,edx);
674
      printregs(eax,ebx,ecx,edx);
675
    }
676
    printf("\n");
677
  }
678
  if(maxei >= 0x80000005){
679
    /* TLB and cache info */
680
    unsigned long eax,ebx,ecx,edx;
681
682
    cpuid(0x80000005,eax,ebx,ecx,edx);
683
    printf("L1 Cache Information:\n");
684
    if(family >= 6){
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);
690
    }
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);
696
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);
700
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);
704
    printf("\n");
705
  }
706
  
707
  /* check K6-III (and later?) on-chip L2 cache size */
708
  if (maxei >= 0x80000006) {
709
    unsigned long eax,ebx,ecx,unused;
710
    int assoc;
711
712
    cpuid(0x80000006,eax,ebx,ecx,unused);
713
    printf("L2 Cache Information:\n");
714
    if(family >= 6){
715
      printf("2/4-MB Pages:\n");
716
      assoc = (eax >> 24) & 0xff;
717
      if(assoc == 6)
718
	assoc = 8;
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);
724
      
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);
730
    }
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);
733
734
    printf("\n");
735
  }
736
  /* Check power management feature flags */
737
  if(maxei >= 0x80000007){
738
    unsigned long unused,edx;
739
740
    printf("Advanced Power Management Feature Flags\n");
741
    cpuid(0x80000007,unused,unused,unused,edx);
742
    if(edx & 1)
743
      printf("Has temperature sensing diode\n");
744
    if(edx & 2)
745
      printf("Supports Frequency ID control\n");
746
    if(edx & 4)
747
      printf("Supports Voltage ID control\n");
748
  }
749
  /* Check phys address & linear address size */
750
  if(maxei >= 0x80000008){
751
    unsigned long unused,eax;
752
753
    cpuid(0x80000008,eax,unused,unused,unused);
754
    printf("Maximum linear address: %ld; maximum phys address %ld\n",
755
	   (eax>>8) & 0xff,eax&0xff);
756
  }
757
}
758
759
char *Cyrix_standard_feature_flags_5[] = {
760
  "FPU   Floating Point Unit",
761
  "V86   Virtual Mode Extensions",
762
  "Debug Extension",
763
  "4MB Page Size",
764
  "Time Stamp Counter",
765
  "RDMSR/WRMSR (Model Specific Registers)",
766
  "PAE",
767
  "Machine Check Exception",
768
  "COMPXCHG8B Instruction",
769
  "APIC - On-chip Advanced Programmable Interrupt Controller present and enabled",
770
  "10 - Reserved",
771
  "11 - Reserved",
772
  "MTRR  Memory Type Range Registers",
773
  "13 - reserved",
774
  "Machine Check",
775
  "CMOV  Conditional Move Instruction",
776
  "16 - reserved",
777
  "17 - reserved",
778
  "18 - reserved",
779
  "19 - reserved",
780
  "20 - reserved",
781
  "21 - reserved",
782
  "22 - reserved",
783
  "MMX instructions",
784
  "24 - reserved",
785
  "25 - reserved",
786
  "26 - reserved",
787
  "27 - reserved",
788
  "28 - reserved",
789
  "29 - reserved",
790
  "30 - reserved",
791
};
792
793
char *Cyrix_standard_feature_flags_not5[] = {
794
  "FPU   Floating Point Unit",
795
  "V86   Virtual Mode Extensions",
796
  "Debug Extension",
797
  "4MB Page Size",
798
  "Time Stamp Counter",
799
  "RDMSR/WRMSR (Model Specific Registers)",
800
  "PAE",
801
  "Machine Check Exception",
802
  "COMPXCHG8B Instruction",
803
  "APIC - On-chip Advanced Programmable Interrupt Controller present and enabled",
804
  "10 - Reserved",
805
  "11 - Reserved",
806
  "MTRR  Memory Type Range Registers",
807
  "Global Paging Extension",
808
  "Machine Check",
809
  "CMOV  Conditional Move Instruction",
810
  "16 - reserved",
811
  "17 - reserved",
812
  "18 - reserved",
813
  "19 - reserved",
814
  "20 - reserved",
815
  "21 - reserved",
816
  "22 - reserved",
817
  "MMX instructions",
818
  "24 - reserved",
819
  "25 - reserved",
820
  "26 - reserved",
821
  "27 - reserved",
822
  "28 - reserved",
823
  "29 - reserved",
824
  "30 - reserved",
825
};
826
827
828
char *Cyrix_extended_feature_flags[] = {
829
  "FPU   Floating Point Unit",
830
  "V86   Virtual Mode Extensions",
831
  "Debug Extension",
832
  "Page Size Extensions",
833
  "Time Stamp Counter",
834
  "Cyrix MSR",
835
  "PAE",
836
  "MC Exception",
837
  "COMPXCHG8B",
838
  "APIC on chip",
839
  "SYSCALL/SYSRET",
840
  "11 - reserved",
841
  "MTRR",
842
  "Global bit",
843
  "Machine Check",
844
  "CMOV",
845
  "FPU CMOV",
846
  "17 - reserved",
847
  "18 - reserved",
848
  "19 - reserved",
849
  "20 - reserved",
850
  "21 - reserved",
851
  "22 - reserved",
852
  "MMX",
853
  "Extended MMX",
854
  "25 - reserved",
855
  "26 - reserved",
856
  "27 - reserved",
857
  "28 - reserved",
858
  "29 - reserved",
859
  "30 - reserved",
860
  "3DNow instructions",
861
};
862
863
/* Cyrix-specific information */
864
void docyrix(int maxi){
865
  unsigned long maxei,unused;
866
  int i;
867
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;
873
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);
876
  }
877
878
  /* Do standard stuff */
879
  if(maxi >= 1){
880
    unsigned long eax,unused,edx;
881
    int stepping,model,family,reserved;
882
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;
888
889
    printf("Family: %d Model: %d [",family,model);
890
    switch(family){
891
    case 4:
892
      switch(model){
893
      case 4:
894
	printf("MediaGX");
895
	break;
896
      }
897
      break;
898
    case 5:
899
      switch(model){
900
      case 2:
901
	printf("6x86");
902
	break;
903
      case 4:
904
	printf("BXm");
905
	break;
906
      }
907
      break;
908
    case 6:
909
      switch(model){
910
      case 0:
911
	printf("6x86/MX");
912
	break;
913
      }
914
      break;
915
    }
916
    printf("]\n\n");
917
    if(family == 5 && model == 0){
918
      int i;
919
920
      for(i=0;i<32;i++){
921
	if(edx & (1<<i)){
922
	  printf("%s\n",Cyrix_standard_feature_flags_5[i]);
923
	}
924
      }
925
    } else {
926
      int i;
927
928
      for(i=0;i<32;i++){
929
	if(edx & (1<<i)){
930
	  printf("%s\n",Cyrix_standard_feature_flags_not5[i]);
931
	}
932
      }
933
    }
934
  }
935
  if(maxi >= 2){
936
    /* TLB and L1 Cache info */
937
    int ntlb = 255;
938
    int i;
939
940
    for(i=0;i<ntlb;i++){
941
      unsigned long eax,edx,unused;
942
943
      cpuid(2,eax,unused,unused,edx);
944
      ntlb =  eax & 0xff;
945
      decode_cyrix_tlb(eax >> 8);
946
      decode_cyrix_tlb(eax >> 16);
947
      decode_cyrix_tlb(eax >> 24);
948
      
949
      /* ebx and ecx are reserved */
950
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);
956
      }
957
    }
958
  }
959
960
  /* Check for presence of extended info */
961
  if(maxei < 0x80000000)
962
    return;
963
964
  printf("\nExtended info:\n");
965
  if(maxei >= 0x80000001){
966
    unsigned long eax,ebx,ecx,edx;
967
    int stepping,model,family,reserved,i;
968
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);
975
    switch(family){
976
    case 4:
977
      printf("MediaGX");
978
      break;
979
    case 5:
980
      printf("6x86/GXm");
981
      break;
982
    case 6:
983
      printf("6x86/MX");
984
    }
985
    printf("]\n\n");
986
987
    printf("Extended feature flags:\n");
988
    for(i=0;i<32;i++){
989
      if(edx & (1<<i)){
990
	printf("%s\n",Cyrix_extended_feature_flags[i]);
991
      }
992
    }
993
  }
994
  printf("\n");
995
  if(maxei >= 0x80000002){
996
    /* Processor identification string */
997
    char namestring[49],*cp;
998
    int j;
999
    cp = namestring;
1000
    printf("Processor name string: ");
1001
    for(j=0x80000002;j<=0x80000004;j++){
1002
      unsigned long eax,ebx,ecx,edx;
1003
1004
      cpuid(j,eax,ebx,ecx,edx);
1005
      printregs(eax,ebx,ecx,edx);
1006
    }
1007
  }
1008
  if(maxei >= 0x80000005){
1009
    /* TLB and L1 Cache info */
1010
    int ntlb = 255;
1011
    int i;
1012
1013
    for(i=0;i<ntlb;i++){
1014
      unsigned long eax,ebx,ecx,unused;
1015
1016
      cpuid(0x80000005,eax,ebx,ecx,unused);
1017
      ntlb =  eax & 0xff;
1018
      decode_cyrix_tlb(ebx >> 8);
1019
      decode_cyrix_tlb(ebx >> 16);
1020
      decode_cyrix_tlb(ebx >> 24);
1021
      
1022
      /* eax and edx are reserved */
1023
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);
1029
      }
1030
    }
1031
  }
1032
}
1033
1034
1035
/* Decode Cyrix TLB and cache info descriptors */
1036
void decode_cyrix_tlb(int x){
1037
  switch(x & 0xff){
1038
  case 0:
1039
    break;
1040
  case 0x70:
1041
    printf("TLB: 32 entries 4-way associative 4KB pages\n");
1042
    break;
1043
  case 0x80:
1044
    printf("L1 Cache: 16KB 4-way associative 16 bytes/line\n");
1045
    break;
1046
  }
1047
}