📄 init.c
字号:
/* VIA/Cyrix/Centaur Processors with CPUID */ case 'C': if ( cpu_id.vend_id[1] == 'e' ) { /* CentaurHauls */ l1_cache = cpu_id.cache_info[3] + cpu_id.cache_info[7]; l2_cache = cpu_id.cache_info[11]; switch(cpu_id.type){ case 5: cprint(LINE_CPU, 0, "Centaur 5x86"); off = 12; break; case 6: // VIA C3 switch(cpu_id.model){ default: if (cpu_id.step < 8) { cprint(LINE_CPU, 0, "VIA C3 Samuel2"); off = 14; } else { cprint(LINE_CPU, 0, "VIA C3 Eden"); off = 11; } break; case 10: cprint(LINE_CPU, 0, "VIA C7 (C5J)"); l1_cache = 64; l2_cache = 128; off = 16; break; case 13: cprint(LINE_CPU, 0, "VIA C7 (C5R)"); l1_cache = 64; l2_cache = 128; off = 12; break; case 15: cprint(LINE_CPU, 0, "VIA Isaiah (CN)"); l1_cache = 64; l2_cache = 1024; off = 15; break; } } } else { /* CyrixInstead */ switch(cpu_id.type) { case 5: switch(cpu_id.model) { case 0: cprint(LINE_CPU, 0, "Cyrix 6x86MX/MII"); off = 16; break; case 4: cprint(LINE_CPU, 0, "Cyrix GXm"); off = 9; break; } return; case 6: // VIA C3 switch(cpu_id.model) { case 6: cprint(LINE_CPU, 0, "Cyrix III"); off = 9; break; case 7: if (cpu_id.step < 8) { cprint(LINE_CPU, 0, "VIA C3 Samuel2"); off = 14; } else { cprint(LINE_CPU, 0, "VIA C3 Ezra-T"); off = 13; } break; case 8: cprint(LINE_CPU, 0, "VIA C3 Ezra-T"); off = 13; break; case 9: cprint(LINE_CPU, 0, "VIA C3 Nehemiah"); off = 15; break; } // L1 = L2 = 64 KB from Cyrix III to Nehemiah l1_cache = 64; l2_cache = 64; break; } } break; /* Unknown processor */ default: off = 3; /* Make a guess at the family */ switch(cpu_id.type) { case 5: cprint(LINE_CPU, 0, "586"); return; case 6: cprint(LINE_CPU, 0, "686"); return; } } /* We are here only if the CPU type supports the rdtsc instruction */ /* Print CPU speed */ if ((speed = cpuspeed()) > 0) { if (speed < 1000000-50) { speed += 50; /* for rounding */ cprint(LINE_CPU, off, " . MHz"); dprint(LINE_CPU, off+1, speed/1000, 3, 1); dprint(LINE_CPU, off+5, (speed/100)%10, 1, 0); } else { speed += 500; /* for rounding */ cprint(LINE_CPU, off, " MHz"); dprint(LINE_CPU, off, speed/1000, 5, 0); } extclock = speed; } /* Print out L1 cache info */ /* To measure L1 cache speed we use a block size that is 1/4th */ /* of the total L1 cache size since half of it is for instructions */ if (l1_cache) { cprint(LINE_CPU+1, 0, "L1 Cache: K "); dprint(LINE_CPU+1, 11, l1_cache, 3, 0); if ((speed=memspeed((ulong)mapping(0x100), (l1_cache / 4) * 1024, 200, MS_COPY))) { cprint(LINE_CPU+1, 16, " MB/s"); dprint(LINE_CPU+1, 16, speed, 6, 0); } } /* Print out L2 cache info */ /* We measure the L2 cache speed by using a block size that is */ /* the size of the L1 cache. We have to fudge if the L1 */ /* cache is bigger than the L2 */ if (l2_cache) { cprint(LINE_CPU+2, 0, "L2 Cache: K "); dprint(LINE_CPU+2, 10, l2_cache, 4, 0); dprint(LINE_CPU+2, 10, l2_cache, 4, 0); if (l2_cache < l1_cache) { i = l1_cache / 4 + l2_cache / 4; } else { i = l1_cache; } if ((speed=memspeed((ulong)mapping(0x100), i*1024, 200, MS_COPY))) { cprint(LINE_CPU+2, 16, " MB/s"); dprint(LINE_CPU+2, 16, speed, 6, 0); } } /* Print out L3 cache info */ /* We measure the L3 cache speed by using a block size that is */ /* the size of the L2 cache. */ if (l3_cache) { cprint(LINE_CPU+3, 0, "L3 Cache: K "); dprint(LINE_CPU+3, 10, l3_cache, 4, 0); dprint(LINE_CPU+3, 10, l3_cache, 4, 0); i = l2_cache*2; if ((speed=memspeed((ulong)mapping(0x100), i*1024, 150, MS_COPY))) { cprint(LINE_CPU+3, 16, " MB/s"); dprint(LINE_CPU+3, 16, speed, 6, 0); } } /* Determine memory speed. To find the memory speed we use */ /* A block size that is 5x the sum of the L1, L2 & L3 caches */ i = (l3_cache + l2_cache + l1_cache) * 5; /* Make sure that we have enough memory to do the test */ if ((1 + (i * 2)) > (v->plim_upper << 2)) { i = ((v->plim_upper <<2) - 1) / 2; } if((speed = memspeed((ulong)mapping(0x100), i*1024, 50, MS_COPY))) { cprint(LINE_CPU+4, 16, " MB/s"); dprint(LINE_CPU+4, 16, speed, 6, 0); } /* Record the starting time */ asm __volatile__ ("rdtsc":"=a" (v->startl),"=d" (v->starth)); v->snapl = v->startl; v->snaph = v->starth; v->rdtsc = 1; if (l1_cache == 0) { l1_cache = 66; } if (l2_cache == 0) { l1_cache = 666; }}/* Find cache-able memory size */static void cacheable(void){ ulong speed, pspeed; ulong paddr, mem_top, cached; mem_top = v->pmap[v->msegs - 1].end; cached = v->test_pages; pspeed = 0; for (paddr=0x200; paddr <= mem_top - 64; paddr+=0x400) { int i; int found; /* See if the paddr is at a testable location */ found = 0; for(i = 0; i < v->msegs; i++) { if ((v->pmap[i].start >= paddr) && (v->pmap[i].end <= (paddr + 32))) { found = 1; break; } } if (!found) { continue; } /* Map the range and perform the test */ map_page(paddr); speed = memspeed((ulong)mapping(paddr), 32*4096, 1, MS_READ); if (pspeed) { if (speed < pspeed) { cached -= 32; } pspeed = (ulong)((float)speed * 0.7); } } aprint(LINE_INFO, COL_CACHE_TOP, cached); /* Ensure the default set of pages are mapped */ map_page(0); map_page(0x80000);}/* #define TICKS 5 * 11832 (count = 6376)*//* #define TICKS (65536 - 12752) *//* #define TICKS (65536 - 8271) */#define TICKS 59659 /* Program counter to 50 ms = 59659 clks *//* Returns CPU clock in khz */static int cpuspeed(void){ int loops; /* Setup timer */ outb((inb(0x61) & ~0x02) | 0x01, 0x61); outb(0xb0, 0x43); outb(TICKS & 0xff, 0x42); outb(TICKS >> 8, 0x42); asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high)); loops = 0; do { loops++; } while ((inb(0x61) & 0x20) == 0); asm __volatile__ ( "rdtsc\n\t" \ "subl st_low,%%eax\n\t" \ "sbbl st_high,%%edx\n\t" \ :"=a" (end_low), "=d" (end_high) ); /* Make sure we have a credible result */ if (loops < 4 || end_low < 50000) { return(-1); } if(tsc_invariable){ end_low = correct_tsc(end_low); } v->clks_msec = end_low/50; return(v->clks_msec);}/* Measure cache/memory speed by copying a block of memory. *//* Returned value is kbytes/second */ulong memspeed(ulong src, ulong len, int iter, int type){ ulong dst; ulong wlen; int i; dst = src + len; wlen = len / 4; /* Length is bytes */ /* Calibrate the overhead with a zero word copy */ asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high)); for (i=0; i<iter; i++) { asm __volatile__ ( "movl %0,%%esi\n\t" \ "movl %1,%%edi\n\t" \ "movl %2,%%ecx\n\t" \ "cld\n\t" \ "rep\n\t" \ "movsl\n\t" \ :: "g" (src), "g" (dst), "g" (0) : "esi", "edi", "ecx" ); } asm __volatile__ ("rdtsc":"=a" (cal_low),"=d" (cal_high)); /* Compute the overhead time */ asm __volatile__ ( "subl %2,%0\n\t" "sbbl %3,%1" :"=a" (cal_low), "=d" (cal_high) :"g" (st_low), "g" (st_high), "0" (cal_low), "1" (cal_high) ); /* Now measure the speed */ switch (type) { case MS_COPY: /* Do the first copy to prime the cache */ asm __volatile__ ( "movl %0,%%esi\n\t" \ "movl %1,%%edi\n\t" \ "movl %2,%%ecx\n\t" \ "cld\n\t" \ "rep\n\t" \ "movsl\n\t" \ :: "g" (src), "g" (dst), "g" (wlen) : "esi", "edi", "ecx" ); asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high)); for (i=0; i<iter; i++) { asm __volatile__ ( "movl %0,%%esi\n\t" \ "movl %1,%%edi\n\t" \ "movl %2,%%ecx\n\t" \ "cld\n\t" \ "rep\n\t" \ "movsl\n\t" \ :: "g" (src), "g" (dst), "g" (wlen) : "esi", "edi", "ecx" ); } asm __volatile__ ("rdtsc":"=a" (end_low),"=d" (end_high)); break; case MS_WRITE: asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high)); for (i=0; i<iter; i++) { asm __volatile__ ( "movl %0,%%ecx\n\t" \ "movl %1,%%edi\n\t" \ "movl %2,%%eax\n\t" \ "rep\n\t" \ "stosl\n\t" :: "g" (wlen), "g" (dst), "g" (0) : "edi", "ecx", "eax" ); } asm __volatile__ ("rdtsc":"=a" (end_low),"=d" (end_high)); break; case MS_READ: asm __volatile__ ( "movl %0,%%esi\n\t" \ "movl %1,%%ecx\n\t" \ "cld\n\t" \ "L1:\n\t" \ "lodsl\n\t" \ "loop L1\n\t" \ :: "g" (src), "g" (wlen) : "esi", "ecx" ); asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high)); for (i=0; i<iter; i++) { asm __volatile__ ( "movl %0,%%esi\n\t" \ "movl %1,%%ecx\n\t" \ "cld\n\t" \ "L2:\n\t" \ "lodsl\n\t" \ "loop L2\n\t" \ :: "g" (src), "g" (wlen) : "esi", "ecx" ); } asm __volatile__ ("rdtsc":"=a" (end_low),"=d" (end_high)); break; } /* Compute the elapsed time */ asm __volatile__ ( "subl %2,%0\n\t" "sbbl %3,%1" :"=a" (end_low), "=d" (end_high) :"g" (st_low), "g" (st_high), "0" (end_low), "1" (end_high) ); /* Subtract the overhead time */ asm __volatile__ ( "subl %2,%0\n\t" "sbbl %3,%1" :"=a" (end_low), "=d" (end_high) :"g" (cal_low), "g" (cal_high), "0" (end_low), "1" (end_high) ); /* Make sure that the result fits in 32 bits */ if (end_high) { return(0); } /* If this was a copy adjust the time */ if (type == MS_COPY) { end_low /= 2; } /* Convert to clocks/KB */ end_low /= len; end_low *= 1024; end_low /= iter; if (end_low == 0) { return(0); } if(tsc_invariable){ end_low = correct_tsc(end_low); } /* Convert to kbytes/sec */ return((v->clks_msec)/end_low);}ulong correct_tsc(ulong el_org){ float coef_now, coef_max; int msr_lo, msr_hi, is_xe; rdmsr(0x198, msr_lo, msr_hi); is_xe = (msr_lo >> 31) & 0x1; if(is_xe){ rdmsr(0x198, msr_lo, msr_hi); coef_max = ((msr_hi >> 8) & 0x1F); if ((msr_hi >> 14) & 0x1) { coef_max = coef_max + 0.5f; } } else { rdmsr(0x17, msr_lo, msr_hi); coef_max = ((msr_lo >> 8) & 0x1F); if ((msr_lo >> 14) & 0x1) { coef_max = coef_max + 0.5f; } } if((cpu_id.feature_flag >> 7) & 1) { rdmsr(0x198, msr_lo, msr_hi); coef_now = ((msr_lo >> 8) & 0x1F); if ((msr_lo >> 14) & 0x1) { coef_now = coef_now + 0.5f; } } else { rdmsr(0x2A, msr_lo, msr_hi); coef_now = (msr_lo >> 22) & 0x1F; } if(coef_max && coef_now) { el_org = (ulong)(el_org * coef_now / coef_max); } return el_org;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -