static void pcmpinit(void) { uchar *p, *e; Apic *apic; void *va; /* * Map the local APIC. */ va = vmap(pcmp->lapicbase, 1024); print("LAPIC: %.8lux %#p\n", pcmp->lapicbase, va); if(va == nil) panic("pcmpinit: cannot map lapic %.8lux", pcmp->lapicbase); p = ((uchar*)pcmp)+PCMPsz; e = ((uchar*)pcmp)+pcmp->length; if(getconf("*dumpmp") != nil) dumpmp(p, e); if(getconf("*mp") != nil) mpoverride(&p, &e); /* * Run through the table saving information needed for starting * application processors and initialising any I/O APICs. The table * is guaranteed to be in order such that only one pass is necessary. */ while(p < e) switch(*p){ default: print("pcmpinit: unknown PCMP type 0x%uX (e-p 0x%luX)\n", *p, e-p); while(p < e){ print("%uX ", *p); p++; } break; case PcmpPROCESSOR: if(apic = mkprocessor((PCMPprocessor*)p)){ apic->addr = va; apic->paddr = pcmp->lapicbase; } p += PCMPprocessorsz; continue; case PcmpBUS: mkbus((PCMPbus*)p); p += PCMPbussz; continue; case PcmpIOAPIC: if(apic = mkioapic((PCMPioapic*)p)) ioapicinit(apic, apic->apicno); p += PCMPioapicsz; continue; case PcmpIOINTR: mkiointr((PCMPintr*)p); p += PCMPintrsz; continue; case PcmpLINTR: mklintr((PCMPintr*)p); p += PCMPintrsz; continue; } /* * Ininitalize local APIC and start application processors. */ mpinit(); }
void mpinit(void) { int ncpu, cpuson; char *cp; PCMP *pcmp; uchar *e, *p; Apic *apic, *bpapic; void *va; mpdebug = getconf("*debugmp") != nil; i8259init(); syncclock(); bpapic = nil; cpuson = 0; if(_mp_ == 0) { /* * We can easily get processor info from ACPI, but * interrupt routing, etc. would require interpreting AML. */ print("mpinit: no mp table found, assuming uniprocessor\n"); archrevert(); return; } pcmp = KADDR(_mp_->physaddr); /* * Map the local APIC. */ if((va = vmap(pcmp->lapicbase, 1024)) == nil) return; mppcmp = pcmp; print("LAPIC: %#lux %#lux\n", pcmp->lapicbase, (ulong)va); /* * Run through the table saving information needed for starting * application processors and initialising any I/O APICs. The table * is guaranteed to be in order such that only one pass is necessary. */ p = ((uchar*)pcmp)+sizeof(PCMP); e = ((uchar*)pcmp)+pcmp->length; while(p < e) switch(*p){ default: print("mpinit: unknown PCMP type 0x%uX (e-p 0x%luX)\n", *p, e-p); while(p < e){ print("%uX ", *p); p++; } break; case PcmpPROCESSOR: if(apic = mkprocessor((PCMPprocessor*)p)){ /* * Must take a note of bootstrap processor APIC * now as it will be needed in order to start the * application processors later and there's no * guarantee that the bootstrap processor appears * first in the table before the others. */ apic->addr = va; apic->paddr = pcmp->lapicbase; if(apic->flags & PcmpBP) bpapic = apic; cpuson++; } p += sizeof(PCMPprocessor); continue; case PcmpBUS: mkbus((PCMPbus*)p); p += sizeof(PCMPbus); continue; case PcmpIOAPIC: if(apic = mkioapic((PCMPioapic*)p)) ioapicinit(apic, ((PCMPioapic*)p)->apicno); p += sizeof(PCMPioapic); continue; case PcmpIOINTR: mkiointr((PCMPintr*)p); p += sizeof(PCMPintr); continue; case PcmpLINTR: mklintr((PCMPintr*)p); p += sizeof(PCMPintr); continue; } dprint("mpinit: mp table describes %d cpus\n", cpuson); /* For now, always scan ACPI's MADT for processors that MP missed. */ trympacpi(); if (bpapic == nil) bpapic = bootapic; /* * No bootstrap processor, no need to go further. */ if(bpapic == 0) return; bpapic->online = 1; lapicinit(bpapic); /* * These interrupts are local to the processor * and do not appear in the I/O APIC so it is OK * to set them now. */ intrenable(IrqTIMER, lapicclock, 0, BUSUNKNOWN, "clock"); intrenable(IrqERROR, lapicerror, 0, BUSUNKNOWN, "lapicerror"); intrenable(IrqSPURIOUS, lapicspurious, 0, BUSUNKNOWN, "lapicspurious"); lapiconline(); checkmtrr(); /* * Initialise the application processors. */ if(cp = getconf("*ncpu")){ ncpu = strtol(cp, 0, 0); if(ncpu < 1) ncpu = 1; else if(ncpu > MAXMACH) ncpu = MAXMACH; } else ncpu = MAXMACH; memmove((void*)APBOOTSTRAP, apbootstrap, sizeof(apbootstrap)); for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){ if(ncpu <= 1) break; if((apic->flags & (PcmpBP|PcmpEN)) == PcmpEN && apic->type == PcmpPROCESSOR){ mpstartap(apic); conf.nmach++; ncpu--; } } /* * we don't really know the number of processors till * here. * * set conf.copymode here if nmach > 1. * Should look for an ExtINT line and enable it. */ if(X86FAMILY(m->cpuidax) == 3 || conf.nmach > 1) conf.copymode = 1; }
void mpinit(void) { int ncpu; char *cp; PCMP *pcmp; uchar *e, *p; Apic *apic, *bpapic; i8259init(); syncclock(); if(_mp_ == 0) return; pcmp = KADDR(_mp_->physaddr); /* * Map the local APIC. */ if(mmukmap(pcmp->lapicbase, 0, 1024) == 0) return; bpapic = nil; /* * Run through the table saving information needed for starting * application processors and initialising any I/O APICs. The table * is guaranteed to be in order such that only one pass is necessary. */ p = ((uchar*)pcmp)+sizeof(PCMP); e = ((uchar*)pcmp)+pcmp->length; while(p < e) switch(*p){ default: print("mpinit: unknown PCMP type 0x%uX (e-p 0x%luX)\n", *p, e-p); while(p < e){ print("%uX ", *p); p++; } break; case PcmpPROCESSOR: if(apic = mkprocessor((PCMPprocessor*)p)){ /* * Must take a note of bootstrap processor APIC * now as it will be needed in order to start the * application processors later and there's no * guarantee that the bootstrap processor appears * first in the table before the others. */ apic->addr = KADDR(pcmp->lapicbase); if(apic->flags & PcmpBP) bpapic = apic; } p += sizeof(PCMPprocessor); continue; case PcmpBUS: mkbus((PCMPbus*)p); p += sizeof(PCMPbus); continue; case PcmpIOAPIC: if(apic = mkioapic((PCMPioapic*)p)) ioapicinit(apic, ((PCMPioapic*)p)->apicno); p += sizeof(PCMPioapic); continue; case PcmpIOINTR: mkiointr((PCMPintr*)p); p += sizeof(PCMPintr); continue; case PcmpLINTR: mklintr((PCMPintr*)p); p += sizeof(PCMPintr); continue; } /* * No bootstrap processor, no need to go further. */ if(bpapic == 0) return; lapicinit(bpapic); lock(&mprdthilock); mprdthi |= (1<<bpapic->apicno)<<24; unlock(&mprdthilock); /* * These interrupts are local to the processor * and do not appear in the I/O APIC so it is OK * to set them now. */ intrenable(IrqTIMER, lapicclock, 0, BUSUNKNOWN, "clock"); intrenable(IrqERROR, lapicerror, 0, BUSUNKNOWN, "lapicerror"); intrenable(IrqSPURIOUS, lapicspurious, 0, BUSUNKNOWN, "lapicspurious"); lapiconline(); checkmtrr(); /* * Initialise the application processors. */ if(cp = getconf("*ncpu")){ ncpu = strtol(cp, 0, 0); if(ncpu < 1) ncpu = 1; } else ncpu = MaxAPICNO; memmove((void*)APBOOTSTRAP, apbootstrap, sizeof(apbootstrap)); for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){ if(ncpu <= 1) break; if((apic->flags & (PcmpBP|PcmpEN)) == PcmpEN && apic->type == PcmpPROCESSOR){ mpstartap(apic); conf.nmach++; ncpu--; } } /* * we don't really know the number of processors till * here. * * set conf.copymode here if nmach > 1. * Should look for an ExtINT line and enable it. */ if(X86FAMILY(m->cpuidax) == 3 || conf.nmach > 1) conf.copymode = 1; }