| plan 9 kernel history: overview | file list | diff list |
1998/0906/pc/archgeneric.c (diff list | history)
| 1998/0906/sys/src/9/pc/archgeneric.c:1,236 – 1998/1106/sys/src/9/pc/archgeneric.c:1,236 (short | long | prev | next) | ||
|
spelling
rsc Fri Mar 4 12:44:25 2005 | ||
| 1992/0923 | #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" | |
| 1997/0327 | static int unimplemented(int) { return 0; } | |
| 1992/0923 | static void | |
| 1997/0327 | nop(void) | |
| 1992/0923 | { } | |
| 1997/0327 | void (*coherence)(void) = nop; | |
| 1998/0710 | void cycletimerinit(void); uvlong cycletimer(uvlong*); | |
| 1997/0327 | PCArch* arch; extern PCArch* knownarch[]; PCArch archgeneric = { "generic", /* id */ 0, /* ident */ i8042reset, /* reset */ unimplemented, /* serialpower */ unimplemented, /* modempower */ i8259init, /* intrinit */ i8259enable, /* intrenable */ i8253enable, /* clockenable */ | |
| 1998/0710 | i8253read, /* read the standard timer */ | |
| 1997/0327 | }; typedef struct { int family; int model; int aalcycles; char* name; } X86type; | |
| 1998/0522 | static X86type x86intel[] = | |
| 1992/0923 | { | |
| 1997/0327 | { 4, 0, 22, "486DX", }, /* known chips */ { 4, 1, 22, "486DX50", }, { 4, 2, 22, "486SX", }, { 4, 3, 22, "486DX2", }, { 4, 4, 22, "486SL", }, { 4, 5, 22, "486SX2", }, { 4, 7, 22, "DX2WB", }, /* P24D */ | |
| 1997/0407 | { 4, 8, 22, "DX4", }, /* P24C */ { 4, 9, 22, "DX4WB", }, /* P24CT */ | |
| 1997/0327 | { 5, 0, 23, "P5", }, { 5, 1, 23, "P5", }, { 5, 2, 23, "P54C", }, | |
| 1997/0407 | { 5, 3, 23, "P24T", }, { 5, 4, 23, "P55C MMX", }, | |
| 1997/0404 | { 5, 7, 23, "P54C VRT", }, | |
| 1997/0327 | { 6, 1, 16, "PentiumPro", },/* determined by trial and error */ | |
| 1998/0906 | { 6, 3, 16, "PentiumII", }, { 6, 5, 16, "PentiumII/Xeon", }, | |
| 1997/0327 | { 3, -1, 32, "386", }, /* family defaults */ { 4, -1, 22, "486", }, | |
| 1998/0906 | { 5, -1, 23, "P5", }, { 6, -1, 16, "P6", }, | |
| 1997/0327 | { -1, -1, 23, "unknown", }, /* total default */ | |
| 1992/0923 | }; | |
| 1997/0327 | ||
| 1998/0522 | /* * The AMD processors all implement the CPUID instruction. * The later ones also return the processor name via functions * 0x80000002, 0x80000003 and 0x80000004 in registers AX, BX, CX * and DX: * K5 "AMD-K5(tm) Processor" * K6 "AMD-K6tm w/ multimedia extensions" * K6 3D "AMD-K6(tm) 3D processor" * K6 3D+ ? */ static X86type x86amd[] = { { 5, 0, 23, "AMD-K5", }, /* guesswork */ { 5, 1, 23, "AMD-K5", }, /* guesswork */ { 5, 2, 23, "AMD-K5", }, /* guesswork */ { 5, 3, 23, "AMD-K5", }, /* guesswork */ | |
| 1998/0702 | { 5, 6, 11, "AMD-K6", }, /* determined by trial and error */ { 5, 7, 11, "AMD-K6", }, /* determined by trial and error */ | |
| 1998/0522 | { 5, 8, 23, "AMD-K6 3D", }, /* guesswork */ { 5, 9, 23, "AMD-K6 3D+", },/* guesswork */ { 4, -1, 22, "Am486", }, /* guesswork */ { 5, -1, 23, "AMD-K5/K6", }, /* guesswork */ { -1, -1, 23, "unknown", }, /* total default */ }; | |
| 1997/0327 | void cpuidprint(void) { int i; char buf[128]; i = sprint(buf, "cpu%d: %dMHz ", m->machno, m->cpumhz); if(m->cpuidid[0]) i += sprint(buf+i, "%s ", m->cpuidid); | |
| 1998/0825 | sprint(buf+i, "%s (cpuid: AX 0x%4.4uX DX 0x%4.4uX)\n", | |
| 1997/0327 | m->cpuidtype, m->cpuidax, m->cpuiddx); print(buf); } int cpuidentify(void) { int family, model; X86type *t; | |
| 1998/0401 | ulong cr4; vlong mct; | |
| 1997/0327 | cpuid(m->cpuidid, &m->cpuidax, &m->cpuiddx); | |
| 1998/0522 | if(strncmp(m->cpuidid, "AuthenticAMD", 12) == 0) t = x86amd; else t = x86intel; | |
| 1997/0327 | family = X86FAMILY(m->cpuidax); model = X86MODEL(m->cpuidax); | |
| 1998/0522 | while(t->name){ | |
| 1997/0327 | if((t->family == family && t->model == model) || (t->family == family && t->model == -1) || (t->family == -1)) break; | |
| 1998/0522 | t++; | |
| 1997/0327 | } m->cpuidtype = t->name; i8253init(t->aalcycles); /* * If machine check exception or page size extensions are supported * enable them in CR4 and clear any other set extensions. * If machine check was enabled clear out any lingering status. */ if(m->cpuiddx & 0x88){ cr4 = 0; if(m->cpuiddx & 0x08) cr4 |= 0x10; /* page size extensions */ if(m->cpuiddx & 0x80) cr4 |= 0x40; /* machine check enable */ putcr4(cr4); if(m->cpuiddx & 0x80) | |
| 1998/0401 | rdmsr(0x01, &mct); | |
| 1997/0327 | } return t->family; } void archinit(void) { PCArch **p; arch = 0; for(p = knownarch; *p; p++){ if((*p)->ident && (*p)->ident() == 0){ arch = *p; break; } } if(arch == 0) arch = &archgeneric; else{ if(arch->id == 0) arch->id = archgeneric.id; if(arch->reset == 0) arch->reset = archgeneric.reset; if(arch->serialpower == 0) arch->serialpower = archgeneric.serialpower; if(arch->modempower == 0) arch->modempower = archgeneric.modempower; if(arch->intrinit == 0) arch->intrinit = archgeneric.intrinit; if(arch->intrenable == 0) arch->intrenable = archgeneric.intrenable; } | |
| 1998/0710 | /* pick the better timer */ if(X86FAMILY(m->cpuidax) >= 5){ cycletimerinit(); arch->fastclock = cycletimer; } | |
| 1997/0327 | /* * Decide whether to use copy-on-reference (386 and mp). */ if(X86FAMILY(m->cpuidax) == 3 || conf.nmach > 1) conf.copymode = 1; if(X86FAMILY(m->cpuidax) == 6 /*&& conf.nmach > 1*/) coherence = wbflush; | |
| 1998/0710 | } static uvlong fasthz; void cycletimerinit(void) { | |
| 1998/0716 | wrmsr(0x10, 0); | |
| 1998/0710 | fasthz = 1000000LL*m->cpumhz; } /* | |
| 1998/1106 | * return the most precise clock we have | |
| 1998/0710 | */ uvlong cycletimer(uvlong *hz) { uvlong tsc; rdmsr(0x10, (vlong*)&tsc); | |
| 1998/0717 | m->fastclock = tsc; | |
| 1998/0710 | if(hz != nil) *hz = fasthz; return tsc; } uvlong fastticks(uvlong *hz) { return (*arch->fastclock)(hz); | |
| 1997/0327 | } | |