// 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]; int ncpu; uchar ioapicid; 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; int ismp; struct mp *mp; struct mpconf *conf; struct mpproc *proc; struct mpioapic *ioapic; if((conf = mpconfig(&mp)) == 0) panic("Expect to run on an SMP"); ismp = 1; lapic = (uint*)conf->lapicaddr; for(p=(uchar*)(conf+1), e=(uchar*)conf+conf->length; papicid; // apicid may differ from 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: ismp = 0; break; } } if(!ismp) panic("Didn't find a suitable machine"); 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. } }