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

« back to all changes in this revision

Viewing changes to cpuid.c

  • Committer: Bazaar Package Importer
  • Author(s): Ramakrishnan M
  • Date: 2002-03-16 10:01:08 UTC
  • Revision ID: james.westby@ubuntu.com-20020316100108-g5s0oncp4nlrzww4
Tags: upstream-3.3
ImportĀ upstreamĀ versionĀ 3.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}