| plan 9 kernel history: overview | file list | diff list |
1997/0327/pc/mp.c (diff list | history)
| 1997/0327/sys/src/9/pc/mp.c:187,192 – 1997/0405/sys/src/9/pc/mp.c:187,195 (short | long) | ||
| 1997/0327 | */ v = vector; | |
| 1997/0405 | po = intr->flags & PcmpPOMASK; el = intr->flags & PcmpELMASK; | |
| 1997/0327 | switch(intr->intr){ default: /* PcmpINT */ | |
| 1997/0327/sys/src/9/pc/mp.c:195,200 – 1997/0405/sys/src/9/pc/mp.c:198,205 | ||
| 1997/0327 | case PcmpNMI: v |= ApicNMI; | |
| 1997/0405 | po = PcmpHIGH; el = PcmpEDGE; | |
| 1997/0327 | break; case PcmpSMI: | |
| 1997/0327/sys/src/9/pc/mp.c:206,214 – 1997/0405/sys/src/9/pc/mp.c:211,216 | ||
| 1997/0327 | break; } | |
| 1997/0327/sys/src/9/pc/mp.c:368,374 – 1997/0405/sys/src/9/pc/mp.c:370,376 | ||
| 1997/0327 | PCMP *pcmp; ulong *pte; uchar *e, *p; | |
| 1997/0405 | Apic *apic, *bpapic; | |
| 1997/0327 | int clkin; i8259init(); | |
| 1997/0327/sys/src/9/pc/mp.c:376,382 – 1997/0405/sys/src/9/pc/mp.c:378,383 | ||
| 1997/0327 | if(_mp_ == 0) return; pcmp = KADDR(_mp_->physaddr); | |
| 1997/0327/sys/src/9/pc/mp.c:389,394 – 1997/0405/sys/src/9/pc/mp.c:390,397 | ||
| 1997/0327 | mmuflushtlb(PADDR(m->pdb)); } | |
| 1997/0405 | bpapic = 0; | |
| 1997/0327 | /* * Run through the table saving information needed for starting application * processors and initialising any I/O APICs. The table is guaranteed to be in | |
| 1997/0327/sys/src/9/pc/mp.c:401,407 – 1997/0405/sys/src/9/pc/mp.c:404,410 | ||
| 1997/0327 | case PcmpPROCESSOR: if(apic = mkprocessor((PCMPprocessor*)p)){ /* | |
| 1997/0405 | * Must take a note of bootstrap processor APIC | |
| 1997/0327 | * now as it will be needed in order to start the * application processors later and there's no * guarantee that the bootstrap processor appears | |
| 1997/0327/sys/src/9/pc/mp.c:409,415 – 1997/0405/sys/src/9/pc/mp.c:412,418 | ||
| 1997/0327 | */ apic->addr = KADDR(pcmp->lapicbase); if(apic->flags & PcmpBP) | |
| 1997/0405 | bpapic = apic; | |
| 1997/0327 | } p += sizeof(PCMPprocessor); continue; | |
| 1997/0327/sys/src/9/pc/mp.c:437,467 – 1997/0405/sys/src/9/pc/mp.c:440,472 | ||
| 1997/0327 | } /* | |
| 1997/0405 | * No bootstrap processor, no need to go further. | |
| 1997/0327 | */ | |
| 1997/0405 | if(bpapic == 0) return; | |
| 1997/0327 |
| |
| 1997/0405 | clkin = lapicinit(bpapic); lock(&mprdthilock); mprdthi |= (1<<bpapic->apicno)<<24; unlock(&mprdthilock); | |
| 1997/0327 |
| |
| 1997/0405 | /* * 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(VectorTIMER, clockintr, 0, BUSUNKNOWN); intrenable(VectorERROR, lapicerror, 0, BUSUNKNOWN); intrenable(VectorSPURIOUS, lapicspurious, 0, BUSUNKNOWN); lapiconline(clkin); | |
| 1997/0327 |
| |
| 1997/0405 | /* * Initialise the application processors. */ memmove((void*)APBOOTSTRAP, apbootstrap, sizeof(apbootstrap)); for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){ if((apic->flags & (PcmpBP|PcmpEN)) == PcmpEN && apic->type == PcmpPROCESSOR) mpstartap(apic); | |
| 1997/0327 | } /* | |
| 1997/0405/sys/src/9/pc/mp.c:359,366 – 1997/0521/sys/src/9/pc/mp.c:359,373 (short | long) | ||
| 1997/0327 | nvramwrite(0x0F, 0x0A); lapicstartap(apic, PADDR(APBOOTSTRAP)); | |
| 1997/0521 | for(i = 0; i < 100000; i++){ lock(&mprdthilock); if(mprdthi & ((1<<apic->apicno)<<24)){ unlock(&mprdthilock); break; } unlock(&mprdthilock); | |
| 1997/0327 | microdelay(10); | |
| 1997/0521 | } | |
| 1997/0327 | nvramwrite(0x0F, 0x00); } | |
| 1997/0521/sys/src/9/pc/mp.c:207,212 – 1997/0522/sys/src/9/pc/mp.c:207,214 (short | long) | ||
| 1997/0327 | break; case PcmpExtINT: | |
| 1997/0522 | po = PcmpHIGH; el = PcmpEDGE; | |
| 1997/0327 | v |= ApicExtINT; break; } | |
| 1997/0522/sys/src/9/pc/mp.c:207,215 – 1997/0524/sys/src/9/pc/mp.c:207,224 (short | long) | ||
| 1997/0327 | break; case PcmpExtINT: | |
| 1997/0522 |
| |
| 1997/0327 | v |= ApicExtINT; | |
| 1997/0524 | /* * The AMI Goliath doesn't boot successfully with it's LINTR0 entry * which decodes to low+level. The PPro manual says ExtINT should be * level, whereas the Pentium is edge. Setting the Goliath to edge+high * seems to cure the problem. Other PPro MP tables (e.g. ASUS P/I-P65UP5 * have a entry which decodes to edge+high, so who knows. * Perhaps it would be best just to not set an ExtINT entry at all, * it shouldn't be needed for SMP mode. */ po = PcmpHIGH; el = PcmpEDGE; | |
| 1997/0327 | break; } | |
| 1997/0522/sys/src/9/pc/mp.c:587,593 – 1997/0524/sys/src/9/pc/mp.c:596,602 | ||
| 1997/0327 | int r; r = mpintrenablex(v, tbdf, irqctl); | |
| 1997/0524 | if(r == -1 && tbdf != BUSUNKNOWN /*&& _mp_->specrev == 1*/) | |
| 1997/0327 | return mpintrenablex(v, BUSUNKNOWN, irqctl); return r; } | |
| 1997/0524/sys/src/9/pc/mp.c:124,150 – 1997/1101/sys/src/9/pc/mp.c:124,143 (short | long) | ||
| 1997/0327 | mkioapic(PCMPioapic* p) { Apic *apic; | |
| 1997/1101 | * Map the I/O APIC. | |
| 1997/0327 | */ | |
| 1997/1101 | if(mmukmap(p->addr, 0, 1024) == 0) | |
| 1997/0327 | return 0; | |
| 1997/1101 | apic->addr = KADDR(p->addr); | |
| 1997/0327 | apic->flags = p->flags; return apic; | |
| 1997/0524/sys/src/9/pc/mp.c:290,297 – 1997/1101/sys/src/9/pc/mp.c:283,289 | ||
| 1997/0327 | { int clkin; | |
| 1997/1101 | // iprint("Hello Squidboy\n"); | |
| 1997/0327 | machinit(); mmuinit(); | |
| 1997/0524/sys/src/9/pc/mp.c:322,346 – 1997/1101/sys/src/9/pc/mp.c:314,344 | ||
| 1997/0327 | mpstartap(Apic* apic) { ulong *apbootp, *pdb, *pte; | |
| 1997/1101 | Mach *mach, *mach0; | |
| 1997/0327 | int i, machno; uchar *p; | |
| 1997/1101 | mach0 = MACHP(0); | |
| 1997/0327 | /* | |
| 1997/1101 | * Initialise the AP page-tables and Mach structure. The page-tables * are the same as for the bootstrap processor with the exception of | |
| 1997/0327 | * the PTE for the Mach structure. * Xspanalloc will panic if an allocation can't be made. */ | |
| 1997/1101 | p = xspanalloc(3*BY2PG, BY2PG, 0); pdb = (ulong*)p; memmove(pdb, mach0->pdb, BY2PG); p += BY2PG; | |
| 1997/0327 |
| |
| 1997/1101 | if((pte = mmuwalk(pdb, MACHADDR, 1, 0)) == nil) return; memmove(p, KADDR(PPN(*pte)), BY2PG); *pte = PADDR(p)|PTEWRITE|PTEVALID; p += BY2PG; | |
| 1997/0327 |
| |
| 1997/1101 | mach = (Mach*)p; if((pte = mmuwalk(pdb, MACHADDR, 2, 0)) == nil) | |
| 1997/0327 | return; *pte = PADDR(mach)|PTEWRITE|PTEVALID; | |
| 1997/0524/sys/src/9/pc/mp.c:386,392 – 1997/1101/sys/src/9/pc/mp.c:384,389 | ||
| 1997/0327 | mpinit(void) { PCMP *pcmp; | |
| 1997/0405 | Apic *apic, *bpapic; | |
| 1997/0327 | int clkin; | |
| 1997/0524/sys/src/9/pc/mp.c:398,412 – 1997/1101/sys/src/9/pc/mp.c:395,404 | ||
| 1997/0327 | pcmp = KADDR(_mp_->physaddr); /* | |
| 1997/1101 | * Map the local APIC. | |
| 1997/0327 | */ | |
| 1997/1101 | if(mmukmap(pcmp->lapicbase, 0, 1024) == 0) | |
| 1997/0327 | return; | |
| 1997/0405 | bpapic = 0; | |
| 1997/0524/sys/src/9/pc/mp.c:633,639 – 1997/1101/sys/src/9/pc/mp.c:625,631 | ||
| 1997/0327 | * warm-boot sequence is tried. The following is Intel specific and * seems to perform a cold-boot, but at least it comes back. */ | |
| 1997/1101 | *(ushort*)KADDR(0x472) = 0x1234; /* BIOS warm-boot flag */ | |
| 1997/0327 | outb(0xCF9, 0x02); outb(0xCF9, 0x06); #else | |
| 1997/1101/sys/src/9/pc/mp.c:12,17 – 1998/0320/sys/src/9/pc/mp.c:12,19 (short | long) | ||
| 1997/0327 | static Bus* mpbus; static Bus* mpbuslast; | |
| 1998/0320 | static int mpisabus = -1; static int mpeisabus = -1; | |
| 1997/0327 | static Apic mpapic[MaxAPICNO+1]; static int machno2apicno[MaxAPICNO+1]; /* inverse map: machno -> APIC ID */ static Lock mprdthilock; | |
| 1997/1101/sys/src/9/pc/mp.c:93,103 – 1998/0320/sys/src/9/pc/mp.c:95,115 | ||
| 1997/0327 | if(bus->type == BusEISA){ bus->po = PcmpLOW; bus->el = PcmpLEVEL; | |
| 1998/0320 | if(mpeisabus != -1) print("mkbus: more than one EISA bus\n"); mpeisabus = bus->busno; | |
| 1997/0327 | } else if(bus->type == BusPCI){ bus->po = PcmpLOW; bus->el = PcmpLEVEL; } | |
| 1998/0320 | else if(bus->type == BusISA){ bus->po = PcmpHIGH; bus->el = PcmpEDGE; if(mpisabus != -1) print("mkbus: more than one ISA bus\n"); mpisabus = bus->busno; } | |
| 1997/0327 | else{ bus->po = PcmpHIGH; bus->el = PcmpEDGE; | |
| 1997/1101/sys/src/9/pc/mp.c:495,524 – 1998/0320/sys/src/9/pc/mp.c:507,519 | ||
| 1997/0327 | Apic *apic; int bno, dno, lo, n, type; | |
| 1998/0320 | type = BUSTYPE(tbdf); bno = BUSBNO(tbdf); dno = BUSDNO(tbdf); | |
| 1997/0327 | n = 0; for(bus = mpbus; bus; bus = bus->next){ if(bus->type != type) | |
| 1997/1101/sys/src/9/pc/mp.c:528,548 – 1998/0320/sys/src/9/pc/mp.c:523,530 | ||
| 1997/0327 | n++; } if(bus == 0){ | |
| 1998/0320 | print("ioapicirq: can't find bus type %d\n", type); return -1; | |
| 1997/0327 | } /* | |
| 1997/1101/sys/src/9/pc/mp.c:553,558 – 1998/0320/sys/src/9/pc/mp.c:535,547 | ||
| 1997/0327 | n = (aintr->intr->irq>>2) & 0x1F; if(n != dno) continue; | |
| 1998/0320 | /* * Problem: there can be an entry for * each of the device #INT[ABCD] lines. * For now look only for #INTA. */ if(aintr->intr->irq & 0x03) continue; | |
| 1997/0327 | } else{ n = aintr->intr->irq; | |
| 1997/1101/sys/src/9/pc/mp.c:587,596 – 1998/0320/sys/src/9/pc/mp.c:576,624 | ||
| 1997/0327 | { int r; | |
| 1997/0524 |
| |
| 1997/0327 |
| |
| 1998/0320 | /* * If the bus is known, try it. * BUSUNKNOWN is given both by [E]ISA devices and by * interrupts local to the processor (local APIC, coprocessor * breakpoint and page-fault). */ if(tbdf != BUSUNKNOWN && (r = mpintrenablex(v, tbdf, irqctl)) != -1) return r; if(v >= VectorLAPIC && v <= MaxVectorLAPIC){ if(v != VectorSPURIOUS) irqctl->isr = lapiceoi; irqctl->isintr = 1; return v; } if(v < VectorPIC || v > MaxVectorPIC){ print("mpintrenable: vector %d out of range\n", v); return -1; } /* * Either didn't find it or we have to try the default * buses (ISA and EISA). This hack is due to either over-zealousness * or laziness on the part of some manufacturers. * * The MP configuration table on some older systems * (e.g. ASUS PCI/E-P54NP4) has an entry for the EISA bus * but none for ISA. It also has the interrupt type and * polarity set to 'default for this bus' which wouldn't * be compatible with ISA. */ if(mpisabus != -1){ r = mpintrenablex(v, MKBUS(BusISA, 0, 0, 0), irqctl); if(r != -1) return r; } if(mpeisabus != -1){ r = mpintrenablex(v, MKBUS(BusEISA, 0, 0, 0), irqctl); if(r != -1) return r; } return -1; | |
| 1997/0327 | } void | |
| 1998/0320/sys/src/9/pc/mp.c:4,9 – 1998/0401/sys/src/9/pc/mp.c:4,10 (short | long) | ||
|
Add MTRR register support. Add NMI handler for debugging.
The NMI handler prints the CPUs current PC. rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/0327 | #include "dat.h" #include "fns.h" #include "io.h" | |
| 1998/0401 | #include "ureg.h" | |
| 1997/0327 | #include "mp.h" #include "apbootstrap.h" | |
| 1998/0320/sys/src/9/pc/mp.c:287,292 – 1998/0401/sys/src/9/pc/mp.c:288,345 | ||
| 1997/0327 | return v; } | |
| 1998/0401 | static void checkmtrr(void) { int i, vcnt; Mach *mach0; /* * If there are MTRR registers, snarf them for validation. */ if(!(m->cpuiddx & 0x1000)) return; rdmsr(0x0FE, &m->mtrrcap); rdmsr(0x2FF, &m->mtrrdef); if(m->mtrrcap & 0x0100){ rdmsr(0x250, &m->mtrrfix[0]); rdmsr(0x258, &m->mtrrfix[1]); rdmsr(0x259, &m->mtrrfix[2]); for(i = 0; i < 8; i++) rdmsr(0x268+i, &m->mtrrfix[(i+3)]); } vcnt = m->mtrrcap & 0x00FF; if(vcnt > nelem(m->mtrrvar)) vcnt = nelem(m->mtrrvar); for(i = 0; i < vcnt; i++) rdmsr(0x200+i, &m->mtrrvar[i]); /* * If not the bootstrap processor, compare. */ if(m->machno == 0) return; mach0 = MACHP(0); if(mach0->mtrrcap != m->mtrrcap) print("mtrrcap%d: %lluX %lluX\n", m->machno, mach0->mtrrcap, m->mtrrcap); if(mach0->mtrrdef != m->mtrrdef) print("mtrrdef%d: %lluX %lluX\n", m->machno, mach0->mtrrdef, m->mtrrdef); for(i = 0; i < 11; i++){ if(mach0->mtrrfix[i] != m->mtrrfix[i]) print("mtrrfix%d: i%d: %lluX %lluX\n", m->machno, i, mach0->mtrrfix[i], m->mtrrfix[i]); } for(i = 0; i < vcnt; i++){ if(mach0->mtrrvar[i] != m->mtrrvar[i]) print("mtrrvar%d: i%d: %lluX %lluX\n", m->machno, i, mach0->mtrrvar[i], m->mtrrvar[i]); } } | |
| 1997/0327 | #define PDX(va) ((((ulong)(va))>>22) & 0x03FF) #define PTX(va) ((((ulong)(va))>>12) & 0x03FF) | |
| 1998/0320/sys/src/9/pc/mp.c:301,306 – 1998/0401/sys/src/9/pc/mp.c:354,360 | ||
| 1997/0327 | cpuidentify(); cpuidprint(); | |
| 1998/0401 | checkmtrr(); | |
| 1997/0327 | lock(&mprdthilock); mprdthi |= (1<<apic->apicno)<<24; | |
| 1998/0320/sys/src/9/pc/mp.c:392,397 – 1998/0401/sys/src/9/pc/mp.c:446,466 | ||
| 1997/0327 | nvramwrite(0x0F, 0x00); } | |
| 1998/0401 | static void senddbgnmi(void) { /* * NMI all excluding self. */ lapicicrw(0, 0x000C0000|ApicNMI); } static void mpdbg(Ureg* ureg, void*) { iprint("MPDBG: cpu%d: PC 0x%uX\n", m->machno, ureg->pc); } | |
| 1997/0327 | void mpinit(void) { | |
| 1998/0320/sys/src/9/pc/mp.c:482,487 – 1998/0401/sys/src/9/pc/mp.c:551,558 | ||
| 1997/0405 | intrenable(VectorSPURIOUS, lapicspurious, 0, BUSUNKNOWN); lapiconline(clkin); | |
| 1997/0327 | ||
| 1998/0401 | checkmtrr(); | |
| 1997/0405 | /* * Initialise the application processors. */ | |
| 1998/0320/sys/src/9/pc/mp.c:493,502 – 1998/0401/sys/src/9/pc/mp.c:564,576 | ||
| 1997/0327 | /* * Remember to set conf.copymode here if nmach > 1. | |
| 1998/0401 | * Should look for an ExtINT line and enable it. | |
| 1997/0327 | */ if(conf.nmach > 1) conf.copymode = 1; | |
| 1998/0401 | consdebug = senddbgnmi; intrenable(VectorNMI, mpdbg, 0, BUSUNKNOWN); | |
| 1997/0327 | } static int | |
| 1998/0320/sys/src/9/pc/mp.c:624,629 – 1998/0401/sys/src/9/pc/mp.c:698,705 | ||
| 1997/0327 | void mpshutdown(void) { | |
| 1998/0401 | int apicno, machno; | |
| 1997/0327 | /* * To be done... */ | |
| 1998/0320/sys/src/9/pc/mp.c:639,644 – 1998/0401/sys/src/9/pc/mp.c:715,728 | ||
| 1997/0327 | } print("apshutdown: active = 0x%2.2uX\n", active.machs); | |
| 1998/0401 | if(active.machs){ for(machno = 1; machno < conf.nmach; machno++){ if(!(active.machs & (1<<machno))) continue; apicno = machno2apicno[machno]; lapicicrw(1<<apicno, ApicNMI); } } | |
| 1997/0327 | delay(1000); splhi(); | |
| 1998/0401/sys/src/9/pc/mp.c:271,278 – 1998/0605/sys/src/9/pc/mp.c:271,286 (short | long) | ||
|
Bug fix: do not enable PcmpExtINT and PcmpNMI to fix problem with Pentium Pro.
Remove NMI debugging. rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/0327 | if((bus = mpgetbus(p->busno)) == 0) return 0; intin = p->intin; | |
| 1998/0605 | /* * Pentium Pros have problems if LINT[01] are set to ExtINT * so just bag it. Should be OK for SMP mode. */ if(p->intr == PcmpExtINT || p->intr == PcmpNMI) v = ApicIMASK; else v = mpintrinit(bus, p, VectorLAPIC+intin); | |
| 1997/0327 | if(p->apicno == 0xFF){ for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){ if((apic->flags & PcmpEN) && apic->type == PcmpPROCESSOR) | |
| 1998/0401/sys/src/9/pc/mp.c:446,466 – 1998/0605/sys/src/9/pc/mp.c:454,459 | ||
| 1997/0327 | nvramwrite(0x0F, 0x00); } | |
| 1998/0401 |
| |
| 1997/0327 | void mpinit(void) { | |
| 1998/0401/sys/src/9/pc/mp.c:568,576 – 1998/0605/sys/src/9/pc/mp.c:561,566 | ||
| 1997/0327 | */ if(conf.nmach > 1) conf.copymode = 1; | |
| 1998/0401 |
| |
| 1997/0327 | } static int | |
| 1998/0401/sys/src/9/pc/mp.c:695,709 – 1998/0605/sys/src/9/pc/mp.c:685,699 | ||
| 1998/0320 | return -1; | |
| 1997/0327 | } | |
| 1998/0605 | static Lock mpshutdownlock; | |
| 1997/0327 | void mpshutdown(void) { | |
| 1998/0401 |
| |
| 1997/0327 | /* * To be done... */ | |
| 1998/0605 | if(!canlock(&mpshutdownlock)){ | |
| 1997/0327 | /* * If this processor received the CTRL-ALT-DEL from * the keyboard, acknowledge it. Send an INIT to self. | |
| 1998/0401/sys/src/9/pc/mp.c:710,728 – 1998/0605/sys/src/9/pc/mp.c:700,709 | ||
| 1997/0327 | */ if(lapicisr(VectorKBD)) lapiceoi(VectorKBD); | |
| 1998/0401 |
| |
| 1997/0327 | delay(1000); splhi(); | |
| 1998/0605/sys/src/9/pc/mp.c:354,362 – 1998/0716/sys/src/9/pc/mp.c:354,364 (short | long) | ||
| 1997/0327 | static void squidboy(Apic* apic) { | |
| 1997/1101 | // iprint("Hello Squidboy\n"); | |
| 1998/0716 | /* synchronize cycle clocks */ wrmsr(0x10, m->clockstart); | |
| 1997/0327 | machinit(); mmuinit(); | |
| 1998/0605/sys/src/9/pc/mp.c:374,381 – 1998/0716/sys/src/9/pc/mp.c:376,383 | ||
| 1997/0327 | while(MACHP(0)->ticks == 0) ; | |
| 1998/0716 | lapicinit(apic); lapiconline(); | |
| 1997/0327 | lock(&active); active.machs |= 1<<m->machno; | |
| 1998/0605/sys/src/9/pc/mp.c:441,446 – 1998/0716/sys/src/9/pc/mp.c:443,449 | ||
| 1997/0327 | *p = i>>8; nvramwrite(0x0F, 0x0A); | |
| 1998/0716 | rdmsr(0x10, &mach->clockstart); | |
| 1997/0327 | lapicstartap(apic, PADDR(APBOOTSTRAP)); | |
| 1997/0521 | for(i = 0; i < 100000; i++){ lock(&mprdthilock); | |
| 1998/0605/sys/src/9/pc/mp.c:460,466 – 1998/0716/sys/src/9/pc/mp.c:463,468 | ||
| 1997/0327 | PCMP *pcmp; uchar *e, *p; | |
| 1997/0405 | Apic *apic, *bpapic; | |
| 1997/0327 |
| |
| 1998/0605/sys/src/9/pc/mp.c:529,535 – 1998/0716/sys/src/9/pc/mp.c:531,537 | ||
| 1997/0405 | if(bpapic == 0) return; | |
| 1997/0327 | ||
| 1997/0405 |
| |
| 1998/0716 | lapicinit(bpapic); | |
| 1997/0405 | lock(&mprdthilock); mprdthi |= (1<<bpapic->apicno)<<24; unlock(&mprdthilock); | |
| 1998/0605/sys/src/9/pc/mp.c:542,548 – 1998/0716/sys/src/9/pc/mp.c:544,550 | ||
| 1997/0405 | intrenable(VectorTIMER, clockintr, 0, BUSUNKNOWN); intrenable(VectorERROR, lapicerror, 0, BUSUNKNOWN); intrenable(VectorSPURIOUS, lapicspurious, 0, BUSUNKNOWN); | |
| 1998/0716 | lapiconline(); | |
| 1997/0327 | ||
| 1998/0401 | checkmtrr(); | |
| 1998/0716/sys/src/9/pc/mp.c:356,364 – 1998/0717/sys/src/9/pc/mp.c:356,361 (short | long) | ||
|
Change clock synchronization mechanism: stomp on TSC while looping.
rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/0327 | { | |
| 1997/1101 | // iprint("Hello Squidboy\n"); | |
| 1998/0716 |
| |
| 1997/0327 | machinit(); mmuinit(); | |
| 1998/0716/sys/src/9/pc/mp.c:374,380 – 1998/0717/sys/src/9/pc/mp.c:371,377 | ||
| 1997/0327 | * Restrain your octopus! Don't let it go out on the sea! */ while(MACHP(0)->ticks == 0) | |
| 1998/0717 | wrmsr(0x10, MACHP(0)->fastclock); /* synchronize fast counters */ | |
| 1997/0327 | ||
| 1998/0716 | lapicinit(apic); lapiconline(); | |
| 1998/0716/sys/src/9/pc/mp.c:443,449 – 1998/0717/sys/src/9/pc/mp.c:440,445 | ||
| 1997/0327 | *p = i>>8; nvramwrite(0x0F, 0x0A); | |
| 1998/0716 |
| |
| 1997/0327 | lapicstartap(apic, PADDR(APBOOTSTRAP)); | |
| 1997/0521 | for(i = 0; i < 100000; i++){ lock(&mprdthilock); | |
| 1998/0717/sys/src/9/pc/mp.c:483,488 – 1998/0729/sys/src/9/pc/mp.c:483,496 (short | long) | ||
| 1997/0327 | e = ((uchar*)pcmp)+pcmp->length; while(p < e) switch(*p){ | |
| 1998/0729 | default: print("mpinit: unknown PCMP type 0x%uX (e-p 0x%uX)\n", *p, e-p); while(p < e){ print("%uX ", *p); p++; } break; | |
| 1997/0327 | case PcmpPROCESSOR: if(apic = mkprocessor((PCMPprocessor*)p)){ /* | |
| 1998/0729/sys/src/9/pc/mp.c:484,490 – 1998/0825/sys/src/9/pc/mp.c:484,490 (short | long) | ||
|
Bug fix: print format.
rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/0327 | while(p < e) switch(*p){ | |
| 1998/0729 | default: | |
| 1998/0825 | print("mpinit: unknown PCMP type 0x%uX (e-p 0x%luX)\n", *p, e-p); | |
| 1998/0729 | while(p < e){ print("%uX ", *p); p++; | |
| 1998/0825/sys/src/9/pc/mp.c:19,24 – 1998/0910/sys/src/9/pc/mp.c:19,25 (short | long) | ||
|
XXX big interrupt change with vctl.
rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/0327 | static int machno2apicno[MaxAPICNO+1]; /* inverse map: machno -> APIC ID */ static Lock mprdthilock; static int mprdthi; | |
| 1998/0910 | static Ref mpvnoref; /* unique vector assignment */ | |
| 1997/0327 | static char* buses[] = { "CBUSI ", | |
| 1998/0825/sys/src/9/pc/mp.c:54,60 – 1998/0910/sys/src/9/pc/mp.c:55,60 | ||
| 1997/0327 | apic->type = PcmpPROCESSOR; apic->apicno = p->apicno; apic->flags = p->flags; | |
| 1998/0825/sys/src/9/pc/mp.c:183,189 – 1998/0910/sys/src/9/pc/mp.c:183,189 | ||
| 1997/0327 | } static int | |
| 1998/0910 | mpintrinit(Bus* bus, PCMPintr* intr, int vno) | |
| 1997/0327 | { int el, po, v; | |
| 1998/0825/sys/src/9/pc/mp.c:191,197 – 1998/0910/sys/src/9/pc/mp.c:191,197 | ||
| 1997/0327 | * Parse an I/O or Local APIC interrupt table entry and * return the encoded vector. */ | |
| 1998/0910 | v = vno; | |
| 1997/0327 | ||
| 1997/0405 | po = intr->flags & PcmpPOMASK; el = intr->flags & PcmpELMASK; | |
| 1998/0825/sys/src/9/pc/mp.c:230,236 – 1998/0910/sys/src/9/pc/mp.c:230,236 | ||
| 1997/0327 | /* */ | |
| 1998/0910 | if(bus->type == BusEISA && !po && !el){ | |
| 1997/0327 | po = PcmpHIGH; el = PcmpEDGE; } | |
| 1998/0825/sys/src/9/pc/mp.c:265,272 – 1998/0910/sys/src/9/pc/mp.c:265,270 | ||
| 1997/0327 | /* * The offsets of vectors for LINT[01] are known to be * 0 and 1 from the local APIC vector space at VectorLAPIC. | |
| 1998/0825/sys/src/9/pc/mp.c:274,280 – 1998/0910/sys/src/9/pc/mp.c:272,278 | ||
| 1997/0327 | ||
| 1998/0605 | /* * Pentium Pros have problems if LINT[01] are set to ExtINT | |
| 1998/0910 | * so just bag it, SMP mode shouldn't need ExtINT anyway. | |
| 1998/0605 | */ if(p->intr == PcmpExtINT || p->intr == PcmpNMI) v = ApicIMASK; | |
| 1998/0825/sys/src/9/pc/mp.c:545,553 – 1998/0910/sys/src/9/pc/mp.c:543,551 | ||
| 1997/0405 | * and do not appear in the I/O APIC so it is OK * to set them now. */ | |
| 1998/0910 | intrenable(IrqTIMER, clockintr, 0, BUSUNKNOWN); intrenable(IrqERROR, lapicerror, 0, BUSUNKNOWN); intrenable(IrqSPURIOUS, lapicspurious, 0, BUSUNKNOWN); | |
| 1998/0716 | lapiconline(); | |
| 1997/0327 | ||
| 1998/0401 | checkmtrr(); | |
| 1998/0825/sys/src/9/pc/mp.c:570,591 – 1998/0910/sys/src/9/pc/mp.c:568,590 | ||
| 1997/0327 | } static int | |
| 1998/0910 | mpintrenablex(Vctl* v) | |
| 1997/0327 | { Bus *bus; Aintr *aintr; Apic *apic; | |
| 1998/0910 | Pcidev *pcidev; int bno, dno, irq, lo, n, type, vno; | |
| 1997/0327 | /* * Find the bus, default is ISA. * There cannot be multiple ISA or EISA buses. */ | |
| 1998/0320 |
| |
| 1998/0910 | type = BUSTYPE(v->tbdf); bno = BUSBNO(v->tbdf); dno = BUSDNO(v->tbdf); | |
| 1997/0327 | n = 0; | |
| 1998/0910 | for(bus = mpbus; bus != nil; bus = bus->next){ | |
| 1997/0327 | if(bus->type != type) continue; if(n == bno) | |
| 1998/0825/sys/src/9/pc/mp.c:592,630 – 1998/0910/sys/src/9/pc/mp.c:591,662 | ||
| 1997/0327 | break; n++; } | |
| 1998/0910 | if(bus == nil){ | |
| 1998/0320 | print("ioapicirq: can't find bus type %d\n", type); return -1; | |
| 1997/0327 | } /* | |
| 1998/0910 | * For PCI devices the interrupt pin (INT[ABCD]) and device * number are encoded into the entry irq field, so create something * to match on. The interrupt pin used by the device has to be * obtained from the PCI config space. | |
| 1997/0327 | */ | |
| 1998/0910 | if(bus->type == BusPCI){ pcidev = pcimatchtbdf(v->tbdf); if(pcidev != nil && (n = pcicfgr8(pcidev, PciINTP)) != 0) irq = (dno<<2)|(n-1); else irq = -1; //print("pcidev %uX: irq %uX v->irq %uX\n", v->tbdf, irq, v->irq); } else irq = v->irq; /* * Find a matching interrupt entry from the list of interrupts * attached to this bus. */ | |
| 1997/0327 | for(aintr = bus->aintr; aintr; aintr = aintr->next){ | |
| 1998/0320 |
| |
| 1998/0910 | if(aintr->intr->irq != irq) continue; /* * Check not already enabled. This is a bad thing as it implies the * same device is requesting the same interrupt to be enabled multiple * times. The RDT read here is safe for now as currently interrupts * are never disabled once enabled. */ apic = aintr->apic; ioapicrdtr(apic, aintr->intr->intin, 0, &lo); if(!(lo & ApicIMASK)){ print("mpintrenable: multiple enable of irq %d, tbdf %uX\n", v->irq, v->tbdf); return -1; | |
| 1997/0327 | } | |
| 1998/0910 | /* * With the APIC a unique vector can be assigned to each request * to enable an interrupt. There are two reasons this is a good idea: * 1) to prevent lost interrupts, no more than 2 interrupts should * be assigned per block of 16 vectors (there is an in-service * entry and a holding entry for each priority level and there is * a priority level per block of 16 interrupts). * 2) each input pin on the IOAPIC will receive a different vector * regardless of whether the devices on that pin use the same IRQ * as devices on another pin. */ vno = VectorAPIC + (incref(&mpvnoref)-1)*8; if(vno > MaxVectorAPIC){ print("mpintrenable: vno %d, irq %d, tbdf %uX\n", vno, v->irq, v->tbdf); return -1; } lo = mpintrinit(bus, aintr->intr, vno); | |
| 1997/0327 | if(lo & ApicIMASK) return -1; lo |= ApicLOGICAL; | |
| 1998/0825/sys/src/9/pc/mp.c:631,641 – 1998/0910/sys/src/9/pc/mp.c:663,672 | ||
| 1997/0327 | unlock(&mprdthilock); } | |
| 1998/0910 | v->isr = lapicisr; v->eoi = lapiceoi; | |
| 1997/0327 |
| |
| 1998/0910 | return vno; | |
| 1997/0327 | } return -1; | |
| 1998/0825/sys/src/9/pc/mp.c:642,650 – 1998/0910/sys/src/9/pc/mp.c:673,681 | ||
| 1997/0327 | } int | |
| 1998/0910 | mpintrenable(Vctl* v) | |
| 1997/0327 | { | |
| 1998/0910 | int irq, tbdf, vno; | |
| 1997/0327 | ||
| 1998/0320 | /* * If the bus is known, try it. | |
| 1998/0825/sys/src/9/pc/mp.c:652,674 – 1998/0910/sys/src/9/pc/mp.c:683,706 | ||
| 1998/0320 | * interrupts local to the processor (local APIC, coprocessor * breakpoint and page-fault). */ | |
| 1998/0910 | tbdf = v->tbdf; if(tbdf != BUSUNKNOWN && (vno = mpintrenablex(v)) != -1) return vno; | |
| 1998/0320 |
| |
| 1998/0910 | irq = v->irq; if(irq >= IrqLINT0 && irq <= MaxIrqLAPIC){ if(irq != IrqSPURIOUS) v->isr = lapiceoi; return VectorPIC+irq; | |
| 1998/0320 | } | |
| 1998/0910 | if(irq < 0 || irq > MaxIrqPIC){ print("mpintrenable: irq %d out of range\n", irq); | |
| 1998/0320 | return -1; } /* | |
| 1998/0910 | * Either didn't find it or have to try the default buses * (ISA and EISA). This hack is due to either over-zealousness | |
| 1998/0320 | * or laziness on the part of some manufacturers. * * The MP configuration table on some older systems | |
| 1998/0825/sys/src/9/pc/mp.c:678,691 – 1998/0910/sys/src/9/pc/mp.c:710,725 | ||
| 1998/0320 | * be compatible with ISA. */ if(mpisabus != -1){ | |
| 1998/0910 | v->tbdf = MKBUS(BusISA, 0, 0, 0); vno = mpintrenablex(v); if(vno != -1) return vno; | |
| 1998/0320 | } if(mpeisabus != -1){ | |
| 1998/0910 | v->tbdf = MKBUS(BusEISA, 0, 0, 0); vno = mpintrenablex(v); if(vno != -1) return vno; | |
| 1998/0320 | } return -1; | |
| 1998/0825/sys/src/9/pc/mp.c:704,711 – 1998/0910/sys/src/9/pc/mp.c:738,747 | ||
| 1997/0327 | * If this processor received the CTRL-ALT-DEL from * the keyboard, acknowledge it. Send an INIT to self. */ | |
| 1998/0910 | #ifdef FIXTHIS | |
| 1997/0327 | if(lapicisr(VectorKBD)) lapiceoi(VectorKBD); | |
| 1998/0910 | #endif /* FIX THIS */ | |
| 1997/0327 | idle(); } | |
| 1998/0910/sys/src/9/pc/mp.c:9,16 – 1998/1021/sys/src/9/pc/mp.c:9,14 (short | long) | ||
| 1997/0327 | #include "mp.h" #include "apbootstrap.h" | |
| 1998/0320 | static int mpisabus = -1; | |
| 1998/1021/sys/src/9/pc/mp.c:13,18 – 1998/1022/sys/src/9/pc/mp.c:13,19 (short | long) | ||
| 1997/0327 | static Bus* mpbuslast; | |
| 1998/0320 | static int mpisabus = -1; static int mpeisabus = -1; | |
| 1998/1022 | extern int elcr; /* mask of level-triggered interrupts */ | |
| 1997/0327 | static Apic mpapic[MaxAPICNO+1]; static int machno2apicno[MaxAPICNO+1]; /* inverse map: machno -> APIC ID */ static Lock mprdthilock; | |
| 1998/1021/sys/src/9/pc/mp.c:181,187 – 1998/1022/sys/src/9/pc/mp.c:182,188 | ||
| 1997/0327 | } static int | |
| 1998/0910 |
| |
| 1998/1022 | mpintrinit(Bus* bus, PCMPintr* intr, int vno, int /*irq*/) | |
| 1997/0327 | { int el, po, v; | |
| 1998/1021/sys/src/9/pc/mp.c:228,234 – 1998/1022/sys/src/9/pc/mp.c:229,235 | ||
| 1997/0327 | /* */ | |
| 1998/0910 |
| |
| 1998/1022 | if(bus->type == BusEISA && !po && !el /*&& !(elcr & (1<<irq))*/){ | |
| 1997/0327 | po = PcmpHIGH; el = PcmpEDGE; } | |
| 1998/1021/sys/src/9/pc/mp.c:275,281 – 1998/1022/sys/src/9/pc/mp.c:276,282 | ||
| 1998/0605 | if(p->intr == PcmpExtINT || p->intr == PcmpNMI) v = ApicIMASK; else | |
| 1998/1022 | v = mpintrinit(bus, p, VectorLAPIC+intin, p->irq); | |
| 1998/0605 | ||
| 1997/0327 | if(p->apicno == 0xFF){ for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){ | |
| 1998/1021/sys/src/9/pc/mp.c:650,656 – 1998/1022/sys/src/9/pc/mp.c:651,657 | ||
| 1998/0910 | vno, v->irq, v->tbdf); return -1; } | |
| 1998/1022 | lo = mpintrinit(bus, aintr->intr, vno, v->irq); | |
| 1997/0327 | if(lo & ApicIMASK) return -1; lo |= ApicLOGICAL; | |
| 1998/1022/sys/src/9/pc/mp.c:13,19 – 1999/0301/sys/src/9/pc/mp.c:13,19 (short | long) | ||
| 1997/0327 | static Bus* mpbuslast; | |
| 1998/0320 | static int mpisabus = -1; static int mpeisabus = -1; | |
| 1998/1022 |
| |
| 1999/0301 | extern int i8259elcr; /* mask of level-triggered interrupts */ | |
| 1997/0327 | static Apic mpapic[MaxAPICNO+1]; static int machno2apicno[MaxAPICNO+1]; /* inverse map: machno -> APIC ID */ static Lock mprdthilock; | |
| 1999/0301/sys/src/9/pc/mp.c:351,356 – 1999/0310/sys/src/9/pc/mp.c:351,358 (short | long) | ||
| 1997/0327 | static void squidboy(Apic* apic) { | |
| 1999/0310 | ulong x; | |
| 1997/1101 | // iprint("Hello Squidboy\n"); | |
| 1998/0716 | ||
| 1997/0327 | machinit(); | |
| 1999/0301/sys/src/9/pc/mp.c:367,374 – 1999/0310/sys/src/9/pc/mp.c:369,380 | ||
| 1997/0327 | /* * Restrain your octopus! Don't let it go out on the sea! */ | |
| 1998/0717 |
| |
| 1999/0310 | lock(&active); x = MACHP(0)->ticks; while(MACHP(0)->ticks == x) ; wrmsr(0x10, MACHP(0)->fastclock); /* synchronize fast counters */ unlock(&active); | |
| 1997/0327 | ||
| 1998/0716 | lapicinit(apic); lapiconline(); | |
| 1999/0310/sys/src/9/pc/mp.c:348,353 – 1999/0320/sys/src/9/pc/mp.c:348,355 (short | long) | ||
| 1997/0327 | #define PDX(va) ((((ulong)(va))>>22) & 0x03FF) #define PTX(va) ((((ulong)(va))>>12) & 0x03FF) | |
| 1999/0320 | Lock clocksynclock; | |
| 1997/0327 | static void squidboy(Apic* apic) { | |
| 1999/0310/sys/src/9/pc/mp.c:369,380 – 1999/0320/sys/src/9/pc/mp.c:371,382 | ||
| 1997/0327 | /* * Restrain your octopus! Don't let it go out on the sea! */ | |
| 1999/0310 |
| |
| 1999/0320 | ilock(&clocksynclock); | |
| 1999/0310 | x = MACHP(0)->ticks; while(MACHP(0)->ticks == x) ; wrmsr(0x10, MACHP(0)->fastclock); /* synchronize fast counters */ | |
| 1999/0320 | iunlock(&clocksynclock); | |
| 1997/0327 | ||
| 1998/0716 | lapicinit(apic); lapiconline(); | |
| 1999/0320/sys/src/9/pc/mp.c:19,24 – 1999/0402/sys/src/9/pc/mp.c:19,25 (short | long) | ||
| 1997/0327 | static Lock mprdthilock; static int mprdthi; | |
| 1998/0910 | static Ref mpvnoref; /* unique vector assignment */ | |
| 1999/0402 | static Lock mpclocksynclock; | |
| 1997/0327 | static char* buses[] = { "CBUSI ", | |
| 1999/0320/sys/src/9/pc/mp.c:214,226 – 1999/0402/sys/src/9/pc/mp.c:215,228 | ||
| 1997/0327 | case PcmpExtINT: v |= ApicExtINT; | |
| 1997/0524 | /* | |
| 1999/0402 | * The AMI Goliath doesn't boot successfully with it's LINTR0 * entry which decodes to low+level. The PPro manual says ExtINT * should be level, whereas the Pentium is edge. Setting the * Goliath to edge+high seems to cure the problem. Other PPro * MP tables (e.g. ASUS P/I-P65UP5 have a entry which decodes * to edge+high, so who knows. * Perhaps it would be best just to not set an ExtINT entry at * all, it shouldn't be needed for SMP mode. | |
| 1997/0524 | */ po = PcmpHIGH; el = PcmpEDGE; | |
| 1999/0320/sys/src/9/pc/mp.c:229,235 – 1999/0402/sys/src/9/pc/mp.c:231,237 | ||
| 1997/0327 | /* */ | |
| 1998/1022 |
| |
| 1999/0402 | if(bus->type == BusEISA && !po && !el /*&& !(i8259elcr & (1<<irq))*/){ | |
| 1997/0327 | po = PcmpHIGH; el = PcmpEDGE; } | |
| 1999/0320/sys/src/9/pc/mp.c:280,286 – 1999/0402/sys/src/9/pc/mp.c:282,289 | ||
| 1998/0605 | ||
| 1997/0327 | if(p->apicno == 0xFF){ for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){ | |
| 1999/0402 | if((apic->flags & PcmpEN) && apic->type == PcmpPROCESSOR) | |
| 1997/0327 | apic->lintr[intin] = v; } } | |
| 1999/0320/sys/src/9/pc/mp.c:348,355 – 1999/0402/sys/src/9/pc/mp.c:351,356 | ||
| 1997/0327 | #define PDX(va) ((((ulong)(va))>>22) & 0x03FF) #define PTX(va) ((((ulong)(va))>>12) & 0x03FF) | |
| 1999/0320 |
| |
| 1997/0327 | static void squidboy(Apic* apic) { | |
| 1999/0320/sys/src/9/pc/mp.c:371,382 – 1999/0402/sys/src/9/pc/mp.c:372,383 | ||
| 1997/0327 | /* * Restrain your octopus! Don't let it go out on the sea! */ | |
| 1999/0320 |
| |
| 1999/0402 | ilock(&mpclocksynclock); | |
| 1999/0310 | x = MACHP(0)->ticks; while(MACHP(0)->ticks == x) ; wrmsr(0x10, MACHP(0)->fastclock); /* synchronize fast counters */ | |
| 1999/0320 |
| |
| 1999/0402 | iunlock(&mpclocksynclock); | |
| 1997/0327 | ||
| 1998/0716 | lapicinit(apic); lapiconline(); | |
| 1999/0320/sys/src/9/pc/mp.c:480,488 – 1999/0402/sys/src/9/pc/mp.c:481,489 | ||
| 1997/0405 | bpapic = 0; | |
| 1997/0327 | /* | |
| 1999/0402 | * 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. | |
| 1997/0327 | */ p = ((uchar*)pcmp)+sizeof(PCMP); e = ((uchar*)pcmp)+pcmp->length; | |
| 1999/0320/sys/src/9/pc/mp.c:489,495 – 1999/0402/sys/src/9/pc/mp.c:490,497 | ||
| 1997/0327 | while(p < e) switch(*p){ | |
| 1998/0729 | default: | |
| 1998/0825 |
| |
| 1999/0402 | print("mpinit: unknown PCMP type 0x%uX (e-p 0x%luX)\n", *p, e-p); | |
| 1998/0729 | while(p < e){ print("%uX ", *p); p++; | |
| 1999/0320/sys/src/9/pc/mp.c:562,568 – 1999/0402/sys/src/9/pc/mp.c:564,571 | ||
| 1997/0405 | */ memmove((void*)APBOOTSTRAP, apbootstrap, sizeof(apbootstrap)); for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){ | |
| 1999/0402 | if((apic->flags & (PcmpBP|PcmpEN)) == PcmpEN && apic->type == PcmpPROCESSOR) | |
| 1997/0405 | mpstartap(apic); | |
| 1997/0327 | } | |
| 1999/0320/sys/src/9/pc/mp.c:575,581 – 1999/0402/sys/src/9/pc/mp.c:578,584 | ||
| 1997/0327 | } static int | |
| 1998/0910 |
| |
| 1999/0402 | mpintrenablex(Vctl* v, int tbdf) | |
| 1997/0327 | { Bus *bus; Aintr *aintr; | |
| 1999/0320/sys/src/9/pc/mp.c:584,595 – 1999/0402/sys/src/9/pc/mp.c:587,597 | ||
| 1998/0910 | int bno, dno, irq, lo, n, type, vno; | |
| 1997/0327 | /* | |
| 1999/0402 | * Find the bus. | |
| 1997/0327 | */ | |
| 1998/0910 |
| |
| 1999/0402 | type = BUSTYPE(tbdf); bno = BUSBNO(tbdf); dno = BUSDNO(tbdf); | |
| 1997/0327 | n = 0; | |
| 1998/0910 | for(bus = mpbus; bus != nil; bus = bus->next){ | |
| 1997/0327 | if(bus->type != type) | |
| 1999/0320/sys/src/9/pc/mp.c:610,621 – 1999/0402/sys/src/9/pc/mp.c:612,623 | ||
| 1998/0910 | * obtained from the PCI config space. | |
| 1997/0327 | */ | |
| 1998/0910 | if(bus->type == BusPCI){ | |
| 1999/0402 | pcidev = pcimatchtbdf(tbdf); | |
| 1998/0910 | if(pcidev != nil && (n = pcicfgr8(pcidev, PciINTP)) != 0) irq = (dno<<2)|(n-1); else irq = -1; | |
| 1999/0402 | //print("pcidev %uX: irq %uX v->irq %uX\n", tbdf, irq, v->irq); | |
| 1998/0910 | } else irq = v->irq; | |
| 1999/0320/sys/src/9/pc/mp.c:629,665 – 1999/0402/sys/src/9/pc/mp.c:631,672 | ||
| 1998/0910 | continue; /* | |
| 1999/0402 | * Check not already enabled. This is a bad thing as it implies * the same device is requesting the same interrupt to be * enabled multiple times. The RDT read here is safe for now * as currently interrupts are never disabled once enabled. | |
| 1998/0910 | */ apic = aintr->apic; ioapicrdtr(apic, aintr->intr->intin, 0, &lo); if(!(lo & ApicIMASK)){ | |
| 1999/0402 | print("mpintrenable: multiple enable irq%d, tbdf %uX\n", v->irq, tbdf); | |
| 1998/0910 | return -1; | |
| 1997/0327 | } | |
| 1998/0910 | /* | |
| 1999/0402 | * With the APIC a unique vector can be assigned to each * request to enable an interrupt. There are two reasons this * is a good idea: * 1) to prevent lost interrupts, no more than 2 interrupts * should be assigned per block of 16 vectors (there is an * in-service entry and a holding entry for each priority * level and there is one priority level per block of 16 * interrupts). * 2) each input pin on the IOAPIC will receive a different * vector regardless of whether the devices on that pin use * the same IRQ as devices on another pin. | |
| 1998/0910 | */ vno = VectorAPIC + (incref(&mpvnoref)-1)*8; if(vno > MaxVectorAPIC){ print("mpintrenable: vno %d, irq %d, tbdf %uX\n", | |
| 1999/0402 | vno, v->irq, tbdf); | |
| 1998/0910 | return -1; } | |
| 1998/1022 | lo = mpintrinit(bus, aintr->intr, vno, v->irq); | |
| 1999/0402 | //print("lo 0x%uX: busno %d intr %d vno %d irq %d elcr 0x%uX\n", // lo, bus->busno, aintr->intr->irq, vno, // v->irq, i8259elcr); | |
| 1997/0327 | if(lo & ApicIMASK) return -1; lo |= ApicLOGICAL; | |
| 1999/0320/sys/src/9/pc/mp.c:669,674 – 1999/0402/sys/src/9/pc/mp.c:676,684 | ||
| 1997/0327 | ioapicrdtw(apic, aintr->intr->intin, mprdthi, lo); unlock(&mprdthilock); } | |
| 1999/0402 | //else // print("lo not enabled 0x%uX %d\n", // apic->flags, apic->type); | |
| 1997/0327 | ||
| 1998/0910 | v->isr = lapicisr; v->eoi = lapiceoi; | |
| 1999/0320/sys/src/9/pc/mp.c:691,697 – 1999/0402/sys/src/9/pc/mp.c:701,707 | ||
| 1998/0320 | * breakpoint and page-fault). */ | |
| 1998/0910 | tbdf = v->tbdf; | |
| 1999/0402 | if(tbdf != BUSUNKNOWN && (vno = mpintrenablex(v, tbdf)) != -1) | |
| 1998/0910 | return vno; | |
| 1998/0320 | ||
| 1998/0910 | irq = v->irq; | |
| 1999/0320/sys/src/9/pc/mp.c:716,730 – 1999/0402/sys/src/9/pc/mp.c:726,738 | ||
| 1998/0320 | * polarity set to 'default for this bus' which wouldn't * be compatible with ISA. */ | |
| 1998/0910 |
| |
| 1999/0402 | if(mpeisabus != -1){ vno = mpintrenablex(v, MKBUS(BusEISA, 0, 0, 0)); | |
| 1998/0910 | if(vno != -1) return vno; | |
| 1998/0320 | } | |
| 1998/0910 |
| |
| 1999/0402 | if(mpisabus != -1){ vno = mpintrenablex(v, MKBUS(BusISA, 0, 0, 0)); | |
| 1998/0910 | if(vno != -1) return vno; | |
| 1998/0320 | } | |
| 1999/0320/sys/src/9/pc/mp.c:767,773 – 1999/0402/sys/src/9/pc/mp.c:775,781 | ||
| 1997/0327 | * warm-boot sequence is tried. The following is Intel specific and * seems to perform a cold-boot, but at least it comes back. */ | |
| 1997/1101 |
| |
| 1999/0402 | *(ushort*)KADDR(0x472) = 0x1234; /* BIOS warm-boot flag */ | |
| 1997/0327 | outb(0xCF9, 0x02); outb(0xCF9, 0x06); #else | |
| 1999/0402/sys/src/9/pc/mp.c:552,560 – 1999/0819/sys/src/9/pc/mp.c:552,560 (short | long) | ||
| 1997/0405 | * and do not appear in the I/O APIC so it is OK * to set them now. */ | |
| 1998/0910 |
| |
| 1999/0819 | intrenable(IrqTIMER, clockintr, 0, BUSUNKNOWN, "clock"); intrenable(IrqERROR, lapicerror, 0, BUSUNKNOWN, "lapicerror"); intrenable(IrqSPURIOUS, lapicspurious, 0, BUSUNKNOWN, "lapicspurious"); | |
| 1998/0716 | lapiconline(); | |
| 1997/0327 | ||
| 1998/0401 | checkmtrr(); | |
| 1999/0819/sys/src/9/pc/mp.c:462,467 – 2001/0127/sys/src/9/pc/mp.c:462,469 (short | long) | ||
| 1997/0327 | void mpinit(void) { | |
| 2001/0127 | int ncpu; char *cp; | |
| 1997/0327 | PCMP *pcmp; uchar *e, *p; | |
| 1997/0405 | Apic *apic, *bpapic; | |
| 1999/0819/sys/src/9/pc/mp.c:562,572 – 2001/0127/sys/src/9/pc/mp.c:564,585 | ||
| 1997/0405 | /* * Initialise the application processors. */ | |
| 2001/0127 | if(cp = getconf("*ncpu")){ ncpu = strtol(cp, 0, 0); if(ncpu < 1) ncpu = 1; } else ncpu = MaxAPICNO; | |
| 1997/0405 | memmove((void*)APBOOTSTRAP, apbootstrap, sizeof(apbootstrap)); for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){ | |
| 2001/0127 | if(ncpu <= 1) break; | |
| 1999/0402 | if((apic->flags & (PcmpBP|PcmpEN)) == PcmpEN | |
| 2001/0127 | && apic->type == PcmpPROCESSOR){ | |
| 1997/0405 | mpstartap(apic); | |
| 2001/0127 | ncpu--; } | |
| 1997/0327 | } /* | |
| 2001/0127/sys/src/9/pc/mp.c:462,469 – 2001/0527/sys/src/9/pc/mp.c:462,467 (short | long) | ||
| 1997/0327 | void mpinit(void) { | |
| 2001/0127 |
| |
| 1997/0327 | PCMP *pcmp; uchar *e, *p; | |
| 1997/0405 | Apic *apic, *bpapic; | |
| 2001/0127/sys/src/9/pc/mp.c:564,585 – 2001/0527/sys/src/9/pc/mp.c:562,572 | ||
| 1997/0405 | /* * Initialise the application processors. */ | |
| 2001/0127 |
| |
| 1997/0405 | memmove((void*)APBOOTSTRAP, apbootstrap, sizeof(apbootstrap)); for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){ | |
| 2001/0127 |
| |
| 1999/0402 | if((apic->flags & (PcmpBP|PcmpEN)) == PcmpEN | |
| 2001/0127 |
| |
| 2001/0527 | && apic->type == PcmpPROCESSOR) | |
| 1997/0405 | mpstartap(apic); | |
| 2001/0127 |
| |
| 1997/0327 | } /* | |
| 2001/0527/sys/src/9/pc/mp.c:462,467 – 2001/0830/sys/src/9/pc/mp.c:462,469 (short | long) | ||
| 1997/0327 | void mpinit(void) { | |
| 2001/0830 | int ncpu; char *cp; | |
| 1997/0327 | PCMP *pcmp; uchar *e, *p; | |
| 1997/0405 | Apic *apic, *bpapic; | |
| 2001/0527/sys/src/9/pc/mp.c:562,572 – 2001/0830/sys/src/9/pc/mp.c:564,585 | ||
| 1997/0405 | /* * Initialise the application processors. */ | |
| 2001/0830 | if(cp = getconf("*ncpu")){ ncpu = strtol(cp, 0, 0); if(ncpu < 1) ncpu = 1; } else ncpu = MaxAPICNO; | |
| 1997/0405 | memmove((void*)APBOOTSTRAP, apbootstrap, sizeof(apbootstrap)); for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){ | |
| 2001/0830 | if(ncpu <= 1) break; | |
| 1999/0402 | if((apic->flags & (PcmpBP|PcmpEN)) == PcmpEN | |
| 2001/0527 |
| |
| 2001/0830 | && apic->type == PcmpPROCESSOR){ | |
| 1997/0405 | mpstartap(apic); | |
| 2001/0830 | ncpu--; } | |
| 1997/0327 | } /* | |
| 2001/0527/sys/src/9/pc/mp.c:631,647 – 2001/0830/sys/src/9/pc/mp.c:644,674 | ||
| 1998/0910 | continue; /* | |
| 1999/0402 |
| |
| 2001/0830 | * Check if already enabled. Multifunction devices may share * INT[A-D]# so, if already enabled, check the polarity matches * and the trigger is level. * * Should check the devices differ only in the function number, * but that can wait for the planned enable/disable rewrite. * The RDT read here is safe for now as currently interrupts * are never disabled once enabled. | |
| 1998/0910 | */ apic = aintr->apic; ioapicrdtr(apic, aintr->intr->intin, 0, &lo); if(!(lo & ApicIMASK)){ | |
| 1999/0402 |
| |
| 1998/0910 |
| |
| 2001/0830 | vno = lo & 0xFF; n = mpintrinit(bus, aintr->intr, vno, v->irq); n |= ApicLOGICAL; if(n != lo || !(n & ApicLEVEL)){ print("mpintrenable: multiple botch irq%d, tbdf %uX, lo %8.8uX, n %8.8uX\n", v->irq, tbdf, lo, n); return -1; } v->isr = lapicisr; v->eoi = lapiceoi; return vno; | |
| 1997/0327 | } | |
| 1998/0910 | /* | |
| 2001/0830/sys/src/9/pc/mp.c:348,356 – 2002/0109/sys/src/9/pc/mp.c:348,353 (short | long) | ||
| 1998/0401 | } } | |
| 1997/0327 |
| |
| 2002/0109/sys/src/9/pc/mp.c:43,48 – 2002/0404/sys/src/9/pc/mp.c:43,85 (short | long) | ||
| 1997/0327 | 0, }; | |
| 2002/0404 | void apicclkenable(void) { Apic *apic; i8259init(); /* Uniprocessor local apic init for apic clock */ apic = &mpapic[0]; apic->type = PcmpPROCESSOR; apic->apicno = 0; apic->flags = 0; apic->lintr[0] = ApicIMASK; apic->lintr[1] = ApicIMASK; apic->machno = 0; apic->addr = (ulong*)0xfee00000; machno2apicno[0] = 0; /* * Map the local APIC. */ if(mmukmap((ulong)apic->addr, 0, 1024) == 0) return; /* * 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, clockintr, 0, BUSUNKNOWN, "clock"); intrenable(IrqERROR, lapicerror, 0, BUSUNKNOWN, "lapicerror"); intrenable(IrqSPURIOUS, lapicspurious, 0, BUSUNKNOWN, "lapicspurious"); lapicinit(apic); lapiconline(); } | |
| 1997/0327 | static Apic* mkprocessor(PCMPprocessor* p) { | |
| Too many diffs (26 > 25). Stopping. | ||