00001
00002
00003
00004
00005 #include "types.h"
00006 #include "defs.h"
00007 #include "param.h"
00008 #include "mp.h"
00009 #include "x86.h"
00010 #include "mmu.h"
00011 #include "proc.h"
00012
00013 struct cpu cpus[NCPU];
00014 static struct cpu *bcpu;
00015 int ismp;
00016 int ncpu;
00017 uchar ioapicid;
00018
00019 int
00020 mpbcpu(void)
00021 {
00022 return bcpu-cpus;
00023 }
00024
00025 static uchar
00026 sum(uchar *addr, int len)
00027 {
00028 int i, sum;
00029
00030 sum = 0;
00031 for(i=0; i<len; i++)
00032 sum += addr[i];
00033 return sum;
00034 }
00035
00036
00037 static struct mp*
00038 mpsearch1(uchar *addr, int len)
00039 {
00040 uchar *e, *p;
00041
00042 e = addr+len;
00043 for(p = addr; p < e; p += sizeof(struct mp))
00044 if(memcmp(p, "_MP_", 4) == 0 && sum(p, sizeof(struct mp)) == 0)
00045 return (struct mp*)p;
00046 return 0;
00047 }
00048
00049
00050
00051
00052
00053
00054 static struct mp*
00055 mpsearch(void)
00056 {
00057 uchar *bda;
00058 uint p;
00059 struct mp *mp;
00060
00061 bda = (uchar*)0x400;
00062 if((p = ((bda[0x0F]<<8)|bda[0x0E]) << 4)){
00063 if((mp = mpsearch1((uchar*)p, 1024)))
00064 return mp;
00065 } else {
00066 p = ((bda[0x14]<<8)|bda[0x13])*1024;
00067 if((mp = mpsearch1((uchar*)p-1024, 1024)))
00068 return mp;
00069 }
00070 return mpsearch1((uchar*)0xF0000, 0x10000);
00071 }
00072
00073
00074
00075
00076
00077
00078 static struct mpconf*
00079 mpconfig(struct mp **pmp)
00080 {
00081 struct mpconf *conf;
00082 struct mp *mp;
00083
00084 if((mp = mpsearch()) == 0 || mp->physaddr == 0)
00085 return 0;
00086 conf = (struct mpconf*)mp->physaddr;
00087 if(memcmp(conf, "PCMP", 4) != 0)
00088 return 0;
00089 if(conf->version != 1 && conf->version != 4)
00090 return 0;
00091 if(sum((uchar*)conf, conf->length) != 0)
00092 return 0;
00093 *pmp = mp;
00094 return conf;
00095 }
00096
00097 void
00098 mpinit(void)
00099 {
00100 uchar *p, *e;
00101 struct mp *mp;
00102 struct mpconf *conf;
00103 struct mpproc *proc;
00104 struct mpioapic *ioapic;
00105
00106 bcpu = &cpus[0];
00107 if((conf = mpconfig(&mp)) == 0)
00108 return;
00109 ismp = 1;
00110 lapic = (uint*)conf->lapicaddr;
00111 for(p=(uchar*)(conf+1), e=(uchar*)conf+conf->length; p<e; ){
00112 switch(*p){
00113 case MPPROC:
00114 proc = (struct mpproc*)p;
00115 if(ncpu != proc->apicid) {
00116 cprintf("mpinit: ncpu=%d apicpid=%d", ncpu, proc->apicid);
00117 panic("mpinit");
00118 }
00119 if(proc->flags & MPBOOT)
00120 bcpu = &cpus[ncpu];
00121 cpus[ncpu].id = ncpu;
00122 ncpu++;
00123 p += sizeof(struct mpproc);
00124 continue;
00125 case MPIOAPIC:
00126 ioapic = (struct mpioapic*)p;
00127 ioapicid = ioapic->apicno;
00128 p += sizeof(struct mpioapic);
00129 continue;
00130 case MPBUS:
00131 case MPIOINTR:
00132 case MPLINTR:
00133 p += 8;
00134 continue;
00135 default:
00136 cprintf("mpinit: unknown config type %x\n", *p);
00137 panic("mpinit");
00138 }
00139 }
00140 if(mp->imcrp){
00141
00142
00143 outb(0x22, 0x70);
00144 outb(0x23, inb(0x23) | 1);
00145 }
00146 }