Main Page | Directories | File List | Globals

cpu.c

Go to the documentation of this file.
00001 /*
00002  * kernel_arch/i386/kernel/cpu/cpu.c
00003  *
00004  * Copyright (c) 2003-2004 Lukasz Dembinski <dembol@nasa.com.pl>
00005  * All Rights Reserved
00006  * 
00007  * Date:        2004/01
00008  * Author:      Lukasz Dembinski
00009  * Info:        cpu.c core file
00010  * Contact:     mailto: <dembol@nasa.com.pl>
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 /*    "prefetchnta 256(%%esi)\n\t"
00100     "prefetchnta 288(%%esi)\n\t"
00101     "prefetchnta 320(%%esi)\n\t"
00102     "prefetchnta 352(%%esi)\n\t"
00103     "prefetchnta 384(%%esi)\n\t"
00104     "prefetchnta 416(%%esi)\n\t"
00105     "prefetchnta 448(%%esi)\n\t"
00106     "prefetchnta 480(%%esi)"
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 /*    "movl 256(%%esi), %%eax\n\t"
00120     "movl 288(%%esi), %%eax\n\t"
00121     "movl 320(%%esi), %%eax\n\t"
00122     "movl 352(%%esi), %%eax\n\t"
00123     "movl 384(%%esi), %%eax\n\t"
00124     "movl 416(%%esi), %%eax\n\t"
00125     "movl 448(%%esi), %%eax\n\t"
00126     "movl 480(%%esi), %%eax"*/
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 //    rdtsc(tsc_s[0], tsc_s[1]);
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 /*    "prefetcht1 256(%%esi)\n\t"
00148     "prefetcht1 288(%%esi)\n\t"
00149     "prefetcht1 320(%%esi)\n\t"
00150     "prefetcht1 352(%%esi)\n\t"
00151     "prefetcht1 384(%%esi)\n\t"
00152     "prefetcht1 416(%%esi)\n\t"
00153     "prefetcht1 448(%%esi)\n\t"
00154     "prefetcht1 480(%%esi)"*/
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 /*    "movl 256(%%esi), %%eax\n\t"
00171     "movl 288(%%esi), %%eax\n\t"
00172     "movl 320(%%esi), %%eax\n\t"
00173     "movl 352(%%esi), %%eax\n\t"
00174     "movl 384(%%esi), %%eax\n\t"
00175     "movl 416(%%esi), %%eax\n\t"
00176     "movl 448(%%esi), %%eax\n\t"
00177     "movl 480(%%esi), %%eax"*/
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 /*    "movl 256(%%esi), %%eax\n\t"
00200     "movl 288(%%esi), %%eax\n\t"
00201     "movl 320(%%esi), %%eax\n\t"
00202     "movl 352(%%esi), %%eax\n\t"
00203     "movl 384(%%esi), %%eax\n\t"
00204     "movl 416(%%esi), %%eax\n\t"
00205     "movl 448(%%esi), %%eax\n\t"
00206     "movl 480(%%esi), %%eax"*/
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, &reg[0], &reg[1], &reg[2], &reg[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                         /* in entries */
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                         /* in k-bytes */
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                         /* in k-bytes */
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                         /* in u-ops */
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     /* AMD features */
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 //    if (!cpuid_level(cpu, 0x0003)) 
00542 //      return;
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 //    cpu_mtrr_init();
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 }
Dokumentacje wygenerowano programem Doxygen 1.4.2 dla projektu Agnix