00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <agnix/agnix.h>
00015 #include <agnix/adi/adi.h>
00016 #include <asm/cpu_ops.h>
00017 #include <agnix/console.h>
00018 #include <agnix/memory.h>
00019 #include <asm/bitops.h>
00020 #include <agnix/math64.h>
00021
00022 #define HIGH_WORD(x) ((x) >> 16)
00023 #define LOW_WORD(x) ((x) & 0xFFFF)
00024
00025 #define CPU_FAMILIES 3
00026 #define CPU_DESCRIPTIONS 15
00027 #define MAX_NR_CPU 8
00028
00029 struct chip_s cpu_chip;
00030 struct chip_ops_s cpu_chip_ops;
00031 struct cpu_parm_s cpu_intel_parm;
00032
00033 struct cpu_model_s cpu_models[] = {
00034
00035 { 0x04,
00036 { "486 DX-25/33", "486 DX-50", "486 SX", "486 DX/2", "486 SL", "486 SX/2",
00037 "unknown", "486 DX/2-WB", "486 DX/4", "486 DX/4-WB", "unknown",
00038 "unknown", "unknown", "unknown", "unknown", "unknown" }
00039 },
00040
00041 { 0x05,
00042 { "Pentium 60/66 A-step", "Pentium 60/66", "Pentium 75-200", "OverDrive PODP5V83",
00043 "Pentium MMX", "unknown", "unknown", "Pentium Mobile 75-200", "Pentium Mobile MMX",
00044 "unknown", "unknown", "unknown", "unknown", "unknown", "unknown", "unknown" }
00045 },
00046
00047 { 0x06,
00048 { "Pentium Pro A-step", "Pentium Pro", "Unknown", "Pentium II (Klamath)", "Unknown",
00049 "Pentium II (Deschutes)","Pentium II Mobile",
00050 "Pentium III (Katmai)", "Pentium III (Coppermine)", "Unknown", "Pentium III (Cascades)",
00051 "Unknown", "Unknown", "Unknown", "Unknown", "Unknown" }
00052 },
00053 };
00054
00055 const char *cpu_descriptions[] = {
00056 "Unknown", "Intel Celeron", "Intel Pentium III", "Intel Pentium III Xeon",
00057 "Intel Pentium III", "Mobile Intel Pentium III", "Mobile Intel Celeron",
00058 "Intel Pentium IV", "Intel Pentium IV", "Intel Celeron", "Intel Xeon",
00059 "Intel Xeon MP", "Unknown", "Intel Pentium 4", "Mobile Intel Celeron"
00060 };
00061
00062 int cpu_capable(u32 capable_bit)
00063 {
00064 struct cpu_parm_s *cpu_parm = cpu_parm((&cpu_chip));
00065
00066 return test_bit(capable_bit, cpu_parm->cpu_features);
00067 }
00068
00069 void __init cpu_get_cache_latency(void)
00070 {
00071 u8 buf[1024];
00072 u8 buf2[1024];
00073 u8 buf3[1024];
00074 u32 ptr, ptr2, ptr3;
00075 u32 tsc[2];
00076 u32 tsc_s[2];
00077 u32 tsc_e[2];
00078
00079 ptr = ((u32)(buf + 0x20) & (~(0x20 - 1)));
00080 ptr2 = ((u32)(buf2 + 0x20) & (~(0x20 - 1)));
00081 ptr3 = ((u32)(buf3 + 0x20) & (~(0x20 - 1)));
00082
00083
00084 __asm__ __volatile__ (
00085 "prefetchnta (%%esi)\n\t"
00086 "prefetchnta 32(%%esi)\n\t"
00087 "prefetchnta 64(%%esi)\n\t"
00088 "prefetchnta 96(%%esi)\n\t"
00089 "prefetchnta 128(%%esi)\n\t"
00090 "prefetchnta 160(%%esi)\n\t"
00091 "prefetchnta 192(%%esi)\n\t"
00092 "prefetchnta 224(%%esi)\n\t"
00093 :
00094 :"S"(ptr)
00095 );
00096
00097 rdtsc(tsc_s[0], tsc_s[1]);
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 __asm__ __volatile__ (
00110 "movl (%%esi), %%eax\n\t"
00111 "movl 32(%%esi), %%eax\n\t"
00112 "movl 64(%%esi), %%eax\n\t"
00113 "movl 96(%%esi), %%eax\n\t"
00114 "movl 128(%%esi), %%eax\n\t"
00115 "movl 160(%%esi), %%eax\n\t"
00116 "movl 192(%%esi), %%eax\n\t"
00117 "movl 224(%%esi), %%eax\n\t"
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 :
00128 :
00129 );
00130
00131 rdtsc(tsc_e[0], tsc_e[1]);
00132 sub_64_64(tsc, tsc_e, tsc_s);
00133 printk("\tL1 latency: %d cycles\n", (tsc[0] / 8));
00134
00135
00136
00137 __asm__ __volatile__ (
00138 "prefetcht1 0(%%esi)\n\t"
00139 "prefetcht1 32(%%esi)\n\t"
00140 "prefetcht1 64(%%esi)\n\t"
00141 "prefetcht1 96(%%esi)\n\t"
00142 "prefetcht1 128(%%esi)\n\t"
00143 "prefetcht1 160(%%esi)\n\t"
00144 "prefetcht1 192(%%esi)\n\t"
00145 "prefetcht1 224(%%esi)\n\t"
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 :
00156 :"S"(ptr2));
00157
00158 rdtsc(tsc_s[0], tsc_s[1]);
00159
00160 __asm__ __volatile__ (
00161 "movl (%%esi), %%eax\n\t"
00162 "movl 32(%%esi), %%eax\n\t"
00163 "movl 64(%%esi), %%eax\n\t"
00164 "movl 96(%%esi), %%eax\n\t"
00165 "movl 128(%%esi), %%eax\n\t"
00166 "movl 160(%%esi), %%eax\n\t"
00167 "movl 192(%%esi), %%eax\n\t"
00168 "movl 224(%%esi), %%eax\n\t"
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 :
00179 :
00180 );
00181
00182 rdtsc(tsc_e[0], tsc_e[1]);
00183 sub_64_64(tsc, tsc_e, tsc_s);
00184 printk("\tL2 latency: %d cycles\n", (tsc[0] / 8));
00185
00186
00187 rdtsc(tsc_s[0], tsc_s[1]);
00188
00189 __asm__ __volatile__ (
00190 "movl (%%esi), %%eax\n\t"
00191 "movl 32(%%esi), %%eax\n\t"
00192 "movl 64(%%esi), %%eax\n\t"
00193 "movl 96(%%esi), %%eax\n\t"
00194 "movl 128(%%esi), %%eax\n\t"
00195 "movl 160(%%esi), %%eax\n\t"
00196 "movl 192(%%esi), %%eax\n\t"
00197 "movl 224(%%esi), %%eax\n\t"
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 :
00208 :"S"(ptr3)
00209 );
00210
00211 rdtsc(tsc_e[0], tsc_e[1]);
00212 sub_64_64(tsc, tsc_e, tsc_s);
00213 printk("\tRAM latency: %d cycles\n", (tsc[0] / 8));
00214 }
00215
00216 void __init cpu_get_speed(void)
00217 {
00218 int speed;
00219
00220 if (!(read_cr4() & CPU_CR4_TSD)) {
00221 speed = tsc_get_speed();
00222 printk("\tcpu_speed: %d.%d MHz\n", speed / 1000, speed % 1000);
00223 }
00224 }
00225
00226 void cpu_print_info(struct cpu_parm_s *cpu, int broadcast)
00227 {
00228 if (cpu->cpu_misc.cpu_brand_id > 0) {
00229 if (cpu->cpu_description) {
00230 if (broadcast)
00231 printk("CPU_%d: %s processor\n", cpu->cpu_no, cpu->cpu_description);
00232 else
00233 printf("CPU_%d: %s processor\n", cpu->cpu_no, cpu->cpu_description);
00234 } else {
00235 if (broadcast)
00236 printk("CPU_%d: Unknown description for Processor\n", cpu->cpu_no);
00237 else
00238 printf("CPU_%d: Unknown description for Processor\n", cpu->cpu_no);
00239 }
00240
00241 if (cpu->cpu_model_id) {
00242 if (broadcast)
00243 printk("\tcpu_model: %s\n", cpu->cpu_model_id);
00244 else
00245 printf("\tcpu_model: %s\n", cpu->cpu_model_id);
00246 } else {
00247 if (broadcast)
00248 printk("\tcpu_model: Unknown\n");
00249 else
00250 printf("\tcpu_model: Unknown\n");
00251 }
00252
00253 } else {
00254 if (cpu->cpu_model_id) {
00255 if (broadcast)
00256 printk("CPU_%d: %s\n", cpu->cpu_no, cpu->cpu_model_id);
00257 else
00258 printf("CPU_%d: %s\n", cpu->cpu_no, cpu->cpu_model_id);
00259 } else {
00260 if (broadcast)
00261 printk("\tcpu_model: Unknown\n");
00262 else
00263 printf("\tcpu_model: Unknown\n");
00264 }
00265 }
00266
00267 if (broadcast) {
00268 printk("\tcpu_serial: %04x-%04x-%04x-%04x-%04x-%04x\n",
00269 HIGH_WORD(cpu->cpu_serial[2]), LOW_WORD(cpu->cpu_serial[2]),
00270 HIGH_WORD(cpu->cpu_serial[2]), LOW_WORD(cpu->cpu_serial[1]),
00271 HIGH_WORD(cpu->cpu_serial[2]), LOW_WORD(cpu->cpu_serial[0]));
00272 } else {
00273 printf("\tcpu_serial: %04x-%04x-%04x-%04x-%04x-%04x\n",
00274 HIGH_WORD(cpu->cpu_serial[2]), LOW_WORD(cpu->cpu_serial[2]),
00275 HIGH_WORD(cpu->cpu_serial[2]), LOW_WORD(cpu->cpu_serial[1]),
00276 HIGH_WORD(cpu->cpu_serial[2]), LOW_WORD(cpu->cpu_serial[0]));
00277 }
00278
00279 if (broadcast) {
00280
00281 #ifdef DEBUG_CPU
00282 printk("\tcpuid_max_level = %d\n", cpu->cpu_cpuid_level);
00283 printk("\tcpu_vendor_id = %s\n", cpu->cpu_vendor_id);
00284 printk("\tcpu_apic_id = %08x\n", cpu->cpu_misc.cpu_apic_id);
00285 printk("\tcpu_logical_count = %08x\n", cpu->cpu_misc.cpu_log_count);
00286 printk("\tcpu_clflush_size = %08x\n", cpu->cpu_misc.cpu_chunks);
00287 printk("\tcpu_brand_index = %08x\n", cpu->cpu_misc.cpu_brand_id);
00288 printk("\tcpu_features = %08x%08x\n\n", cpu->cpu_features[1], cpu->cpu_features[0]);
00289
00290 printk("\texfamily exmodel type family model stepping\n");
00291 printk("\t%08x %04x %02x %04x %04x %04x\n", cpu->cpu_sig.cpu_extended_family, cpu->cpu_sig.cpu_extended_model,
00292 cpu->cpu_sig.cpu_type, cpu->cpu_sig.cpu_family,
00293 cpu->cpu_sig.cpu_model, cpu->cpu_sig.cpu_stepping);
00294 #endif
00295
00296 #ifdef DEBUG_CPU
00297 printk("\tcache_sizes:\n");
00298 printk("\t\td_cache_level_1 = %dKB\n", cpu->cpu_cache.dcl_1);
00299 printk("\t\ti_cache_level_1 = %dKB\n", cpu->cpu_cache.icl_1);
00300 printk("\t\tcache_level_2 = %dKB\n", cpu->cpu_cache.cl_2);
00301 printk("\t\tcache_level_3 = %dKB\n", cpu->cpu_cache.cl_3);
00302 printk("\t\ttrace_cache = %duops\n", cpu->cpu_cache.trc);
00303 #else
00304 printk("\tcache_sizes: ");
00305 printk("d_L1 %dKB, ", cpu->cpu_cache.dcl_1);
00306 printk("i_L1 %dKB, ", cpu->cpu_cache.icl_1);
00307 printk("L2 %dKB, ", cpu->cpu_cache.cl_2);
00308 printk("L3 %dKB, ", cpu->cpu_cache.cl_3);
00309 printk("TC %duops\n", cpu->cpu_cache.trc);
00310 #endif
00311
00312 #ifdef DEBUG_CPU
00313 printk("\t\ti_tlb_4K = %d ent i_tlb_2M = %d ent i_tlb_4M = %d ent\n",
00314 cpu->cpu_cache.itlb_4K, cpu->cpu_cache.itlb_2M, cpu->cpu_cache.itlb_4M);
00315 printk("\t\td_tlb_4K = %d ent d_tlb_2M = %d ent d_tlb_4M = %d ent\n",
00316 cpu->cpu_cache.dtlb_4K, cpu->cpu_cache.dtlb_2M, cpu->cpu_cache.dtlb_4M);
00317 #endif
00318
00319 } else {
00320 printf("\tcpuid_max_level = %d\n", cpu->cpu_cpuid_level);
00321 printf("\tcpu_vendor_id = %s\n", cpu->cpu_vendor_id);
00322 printf("\tcpu_apic_id = %08x\n", cpu->cpu_misc.cpu_apic_id);
00323 printf("\tcpu_logical_count = %08x\n", cpu->cpu_misc.cpu_log_count);
00324 printf("\tcpu_clflush_size = %08x\n", cpu->cpu_misc.cpu_chunks);
00325 printf("\tcpu_brand_index = %08x\n", cpu->cpu_misc.cpu_brand_id);
00326 printf("\tcpu_features = %08x%08x\n\n", cpu->cpu_features[1], cpu->cpu_features[0]);
00327
00328 printf("\texfamily exmodel type family model stepping\n");
00329 printf("\t%08x %04x %02x %04x %04x %04x\n\n", cpu->cpu_sig.cpu_extended_family, cpu->cpu_sig.cpu_extended_model,
00330 cpu->cpu_sig.cpu_type, cpu->cpu_sig.cpu_family,
00331 cpu->cpu_sig.cpu_model, cpu->cpu_sig.cpu_stepping);
00332 printf("\td_cache_level_1 = %dKB\n", cpu->cpu_cache.dcl_1);
00333 printf("\ti_cache_level_1 = %dKB\n", cpu->cpu_cache.icl_1);
00334 printf("\tcache_level_2 = %dKB\n", cpu->cpu_cache.cl_2);
00335 printf("\tcache_level_3 = %dKB\n", cpu->cpu_cache.cl_3);
00336 printf("\ttrace_cache = %duops\n", cpu->cpu_cache.trc);
00337
00338 printf("\ti_tlb_4K = %d ent i_tlb_2M = %d ent i_tlb_4M = %d ent\n",
00339 cpu->cpu_cache.itlb_4K, cpu->cpu_cache.itlb_2M, cpu->cpu_cache.itlb_4M);
00340 printf("\td_tlb_4K = %d ent d_tlb_2M = %d ent d_tlb_4M = %d ent\n",
00341 cpu->cpu_cache.dtlb_4K, cpu->cpu_cache.dtlb_2M, cpu->cpu_cache.dtlb_4M);
00342 }
00343 }
00344
00345 void __init cpu_parse_model_id(struct cpu_parm_s *cpu)
00346 {
00347 int i;
00348
00349 if (cpu->cpu_misc.cpu_brand_id > 0) {
00350 if (cpu->cpu_misc.cpu_brand_id < CPU_DESCRIPTIONS)
00351 cpu->cpu_description = cpu_descriptions[cpu->cpu_misc.cpu_brand_id];
00352 else
00353 cpu->cpu_description = NULL;
00354 }
00355
00356 cpu->cpu_model_id = NULL;
00357 for (i = 0; i < CPU_FAMILIES; i++) {
00358 if (cpu_models[i].cpu_family == cpu->cpu_sig.cpu_family) {
00359 cpu->cpu_model_id = cpu_models[i].cpu_names[cpu->cpu_sig.cpu_model];
00360 break;
00361 }
00362 }
00363
00364 }
00365
00366 void __init cpu_get_cache_size(struct cpu_parm_s *cpu)
00367 {
00368 u32 reg[4];
00369 u8 *reg_ch = (u8 *)reg;
00370 int cycles;
00371 int i, j;
00372 u32 dcl_1, icl_1, cl_2, cl_3;
00373 u32 itlb_4K, itlb_2M, itlb_4M;
00374 u32 dtlb_4K, dtlb_2M, dtlb_4M;
00375 u32 trc;
00376
00377 dcl_1 = icl_1 = cl_2 = cl_3 = 0;
00378 itlb_4K = itlb_2M = itlb_4M = 0;
00379 dtlb_4K = dtlb_2M = dtlb_4M = 0;
00380 trc = 0;
00381
00382 if (!cpuid_level(cpu, 0x0002))
00383 return;
00384
00385 cycles = (int)cpuid_eax(0x0002) & 0xFF;
00386
00387 for (i = 0; i < cycles; i++) {
00388 cpuid(0x0002, ®[0], ®[1], ®[2], ®[3]);
00389
00390 for (j = 0; j < 16; j++) {
00391 u8 regl, regh;
00392
00393 if (reg_ch[j] & 0x80)
00394 continue;
00395
00396 regh = reg_ch[j] >> 4;
00397 regl = reg_ch[j] & 0xF;
00398 switch(regh) {
00399 case 0:
00400 switch(regl) {
00401
00402 case 0x1: itlb_4K += 32; break;
00403 case 0x2: itlb_4M += 2; break;
00404 case 0x3: dtlb_4K += 64; break;
00405 case 0x4: dtlb_4M += 8; break;
00406
00407 case 0x6: icl_1 += 8; break;
00408 case 0x8: icl_1 += 16; break;
00409 case 0xA: dcl_1 += 8; break;
00410 case 0xC: dcl_1 += 16; break;
00411 } break;
00412
00413 case 2:
00414 if (regl >= 2 && regl <= 9)
00415 cl_3 += (regl - 1) << 9;
00416
00417 if (regl == 0xC)
00418 dcl_1 += 32;
00419
00420 break;
00421
00422 case 3:
00423 switch(regl) {
00424
00425 case 0x0: icl_1 += 32; break;
00426 case 0x9:
00427 case 0xB: cl_2 += 128; break;
00428 case 0xC: cl_2 += 256; break;
00429 } break;
00430
00431 case 4:
00432 if (regl >= 1 && regl <= 5)
00433 cl_2 += 128 << (regl - 1);
00434 break;
00435
00436 case 5:
00437 if (regl <= 2) {
00438 itlb_4K += 64 << regl;
00439 itlb_2M += 64 << regl;
00440 itlb_4M += 64 << regl;
00441 } else
00442 if (regl >= 0xB && regl <= 0xD) {
00443 dtlb_4K += 64 << (regl - 0xB);
00444 dtlb_4M += 64 << (regl - 0xB);
00445 }
00446 break;
00447
00448 case 6:
00449 if (regl >= 6 && regl <= 8)
00450 dcl_1 += 8 << (regl - 6);
00451 break;
00452
00453 case 7:
00454 switch(regl) {
00455
00456 case 0: trc += 12; break;
00457 case 1: trc += 16; break;
00458 case 2: trc += 32; break;
00459
00460 default:
00461 if (regl >= 0x9 && regl <= 0xC) {
00462 cl_2 += 128 << (regl - 0x9);
00463 }
00464 } break;
00465
00466 case 8:
00467 if (regl >= 2 && regl <= 5)
00468 cl_2 += 256 << (regl - 2);
00469
00470 if (regl >= 6 && regl <= 7)
00471 cl_2 += 512 << (regl - 6);
00472 break;
00473
00474 case 0xB:
00475 switch (regl) {
00476 case 0: itlb_4K += 128; break;
00477 case 3: dtlb_4K += 128; break;
00478 }
00479 break;
00480 }
00481 }
00482 }
00483
00484 cpu->cpu_cache.dcl_1 = dcl_1;
00485 cpu->cpu_cache.icl_1 = icl_1;
00486 cpu->cpu_cache.cl_2 = cl_2;
00487 cpu->cpu_cache.cl_3 = cl_3;
00488 cpu->cpu_cache.itlb_4K = itlb_4K;
00489 cpu->cpu_cache.itlb_2M = itlb_2M;
00490 cpu->cpu_cache.itlb_4M = itlb_4M;
00491 cpu->cpu_cache.dtlb_4K = dtlb_4K;
00492 cpu->cpu_cache.dtlb_2M = dtlb_2M;
00493 cpu->cpu_cache.dtlb_4M = dtlb_4M;
00494 }
00495
00496 void __init cpu_get_signature(struct cpu_parm_s *cpu)
00497 {
00498 u32 eax, ebx, ecx, edx;
00499
00500 if (!cpuid_level(cpu, 0x0001))
00501 return;
00502
00503 cpuid(0x0001, &eax, &ebx, &ecx, &edx);
00504
00505 cpu->cpu_sig_union.cpu_signature_raw = eax;
00506 cpu->cpu_misc_union.cpu_misc_info_raw = ebx;
00507 cpu->cpu_features[0] = edx;
00508 cpu->cpu_features[1] = ecx;
00509 cpu->cpu_serial[2] = eax;
00510
00511
00512 }
00513
00514 void __init cpu_get_vendor_id(struct cpu_parm_s *cpu)
00515 {
00516 if (!cpuid_level(cpu, 0x0000))
00517 return;
00518
00519 cpuid(0x0000, (u32 *)&cpu->cpu_cpuid_level, (u32 *)cpu->cpu_vendor_id,
00520 (u32 *)(cpu->cpu_vendor_id + 8), (u32 *)(cpu->cpu_vendor_id + 4));
00521 }
00522
00523 void __init cpu_get_brand_string(struct cpu_parm_s *cpu)
00524 {
00525 int i, j;
00526
00527 if (!cpuid_level(cpu, 0x0001))
00528 return;
00529
00530 for (i = 0, j = 0; i < 3; i+=4, j++)
00531
00532 cpuid(0x80000002 + j, &cpu->cpu_brand_string[i], &cpu->cpu_brand_string[i + 1],
00533 &cpu->cpu_brand_string[i + 2], &cpu->cpu_brand_string[i + 3]);
00534
00535 }
00536
00537 void __init cpu_get_serial_number(struct cpu_parm_s *cpu)
00538 {
00539 u32 eax, ebx;
00540
00541
00542
00543
00544 cpuid(0x0003, &eax, &ebx, &cpu->cpu_serial[0], &cpu->cpu_serial[1]);
00545 }
00546
00547 int __init cpu_init(struct chip_s *cpu_chip)
00548 {
00549 struct cpu_parm_s *cpu_parm = cpu_parm(cpu_chip);
00550
00551 memset(cpu_parm, 0, sizeof(struct cpu_parm_s));
00552
00553 cpu_get_vendor_id(cpu_parm);
00554 cpu_get_signature(cpu_parm);
00555 cpu_get_cache_size(cpu_parm);
00556 cpu_get_serial_number(cpu_parm);
00557 cpu_parse_model_id(cpu_parm);
00558 cpu_print_info(cpu_parm, 1);
00559
00560 cpu_tsc_init();
00561
00562 cpu_get_speed();
00563
00564 return 0;
00565 }
00566
00567 int __init intel_init(int cpu_no)
00568 {
00569 memset(&cpu_chip, 0, sizeof(cpu_chip));
00570
00571 cpu_chip.chip_name = "CPU";
00572 cpu_chip.chip_ops = &cpu_chip_ops;
00573
00574 cpu_chip_ops.init = cpu_init;
00575 cpu_chip_ops.release = 0;
00576 cpu_chip.internal_parm = (void *)&cpu_intel_parm;
00577 cpu_chip.chip_class = CHIP_CLASS_CPU;
00578 cpu_chip.chip_vendor = 0x8086;
00579 cpu_chip.chip_priority = 100;
00580
00581 adi_register_chip(&cpu_chip);
00582
00583 return 0;
00584 }
00585
00586 void cpu_print_cpuinfo(void)
00587 {
00588 struct cpu_parm_s *cpu_parm = cpu_parm(&cpu_chip);
00589
00590 cpu_print_info(cpu_parm, 0);
00591 }