make multiple i/o apics work by mapping gsis to ioapic intins correctly: - fix off-by-one error in mapping gsi interrupts to ioapics. - use the intin and not the gsi when building the interrupt, - make acpi apic mapping errors more informative. - create a fake interrupt type (instead of just using 0) MTint for acpi mapped interrupts through the ioapic. this decision might need further consideration. Reference: /n/atom/patch/applied2013/acpiioapics Date: Mon Aug 26 19:47:54 CES 2013 Signed-off-by: quanstro@quanstro.net --- /sys/src/nix/k10/ioapic.c Mon Aug 26 19:42:04 2013 +++ /sys/src/nix/k10/ioapic.c Mon Aug 26 19:42:04 2013 @@ -88,7 +88,7 @@ a = xioapic + i; if(!a->useable) continue; - if(gsi >= a->ibase && gsi <= a->ibase+a->nrdt){ + if(gsi >= a->ibase && gsi < a->ibase+a->nrdt){ if(intin != nil) *intin = gsi - a->ibase; return a - xioapic; @@ -149,8 +149,8 @@ apic = &xioapic[apicno]; if(!apic->useable || intin >= apic->nrdt) - panic("ioapic: intrinit: usable %d: bus %d apic %d intin %d dev %d lo %.8ux\n", - apic->useable, busno, apicno, intin, devno, lo); + panic("ioapic: intrinit: usable %d nrdt %d: bus %d apic %d intin %d dev %d lo %.8ux\n", + apic->useable, apic->nrdt, busno, apicno, intin, devno, lo); rdt = rdtlookup(apic, intin); if(rdt == nil){ --- /sys/src/nix/k10/acpi.c Mon Aug 26 19:42:04 2013 +++ /sys/src/nix/k10/acpi.c Mon Aug 26 19:42:04 2013 @@ -225,6 +225,8 @@ enum { Iointr, Lintr, + + MTint = 0, /* fake interrupt type, equivalent to fixed */ }; static u32int @@ -253,21 +255,21 @@ return 0; case Iointr: if((apic = ioapiclookup(apicno)) == nil){ - print("apic: ioapic unusable %d\n", apicno); + print("ioapic%d: ioapic unusable\n", apicno); return 0; } if(intin >= apic->nrdt){ - print("apic: id beyond nrdt: %d\n", apicno); + print("ioapic%d: intin %d >= nrdt %d\n", apicno, intin, apic->nrdt); return 0; } break; case Lintr: if((apic = lapiclookup(apicno)) == nil){ - print("apic: lapic unusable %d\n", apicno); + print("lapic%d: lapic unusable\n", apicno); return 0; } if(intin >= nelem(apic->lvt)){ - print("apic: intin beyond lvt: %d\n", intin); + print("lapic%d: intin beyond lvt: %d\n", apicno, intin); return 0; } USED(apic); @@ -288,7 +290,7 @@ default: print("apic: bad irq type %d\n", inttype); return 0; - case 0: /* INT (fake type, same as fixed) */ + case MTint: /* INT (fake type, same as fixed) */ v |= polarity | trigger; break; case MTnmi: /* NMI */ @@ -351,8 +353,10 @@ uint apicno, intin, polarity, trigger; u32int i; - if((apicno = gsitoapicid(gsi, &intin)) == -1) + if((apicno = gsitoapicid(gsi, &intin)) == -1){ + print("acpi: addirq: no apic for gsi %d bus %d.%d\n", gsi, bustype, busno); return; + } DBG("addirq: gsi %d %s busno %d irq %d flags %.8ux\n", gsi, bustype == BusPCI? "pci": "isa", busno, irq, flags); polarity = flagstopolarity(bustype, flags); @@ -363,8 +367,8 @@ return; } - i = apicmkintr(Iointr, 0, polarity, trigger, apicno, gsi); - ioapicintrinit(bustype, busno, apicno, gsi, irq, i); + i = apicmkintr(Iointr, MTint, polarity, trigger, apicno, intin); + ioapicintrinit(bustype, busno, apicno, intin, irq, i); } static char* @@ -489,6 +493,7 @@ Lapicen = 1, }; +#define acpiinit(x) mpsinit(x) /* temporary hack */ void acpiinit(int maxmach) { @@ -535,7 +540,7 @@ print("acpi: ignoring nmi source\n"); break; case 0x04: /* Local APIC NMI */ - print("acpi: lapic nmi %.2ux flags %.4ux lint# %d (ignored)\n", + DBG("acpi: lapic nmi %.2ux flags %.4ux lint# %d (ignored)\n", p[2], (uint)get16(p+3), p[5]); break; case 0x05: /* Local APIC Address Override */