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; p < e; ) { switch(*p) { case MPPROC: proc = (struct mpproc*)p; if(ncpu != proc->apicid) { 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. } }
void mp_init(void) { uint8_t *p, *e; struct mp *mp; struct mpconf *conf; struct mpproc *proc; struct mpioapic *mpio; if (!cpu_onboot()) // only do once, on the boot CPU return; if ((conf = mpconfig(&mp)) == 0) return; // Not a multiprocessor machine - just use boot CPU. ismp = 1; lapic = (uint32_t *) conf->lapicaddr; for (p = (uint8_t *) (conf + 1), e = (uint8_t *) conf + conf->length; p < e;) { switch (*p) { case MPPROC: proc = (struct mpproc *) p; p += sizeof(struct mpproc); if (!(proc->flags & MPENAB)) continue; // processor disabled // Get a cpu struct and kernel stack for this CPU. cpu *c = (proc->flags & MPBOOT) ? &cpu_boot : cpu_alloc(); c->id = proc->apicid; #if LAB >= 9 c->num = ncpu; // also assign sequential CPU numbers #endif ncpu++; continue; case MPIOAPIC: mpio = (struct mpioapic *) p; p += sizeof(struct mpioapic); ioapicid = mpio->apicno; ioapic = (struct ioapic *) mpio->addr; continue; case MPBUS: case MPIOINTR: case MPLINTR: p += 8; continue; default: panic("mpinit: unknown config type %x\n", *p); } } 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. } }
void mp_init(void) { struct mp *mp; struct mpconf *conf; struct mpproc *proc; uint8_t *p; unsigned int i; bootcpu = &cpus[0]; if ((conf = mpconfig(&mp)) == 0) return; ismp = 1; lapic = (uint32_t *)conf->lapicaddr; for (p = conf->entries, i = 0; i < conf->entry; i++) { //cprintf("mpinit: *p = %u i = %u\n", *p, i); switch (*p) { case MPPROC: proc = (struct mpproc *)p; if (proc->flags & MPPROC_BOOT) bootcpu = &cpus[ncpu]; if (ncpu < NCPU) { cpus[ncpu].cpu_id = ncpu; ncpu++; } else { cprintf("SMP: too many CPUs, CPU %d disabled\n", proc->apicid); } p += sizeof(struct mpproc); continue; case MPBUS: case MPIOAPIC: case MPIOINTR: case MPLINTR: p += 8; continue; default: cprintf("mpinit: unknown config type %x\n", *p); ismp = 0; i = conf->entry; } } bootcpu->cpu_status = CPU_STARTED; if (!ismp) { // Didn't like what we found; fall back to no MP. ncpu = 1; lapic = NULL; cprintf("SMP: configuration not found, SMP disabled\n"); return; } cprintf("SMP: CPU %d found %d CPU(s)\n", bootcpu->cpu_id, ncpu); if (mp->imcrp) { // [MP 3.2.6.1] If the hardware implements PIC mode, // switch to getting interrupts from the LAPIC. cprintf("SMP: Setting IMCR to switch from PIC mode to symmetric I/O mode\n"); outb(0x22, 0x70); // Select IMCR outb(0x23, inb(0x23) | 1); // Mask external interrupts. } }
int init_mp() { uchar_t *p; uint_t ncpu = 0, ismp = 1; mpconf_t *conf; mpproc_t *proc; mpfp_t *mp; mpioapic_t *ioapic; if ((conf = mpconfig(&mp)) == NULL) { printk("could not find MP configuration\n"); return 0; } lapic_regp = (uint_t *) conf->lapicaddr; for (p = (uchar_t *) (conf + 1); p < (uchar_t *) conf + conf->length;) { switch (*p) { case MPPROC: proc = (mpproc_t *) p; if (ncpu != proc->apicid) { printk(LOG_MP "mpinit: ncpu=%d apicid=%d\n", ncpu, proc->apicid); ismp = 0; } cpu_reset_state(&cpuset[ncpu]); if (proc->flags & MPBOOT) { cpu_set_val(&cpuset[ncpu], flag_bsp, 1); printk ("found bootstrap processor #%d\n", proc->apicid); } else printk ("found application processor #%d\n", proc->apicid); cpu_set_val(&cpuset[ncpu], proc_id, proc->apicid); // find next processor ncpu++; p += sizeof(mpproc_t); continue; case MPIOAPIC: ioapic = (mpioapic_t *) p; ioapic_id = ioapic->apicno; p += sizeof(mpioapic_t); continue; case MPBUS: case MPIOINTR: case MPLINTR: p += 8; continue; default: printk(LOG_MP "mpinit: unknown config type %x\n", *p); ismp = 0; } } if (!ismp) { // Didn't like what we found; fall back to no MP. mpinfo.ncpu = 1; mpinfo.ismp = 0; lapic_regp = NULL; ioapic_id = 0; return 0; } // Select IMCR, Mask external interrupts if (mp->imcrp) { outb(0x22, 0x70); outb(0x23, inb(0x23) | 1); } if (ncpu > 1) mpinfo.ismp = 1; else mpinfo.ismp = 0; mpinfo.ncpu = ncpu; // only return AP num return ncpu - 1; }