// Multiprocessor support // Search memory for MP description structures. // http://developer.intel.com/design/pentium/datashts/24201606.pdf #include "types.h" #include "defs.h" #include "param.h" #include "memlayout.h" #include "mp.h" #include "x86.h" #include "mmu.h" #include "proc.h" struct cpu cpus[NCPU]; static struct cpu *bcpu; int ismp; int ncpu; uchar ioapicid; int mpbcpu(void) { return bcpu-cpus; } static uchar sum(uchar *addr, int len) { int i, sum; sum = 0; for(i=0; iphysaddr == 0) return 0; conf = (struct mpconf*) p2v((uint) mp->physaddr); if(memcmp(conf, "PCMP", 4) != 0) return 0; if(conf->version != 1 && conf->version != 4) return 0; if(sum((uchar*)conf, conf->length) != 0) return 0; *pmp = mp; return conf; } void mpinit(void) { uchar *p, *e; struct mp *mp; struct mpconf *conf; struct mpproc *proc; struct mpioapic *ioapic; bcpu = &cpus[0]; if((conf = mpconfig(&mp)) == 0) return; ismp = 1; lapic = (uint*)conf->lapicaddr; for(p=(uchar*)(conf+1), e=(uchar*)conf+conf->length; papicid){ cprintf("mpinit: ncpu=%d apicid=%d\n", ncpu, proc->apicid); ismp = 0; } if(proc->flags & MPBOOT) bcpu = &cpus[ncpu]; cpus[ncpu].id = ncpu; ncpu++; p += sizeof(struct mpproc); continue; case MPIOAPIC: ioapic = (struct mpioapic*)p; ioapicid = ioapic->apicno; p += sizeof(struct mpioapic); continue; case MPBUS: case MPIOINTR: case MPLINTR: p += 8; continue; default: cprintf("mpinit: unknown config type %x\n", *p); ismp = 0; } } if(!ismp){ // Didn't like what we found; fall back to no MP. ncpu = 1; lapic = 0; ioapicid = 0; return; } if(mp->imcrp){ // Bochs doesn't support IMCR, so this doesn't run on Bochs. // But it would on real hardware. outb(0x22, 0x70); // Select IMCR outb(0x23, inb(0x23) | 1); // Mask external interrupts. } }