X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=sys%2Fsrc%2F9%2Fpc%2Fmp.c;h=27eee1da670a4008fa0c9eb8f326346ee4b6a4ad;hb=97d136fb21aa6068825c4fda5a7936ba98743ac2;hp=b74fa12507b8672cccc97d692a7127e1067accdc;hpb=8e1fbbeda59186f50449ae31212632b00b328af6;p=plan9front.git diff --git a/sys/src/9/pc/mp.c b/sys/src/9/pc/mp.c index b74fa1250..27eee1da6 100644 --- a/sys/src/9/pc/mp.c +++ b/sys/src/9/pc/mp.c @@ -9,239 +9,15 @@ #include "mp.h" #include "apbootstrap.h" -static PCMP* mppcmp; -static Bus* mpbus; -static Bus* mpbuslast; -static int mpisabus = -1; -static int mpeisabus = -1; -extern int i8259elcr; /* mask of level-triggered interrupts */ -static Apic mpapic[MaxAPICNO+1]; -static int machno2apicno[MaxAPICNO+1]; /* inverse map: machno -> APIC ID */ -static int mpapicremap[MaxAPICNO+1]; -static int mpmachno = 1; -static Lock mpphysidlock; -static int mpphysid; - -static char* buses[] = { - "CBUSI ", - "CBUSII", - "EISA ", - "FUTURE", - "INTERN", - "ISA ", - "MBI ", - "MBII ", - "MCA ", - "MPI ", - "MPSA ", - "NUBUS ", - "PCI ", - "PCMCIA", - "TC ", - "VL ", - "VME ", - "XPRESS", - 0, -}; - -static Apic* -mkprocessor(PCMPprocessor* p) -{ - int apicno; - Apic *apic; - - apicno = p->apicno; - if(!(p->flags & PcmpEN) || apicno > MaxAPICNO) - return 0; - - apic = &mpapic[apicno]; - apic->type = PcmpPROCESSOR; - apic->apicno = apicno; - apic->flags = p->flags; - apic->lintr[0] = ApicIMASK; - apic->lintr[1] = ApicIMASK; - - if(p->flags & PcmpBP){ - machno2apicno[0] = apicno; - apic->machno = 0; - } - else{ - machno2apicno[mpmachno] = apicno; - apic->machno = mpmachno; - mpmachno++; - } - - return apic; -} - -static Bus* -mkbus(PCMPbus* p) -{ - Bus *bus; - int i; - - for(i = 0; buses[i]; i++){ - if(strncmp(buses[i], p->string, sizeof(p->string)) == 0) - break; - } - if(buses[i] == 0) - return 0; - - bus = xalloc(sizeof(Bus)); - if(mpbus) - mpbuslast->next = bus; - else - mpbus = bus; - mpbuslast = bus; - - bus->type = i; - bus->busno = p->busno; - if(bus->type == BusEISA){ - bus->po = PcmpLOW; - bus->el = PcmpLEVEL; - if(mpeisabus != -1) - print("mkbus: more than one EISA bus\n"); - mpeisabus = bus->busno; - } - else if(bus->type == BusPCI){ - bus->po = PcmpLOW; - bus->el = PcmpLEVEL; - } - 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; - } - else{ - bus->po = PcmpHIGH; - bus->el = PcmpEDGE; - } - - return bus; -} - -static Bus* -mpgetbus(int busno) -{ - Bus *bus; - - for(bus = mpbus; bus; bus = bus->next){ - if(bus->busno == busno) - return bus; - } - print("mpgetbus: can't find bus %d\n", busno); - - return 0; -} - -static int -freeapicid(void) -{ - int i; - - for(i = 0; i < MaxAPICNO+1; i++) - if(mpapic[i].flags == 0) - return i; - return -1; -} - -static Apic* -mkioapic(PCMPioapic* p) -{ - void *va; - int apicno, new; - Apic *apic; - - apicno = p->apicno; - if(!(p->flags & PcmpEN) || apicno > MaxAPICNO) - return 0; - - /* - * Map the I/O APIC. - */ - if((va = vmap(p->addr, 1024)) == nil) - return 0; - - apic = &mpapic[apicno]; - if(apic->flags != 0) { - new = freeapicid(); - if(new < 0) - print("mkioapic: out of APIC IDs\n"); - else { - mpapicremap[p->apicno] = new; - print("mkioapic: APIC ID conflict at %d, remapping to %d\n", p->apicno, new); - p->apicno = apicno = new; - apic = &mpapic[apicno]; - } - } else - mpapicremap[p->apicno] = p->apicno; - apic->type = PcmpIOAPIC; - apic->apicno = apicno; - apic->addr = va; - apic->paddr = p->addr; - apic->flags = p->flags; - - return apic; -} - -static Aintr* -mkiointr(PCMPintr* p) -{ - Bus *bus; - Aintr *aintr; - PCMPintr* pcmpintr; - - /* - * According to the MultiProcessor Specification, a destination - * I/O APIC of 0xFF means the signal is routed to all I/O APICs. - * It's unclear how that can possibly be correct so treat it as - * an error for now. - */ - if(p->apicno > MaxAPICNO) - return 0; - - if(mpapicremap[p->apicno] < 0) { - print("iointr: non-existing IOAPIC %d\n", p->apicno); - return 0; - } - p->apicno = mpapicremap[p->apicno]; - if((bus = mpgetbus(p->busno)) == 0) - return 0; - - aintr = xalloc(sizeof(Aintr)); - aintr->intr = p; - - if(0) - print("iointr: type %d intr type %d flags %#o " - "bus %d irq %d apicno %d intin %d\n", - p->type, p->intr, p->flags, - p->busno, p->irq, p->apicno, p->intin); - /* - * Hack for Intel SR1520ML motherboard, which BIOS describes - * the i82575 dual ethernet controllers incorrectly. - */ - if(memcmp(mppcmp->product, "INTEL X38MLST ", 20) == 0){ - if(p->busno == 1 && p->intin == 16 && p->irq == 1){ - pcmpintr = malloc(sizeof(PCMPintr)); - memmove(pcmpintr, p, sizeof(PCMPintr)); - print("mkiointr: %20.20s bus %d intin %d irq %d\n", - (char*)mppcmp->product, - pcmpintr->busno, pcmpintr->intin, - pcmpintr->irq); - pcmpintr->intin = 17; - aintr->intr = pcmpintr; - } - } - aintr->apic = &mpapic[p->apicno]; - aintr->next = bus->aintr; - bus->aintr = aintr; +/* filled in by pcmpinit or acpiinit */ +Bus* mpbus; +Bus* mpbuslast; +int mpisabus = -1; +int mpeisabus = -1; +Apic *mpioapic[MaxAPICNO+1]; +Apic *mpapic[MaxAPICNO+1]; - return aintr; -} - -static int +int mpintrinit(Bus* bus, PCMPintr* intr, int vno, int /*irq*/) { int el, po, v; @@ -256,7 +32,6 @@ mpintrinit(Bus* bus, PCMPintr* intr, int vno, int /*irq*/) el = intr->flags & PcmpELMASK; switch(intr->intr){ - default: /* PcmpINT */ v |= ApicFIXED; /* no-op */ break; @@ -315,46 +90,6 @@ mpintrinit(Bus* bus, PCMPintr* intr, int vno, int /*irq*/) return v; } -static int -mklintr(PCMPintr* p) -{ - Apic *apic; - Bus *bus; - int intin, v; - - /* - * The offsets of vectors for LINT[01] are known to be - * 0 and 1 from the local APIC vector space at VectorLAPIC. - */ - if((bus = mpgetbus(p->busno)) == 0) - return 0; - intin = p->intin; - - /* - * Pentium Pros have problems if LINT[01] are set to ExtINT - * so just bag it, SMP mode shouldn't need ExtINT anyway. - */ - if(p->intr == PcmpExtINT || p->intr == PcmpNMI) - v = ApicIMASK; - else - v = mpintrinit(bus, p, VectorLAPIC+intin, p->irq); - - if(p->apicno == 0xFF){ - for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){ - if((apic->flags & PcmpEN) - && apic->type == PcmpPROCESSOR) - apic->lintr[intin] = v; - } - } - else{ - apic = &mpapic[p->apicno]; - if((apic->flags & PcmpEN) && apic->type == PcmpPROCESSOR) - apic->lintr[intin] = v; - } - - return v; -} - static void checkmtrr(void) { @@ -364,7 +99,7 @@ checkmtrr(void) /* * If there are MTRR registers, snarf them for validation. */ - if(!(m->cpuiddx & 0x1000)) + if(!(m->cpuiddx & Mtrr)) return; rdmsr(0x0FE, &m->mtrrcap); @@ -407,6 +142,36 @@ checkmtrr(void) } } +uvlong +tscticks(uvlong *hz) +{ + if(hz != nil) + *hz = m->cpuhz; + + cycles(&m->tscticks); /* Uses the rdtsc instruction */ + return m->tscticks; +} + +void +syncclock(void) +{ + uvlong x; + + if(arch->fastclock != tscticks) + return; + + if(m->machno == 0){ + wrmsr(0x10, 0); + m->tscticks = 0; + } else { + x = MACHP(0)->tscticks; + while(x == MACHP(0)->tscticks) + ; + wrmsr(0x10, MACHP(0)->tscticks); + cycles(&m->tscticks); + } +} + static void squidboy(Apic* apic) { @@ -420,6 +185,7 @@ squidboy(Apic* apic) checkmtrr(); apic->online = 1; + coherence(); lapicinit(apic); lapiconline(); @@ -486,14 +252,14 @@ mpstartap(Apic* apic) * The offsets are known in the AP bootstrap code. */ apbootp = (ulong*)(APBOOTSTRAP+0x08); - *apbootp++ = (ulong)squidboy; + *apbootp++ = (ulong)squidboy; /* assembler jumps here eventually */ *apbootp++ = PADDR(pdb); *apbootp = (ulong)apic; /* * Universal Startup Algorithm. */ - p = KADDR(0x467); + p = KADDR(0x467); /* warm-reset vector */ *p++ = PADDR(APBOOTSTRAP); *p++ = PADDR(APBOOTSTRAP)>>8; i = (PADDR(APBOOTSTRAP) & ~0xFFFF)/16; @@ -502,8 +268,9 @@ mpstartap(Apic* apic) print("mp: bad APBOOTSTRAP\n"); *p++ = i; *p = i>>8; + coherence(); - nvramwrite(0x0F, 0x0A); + nvramwrite(0x0F, 0x0A); /* shutdown code: warm reset upon init ipi */ lapicstartap(apic, PADDR(APBOOTSTRAP)); for(i = 0; i < 1000; i++){ if(apic->online) @@ -513,145 +280,57 @@ mpstartap(Apic* apic) nvramwrite(0x0F, 0x00); } -static void -dumpmp(uchar *p, uchar *e) -{ - int i; - - for(i = 0; p < e; p++) { - if((i % 16) == 0) print("*mp%d=", i/16); - print("%.2x ", *p); - if((++i % 16) == 0) print("\n"); - } - if((i % 16) != 0) print("\n"); -} - -static void -mpoverride(uchar** newp, uchar** e) -{ - int size, i, j; - char buf[20]; - uchar* p; - char* s; - - size = atoi(getconf("*mp")); - if(size == 0) panic("mpoverride: invalid size in *mp"); - *newp = p = malloc(size); - if(p == nil) panic("mpoverride: can't allocate memory"); - *e = p + size; - for(i = 0; ; i++){ - snprint(buf, sizeof buf, "*mp%d", i); - s = getconf(buf); - if(s == nil) break; - while(*s){ - j = strtol(s, &s, 16); - if(*s && *s != ' ' || j < 0 || j > 0xff) panic("mpoverride: invalid entry in %s", buf); - if(p >= *e) panic("mpoverride: overflow in %s", buf); - *p++ = j; - } - } - if(p != *e) panic("mpoverride: size doesn't match"); -} - void mpinit(void) { int ncpu, i; + Apic *apic; char *cp; - PCMP *pcmp; - uchar *e, *p; - Apic *apic, *bpapic; - void *va; i8259init(); syncclock(); - if(_mp_ == 0) - return; - pcmp = KADDR(_mp_->physaddr); - - /* - * Map the local APIC. - */ - if((va = vmap(pcmp->lapicbase, 1024)) == nil) - return; - mppcmp = pcmp; - print("LAPIC: %.8lux %.8lux\n", pcmp->lapicbase, (ulong)va); - - bpapic = nil; - - for(i = 0; i <= MaxAPICNO; i++) - mpapicremap[i] = -1; - - /* - * 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; - if(getconf("*dumpmp") != nil) - dumpmp(p, e); - if(getconf("*mp") != nil) - mpoverride(&p, &e); - 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++; + if(getconf("*apicdebug")){ + Bus *b; + Aintr *ai; + PCMPintr *pi; + + for(i=0; i<=MaxAPICNO; i++){ + if(apic = mpapic[i]) + print("LAPIC%d: pa=%lux va=%lux flags=%x\n", + i, apic->paddr, (ulong)apic->addr, apic->flags); + if(apic = mpioapic[i]) + print("IOAPIC%d: pa=%lux va=%lux flags=%x gsibase=%d mre=%d\n", + i, apic->paddr, (ulong)apic->addr, apic->flags, apic->gsibase, apic->mre); } - break; + for(b = mpbus; b; b = b->next){ + print("BUS%d type=%d flags=%x\n", b->busno, b->type, b->po|b->el); + for(ai = b->aintr; ai; ai = ai->next){ + if(pi = ai->intr) + print("\ttype=%d irq=%d (%d [%c]) apic=%d intin=%d flags=%x\n", + pi->type, pi->irq, pi->irq>>2, "ABCD"[pi->irq&3], + pi->apicno, pi->intin, pi->flags); + } + } + } - 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; + apic = nil; + for(i=0; i<=MaxAPICNO; i++){ + if(mpapic[i] == nil) + continue; + if(mpapic[i]->flags & PcmpBP){ + apic = mpapic[i]; + break; } - 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) + if(apic == nil){ + panic("mpinit: no bootstrap processor"); return; - bpapic->online = 1; + } + apic->online = 1; - lapicinit(bpapic); + lapicinit(apic); /* * These interrupts are local to the processor @@ -678,11 +357,12 @@ mpinit(void) else ncpu = MAXMACH; memmove((void*)APBOOTSTRAP, apbootstrap, sizeof(apbootstrap)); - for(apic = mpapic; apic <= &mpapic[MaxAPICNO]; apic++){ + for(i=0; iflags & (PcmpBP|PcmpEN)) == PcmpEN - && apic->type == PcmpPROCESSOR){ + if((apic->flags & (PcmpBP|PcmpEN)) == PcmpEN){ mpstartap(apic); conf.nmach++; ncpu--; @@ -703,6 +383,8 @@ mpinit(void) static int mpintrcpu(void) { + static Lock physidlock; + static int physid; int i; /* @@ -722,33 +404,47 @@ mpintrcpu(void) * to more than one thread in a core, or to use a "noise" core. * But, as usual, Intel make that an onerous task. */ - lock(&mpphysidlock); + lock(&physidlock); for(;;){ - i = mpphysid++; - if(mpphysid >= MaxAPICNO+1) - mpphysid = 0; - if(mpapic[i].online) + i = physid++; + if(physid >= nelem(mpapic)) + physid = 0; + if(mpapic[i] == nil) + continue; + if(mpapic[i]->online) break; } - unlock(&mpphysidlock); + unlock(&physidlock); - return mpapic[i].apicno; + return mpapic[i]->apicno; } -/* hardcoded VectorAPIC and stuff. bad. */ +/* + * 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. + */ static int allocvector(void) { - static int round = 0, num = 1; + static int round = 0, num = 0; static Lock l; int vno; lock(&l); - if(num >= 24) { - if(++round >= 8) round = 0; - num = 1; - } - vno = 64 + num++ * 8 + round; + vno = VectorAPIC + num; + if(vno < MaxVectorAPIC-7) + num += 8; + else + num = ++round % 8; unlock(&l); return vno; } @@ -760,40 +456,55 @@ mpintrenablex(Vctl* v, int tbdf) Aintr *aintr; Apic *apic; Pcidev *pcidev; - int bno, dno, hi, irq, lo, n, type, vno; + int bno, dno, pin, hi, irq, lo, n, type, vno; - /* - * Find the bus. - */ type = BUSTYPE(tbdf); bno = BUSBNO(tbdf); dno = BUSDNO(tbdf); - if(type == BusISA) + + pin = 0; + pcidev = nil; + if(type == BusPCI){ + if(pcidev = pcimatchtbdf(tbdf)) + pin = pcicfgr8(pcidev, PciINTP); + } else if(type == BusISA) bno = mpisabus; + +Findbus: for(bus = mpbus; bus != nil; bus = bus->next){ if(bus->type != type) continue; if(bus->busno == bno) break; } + if(bus == nil){ - print("ioapicirq: can't find bus type %d, number %d\n", type, bno); + /* + * if the PCI device is behind a PCI-PCI bridge thats not described + * by the MP or ACPI tables then walk up the bus translating interrupt + * pin to parent bus. + */ + if(pcidev && pcidev->parent && pin > 0){ + pin = ((dno+(pin-1))%4)+1; + pcidev = pcidev->parent; + bno = BUSBNO(pcidev->tbdf); + dno = BUSDNO(pcidev->tbdf); + goto Findbus; + } + print("mpintrenable: can't find bus type %d, number %d\n", type, bno); return -1; } /* * 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. + * to match on. */ if(bus->type == BusPCI){ - pcidev = pcimatchtbdf(tbdf); - if(pcidev != nil && (n = pcicfgr8(pcidev, PciINTP)) != 0) - irq = (dno<<2)|(n-1); + if(pin > 0) + irq = (dno<<2)|(pin-1); else irq = -1; - //print("pcidev %uX: irq %uX v->irq %uX\n", tbdf, irq, v->irq); } else irq = v->irq; @@ -805,9 +516,8 @@ mpintrenablex(Vctl* v, int tbdf) for(aintr = bus->aintr; aintr; aintr = aintr->next){ if(aintr->intr->irq != irq) continue; - if (0) { + if(0){ PCMPintr* p = aintr->intr; - print("mpintrenablex: bus %d intin %d irq %d\n", p->busno, p->intin, p->irq); } @@ -825,55 +535,34 @@ mpintrenablex(Vctl* v, int tbdf) ioapicrdtr(apic, aintr->intr->intin, 0, &lo); if(!(lo & ApicIMASK)){ vno = lo & 0xFF; -//print("%s vector %d (!imask)\n", v->name, vno); + if(0) print("%s vector %d (!imask)\n", v->name, vno); n = mpintrinit(bus, aintr->intr, vno, v->irq); n |= ApicPHYSICAL; /* no-op */ lo &= ~(ApicRemoteIRR|ApicDELIVS); - if(n != lo || !(n & ApicLEVEL)){ - print("mpintrenable: multiple botch irq%d, tbdf %uX, lo %8.8uX, n %8.8uX\n", + if(n != lo){ + 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; } - /* - * 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. - */ vno = allocvector(); hi = mpintrcpu()<<24; lo = mpintrinit(bus, aintr->intr, vno, v->irq); - //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); - if(lo & ApicIMASK) - return -1; - lo |= ApicPHYSICAL; /* no-op */ - + if(lo & ApicIMASK){ + print("mpintrenable: disabled irq %d, tbdf %uX, lo %8.8uX, hi %8.8uX\n", + v->irq, tbdf, lo, hi); + return -1; + } if((apic->flags & PcmpEN) && apic->type == PcmpIOAPIC) ioapicrdtw(apic, aintr->intr->intin, hi, lo); - //else - // print("lo not enabled 0x%uX %d\n", - // apic->flags, apic->type); v->isr = lapicisr; v->eoi = lapiceoi; - return vno; } @@ -883,41 +572,36 @@ mpintrenablex(Vctl* v, int tbdf) enum { MSICtrl = 0x02, /* message control register (16 bit) */ MSIAddr = 0x04, /* message address register (64 bit) */ - MSIData = 0x0C, /* message data register (16 bit) */ + MSIData32 = 0x08, /* message data register for 32 bit MSI (16 bit) */ + MSIData64 = 0x0C, /* message data register for 64 bit MSI (16 bit) */ }; static int msiintrenable(Vctl *v) { - int tbdf, vno, cap, cpu; + int tbdf, vno, cap, cpu, ok64; Pcidev *pci; - if(getconf("*msi") == nil) + if(getconf("*nomsi") != nil) return -1; tbdf = v->tbdf; if(tbdf == BUSUNKNOWN || BUSTYPE(tbdf) != BusPCI) return -1; pci = pcimatchtbdf(tbdf); if(pci == nil) { - print("msiintrenable: could not find Pcidev for tbdf %.8x\n", tbdf); + print("msiintrenable: could not find Pcidev for tbdf %uX\n", tbdf); return -1; } - cap = 0; - for(;;) { - cap = pcinextcap(pci, cap); - if(cap == 0) - return -1; - if(pcicfgr8(pci, cap) == 0x05) /* MSI block */ - break; - } - + cap = pcicap(pci, PciCapMSI); + if(cap < 0) + return -1; vno = allocvector(); cpu = mpintrcpu(); + ok64 = (pcicfgr16(pci, cap + MSICtrl) & (1<<7)) != 0; pcicfgw32(pci, cap + MSIAddr, (0xFEE << 20) | (cpu << 12)); - pcicfgw32(pci, cap + MSIAddr + 4, 0); - pcicfgw16(pci, cap + MSIData, vno | (1<<14)); + if(ok64) pcicfgw32(pci, cap + MSIAddr + 4, 0); + pcicfgw16(pci, cap + (ok64 ? MSIData64 : MSIData32), vno | (1<<14)); pcicfgw16(pci, cap + MSICtrl, 1); - print("msiintrenable: success with tbdf %.8x, vector %d, cpu %d\n", tbdf, vno, cpu); v->isr = lapicisr; v->eoi = lapiceoi; return vno; @@ -974,20 +658,21 @@ mpintrenable(Vctl* v) if(vno != -1) return vno; } - print("mpintrenable: out of choices eisa %d isa %d tbdf %#ux irq %d\n", + print("mpintrenable: out of choices eisa %d isa %d tbdf %uX irq %d\n", mpeisabus, mpisabus, v->tbdf, v->irq); return -1; } -static Lock mpshutdownlock; void mpshutdown(void) { + static Lock shutdownlock; + /* * To be done... */ - if(!canlock(&mpshutdownlock)){ + if(!canlock(&shutdownlock)){ /* * If this processor received the CTRL-ALT-DEL from * the keyboard, acknowledge it. Send an INIT to self.