diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
| commit | 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch) | |
| tree | c6e220ba61db3a6ea4052e6841296d829654e664 /os/pc/archmp.c | |
| parent | 46439007cf417cbd9ac8049bb4122c890097a0fa (diff) | |
20060303
Diffstat (limited to 'os/pc/archmp.c')
| -rw-r--r-- | os/pc/archmp.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/os/pc/archmp.c b/os/pc/archmp.c new file mode 100644 index 00000000..fbbda091 --- /dev/null +++ b/os/pc/archmp.c @@ -0,0 +1,138 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +#include "mp.h" + +#define cpuserver 1 + +_MP_ *_mp_; + +static _MP_* +mpscan(uchar *addr, int len) +{ + uchar *e, *p, sum; + int i; + + e = addr+len; + for(p = addr; p < e; p += sizeof(_MP_)){ + if(memcmp(p, "_MP_", 4)) + continue; + sum = 0; + for(i = 0; i < sizeof(_MP_); i++) + sum += p[i]; + if(sum == 0) + return (_MP_*)p; + } + return 0; +} + +static _MP_* +mpsearch(void) +{ + uchar *bda; + ulong p; + _MP_ *mp; + + /* + * Search for the MP Floating Pointer Structure: + * 1) in the first KB of the EBDA; + * 2) in the last KB of system base memory; + * 3) in the BIOS ROM between 0xE0000 and 0xFFFFF. + */ + bda = KADDR(0x400); + if((p = (bda[0x0F]<<8)|bda[0x0E])){ + if(mp = mpscan(KADDR(p), 1024)) + return mp; + } + else{ + p = ((bda[0x14]<<8)|bda[0x13])*1024; + if(mp = mpscan(KADDR(p-1024), 1024)) + return mp; + } + return mpscan(KADDR(0xF0000), 0x10000); +} + +static int identify(void); + +PCArch archmp = { +.id= "_MP_", +.ident= identify, +.reset= mpshutdown, +.intrinit= mpinit, +.intrenable= mpintrenable, +.fastclock= i8253read, +.timerset= lapictimerset, +}; + +static int +identify(void) +{ + PCMP *pcmp; + uchar *p, sum; + ulong length; + + if(getconf("*nomp")) + return 1; + + /* + * Search for an MP configuration table. For now, + * don't accept the default configurations (physaddr == 0). + * Check for correct signature, calculate the checksum and, + * if correct, check the version. + * To do: check extended table checksum. + */ + if((_mp_ = mpsearch()) == 0 || _mp_->physaddr == 0) + return 1; + + pcmp = KADDR(_mp_->physaddr); + if(memcmp(pcmp, "PCMP", 4)) + return 1; + + length = pcmp->length; + sum = 0; + for(p = (uchar*)pcmp; length; length--) + sum += *p++; + + if(sum || (pcmp->version != 1 && pcmp->version != 4)) + return 1; + + if(cpuserver && m->havetsc) + archmp.fastclock = tscticks; + return 0; +} + +Lock mpsynclock; + +void +syncclock(void) +{ + uvlong x; + + if(arch->fastclock != tscticks) + return; + + if(m->machno == 0){ + wrmsr(0x10, 0); + m->tscticks = 0; + } else { + x = MACHP(0)->tscticks; + while(x == MACHP(0)->tscticks) + ; + wrmsr(0x10, MACHP(0)->tscticks); + cycles(&m->tscticks); + } +} + +uvlong +tscticks(uvlong *hz) +{ + if(hz != nil) + *hz = m->cpuhz; + + cycles(&m->tscticks); /* Uses the rdtsc instruction */ + return m->tscticks; +} |
