also use the apic madt table to pick up processors and i/o apics. this is important for many intel machines which have incomplete mp tables. (some are as bare as just mentioning the bsp and interrupt routing.) here's some output from my 4c/8t intel 1st generation i7 APIC lapic paddr 0xfee00000, flags 0x00000001 apic proc 0/0 apicid 0 (mp) apic proc 1/1 apicid 2 (mp) apic proc 2/2 apicid 4 (mp) apic proc 3/3 apicid 6 (mp) apic proc 4/4 apicid 1 apic proc 5/5 apicid 3 apic proc 6/6 apicid 5 apic proc 7/7 apicid 7 note that the odd apic ids (that is, the hyperthread partners) were not in the mp table, but the even apic ids were. changes: - undid changes to devacpi prints Reference: /n/patches.lsub.org/patch/mpacpi Date: Fri Jul 6 00:51:18 CES 2012 Signed-off-by: quanstro@quanstro.net --- /sys/src/nix/k10/mpacpi.c Thu Jan 1 00:00:00 1970 +++ /sys/src/nix/k10/mpacpi.c Thu Jul 5 23:25:04 2012 @@ -0,0 +1,57 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "mp.h" +#include "apic.h" +#include "acpi.h" + +extern Madt *apics; + +int +mpacpi(int maxcores) +{ + char *already; + int np, bp; + Apic *apic; + Apicst *st; + + print("APIC lapic paddr %#.8llux, flags %#.8ux\n", + apics->lapicpa, apics->pcat); + np = 0; + for(st = apics->st; st != nil; st = st->next){ + already = ""; + switch(st->type){ + case ASlapic: + if(st->lapic.id > Napic || np == maxcores) + break; + apic = xlapic + st->lapic.id; + bp = (np++ == 0); + if(apic->useable){ + already = "(mp)"; + goto pr; + } + apicinit(st->lapic.id, apics->lapicpa, bp); + pr: + print("apic proc %d/%d apicid %d %s\n", np-1, apic->machno, st->lapic.id, already); + break; + case ASioapic: + if(st->ioapic.id > Napic) + break; + apic = xioapic + st->ioapic.id; + if(apic->useable){ + apic->ibase = st->ioapic.ibase; /* gnarly */ + already = "(mp)"; + goto pr1; + } + ioapicinit(st->ioapic.id, st->ioapic.ibase, st->ioapic.addr); + pr1: + print("ioapic %d ", st->ioapic.id); + print("addr %p base %d %s\n", apic->paddr, apic->ibase, already); + break; + } + } + return maxcores - np; +} --- /sys/src/nix/k10/devacpi.c Fri Jun 29 11:50:22 2012 +++ /sys/src/nix/k10/devacpi.c Thu Jul 5 23:52:49 2012 @@ -64,7 +64,7 @@ static Xsdt* xsdt; /* XSDT table */ static Atable* tfirst; /* loaded DSDT/SSDT/... tables */ static Atable* tlast; /* pointer to last table */ -static Madt* apics; /* APIC info */ + Madt* apics; /* APIC info */ static Srat* srat; /* System resource affinity, used by physalloc */ static Slit* slit; /* System locality information table used by the scheduler */ static Msct* msct; /* Maximum system characteristics table */ --- /sys/src/nix/k10/apic.h Thu Apr 12 12:26:27 2012 +++ /sys/src/nix/k10/apic.h Fri Jul 6 15:03:27 2012 @@ -10,16 +10,17 @@ typedef struct Apic Apic; struct Ioapic { - Lock; /* IOAPIC: register access */ - u32int* addr; /* IOAPIC: register base */ - int nrdt; /* IOAPIC: size of RDT */ - int gsib; /* IOAPIC: global RDT index */ + Lock; /* register access */ + u32int* addr; /* register base */ + uintmem paddr; /* register base */ + int nrdt; /* size of RDT */ + int ibase; /* global interrupt base */ }; struct Lapic { int machno; /* APIC */ - u32int lvt[6]; + u32int lvt[7]; int nlvt; int ver; @@ -36,7 +37,7 @@ }; enum { - Nbus = 256, + Nbus = 256, /* must be 256 */ Napic = 254, /* xAPIC architectural limit */ Nrdt = 64, }; --- /sys/src/nix/k10/mp.c Mon May 14 11:40:26 2012 +++ /sys/src/nix/k10/mp.c Thu Jul 5 23:19:38 2012 @@ -173,7 +173,7 @@ return v; } -static void +static int mpparse(PCMP* pcmp, int maxcores) { u32int lo; @@ -245,7 +245,7 @@ * p[1] is the APIC ID, p[4-7] is the memory mapped address. */ if(p[3] & 0x01) - ioapicinit(p[1], l32get(p+4)); + ioapicinit(p[1], -1, l32get(p+4)); p += 8; break; @@ -348,6 +348,7 @@ p += p[1]; break; } + return maxcores; } static int @@ -476,7 +477,8 @@ * for later interrupt enabling and application processor * startup. */ - mpparse(pcmp, maxcores); + maxcores = mpparse(pcmp, maxcores); + mpacpi(maxcores); apicdump(); ioapicdump(); --- /sys/src/nix/k10/ioapic.c Thu Jun 14 09:36:22 2012 +++ /sys/src/nix/k10/ioapic.c Thu Jul 5 23:22:36 2012 @@ -40,7 +40,6 @@ static Rdt rdtarray[Nrdt]; static int nrdtarray; -static int gsib; static Rbus* rdtbus[Nbus]; static Rdt* rdtvecno[IdtMAX+1]; @@ -121,9 +120,10 @@ } void -ioapicinit(int id, uintptr pa) +ioapicinit(int id, int ibase, uintptr pa) { Apic *apic; + static int base; /* * Mark the IOAPIC useable if it has a good ID @@ -136,6 +136,7 @@ if(apic->useable || (apic->addr = vmap(pa, 1024)) == nil) return; apic->useable = 1; + apic->paddr = pa; /* * Initialise the I/O APIC. @@ -145,9 +146,12 @@ lock(apic); *(apic->addr+Ioregsel) = Ioapicver; apic->nrdt = ((*(apic->addr+Iowin)>>16) & 0xff) + 1; - apic->gsib = gsib; - gsib += apic->nrdt; - + if(ibase != -1) + apic->ibase = ibase; + else{ + apic->ibase = base; + base += apic->nrdt; + } *(apic->addr+Ioregsel) = Ioapicid; *(apic->addr+Iowin) = id<<24; unlock(apic); @@ -168,8 +172,8 @@ apic = &xioapic[i]; if(!apic->useable || apic->addr == 0) continue; - print("ioapic %d addr %#p nrdt %d gsib %d\n", - i, apic->addr, apic->nrdt, apic->gsib); + print("ioapic %d addr %#p nrdt %d ibase %d\n", + i, apic->addr, apic->nrdt, apic->ibase); for(n = 0; n < apic->nrdt; n++){ lock(apic); rtblget(apic, n, &hi, &lo); @@ -367,19 +371,19 @@ busno = BUSBNO(v->tbdf); if((pcidev = pcimatchtbdf(v->tbdf)) == nil) - panic("no PCI dev for tbdf %#8.8ux\n", v->tbdf); + panic("no PCI dev for tbdf %#8.8ux", v->tbdf); if((vecno = intrenablemsi(v, pcidev)) != -1) return vecno; disablemsi(v, pcidev); if((devno = pcicfgr8(pcidev, PciINTP)) == 0) - panic("no INTP for tbdf %#8.8ux\n", v->tbdf); + panic("no INTP for tbdf %#8.8ux", v->tbdf); devno = BUSDNO(v->tbdf)<<2|(devno-1); DBG("ioapicintrenable: tbdf %#8.8ux busno %d devno %d\n", v->tbdf, busno, devno); } else{ SET(busno, devno); - panic("unknown tbdf %#8.8ux\n", v->tbdf); + panic("unknown tbdf %#8.8ux", v->tbdf); } rdt = nil; --- /sys/src/nix/k10/k8cpu Tue Apr 24 10:39:34 2012 +++ /sys/src/nix/k10/k8cpu Thu Jul 5 23:34:40 2012 @@ -57,7 +57,7 @@ misc +dev # cache - mp apic ioapic msi pci sipi + mp mpacpi apic ioapic msi pci sipi # #boot cpu --- /sys/src/nix/k10/fns.h Tue Jul 3 10:40:23 2012 +++ /sys/src/nix/k10/fns.h Thu Jul 5 23:35:38 2012 @@ -221,7 +221,7 @@ extern void apicsipi(int, uintmem); void apicnipi(int apicno); -extern void ioapicinit(int, uintmem); +extern void ioapicinit(int, int, uintmem); extern void ioapicintrinit(int, int, int, int, u32int); extern void ioapiconline(void); @@ -243,6 +243,7 @@ * mp.c */ extern void mpsinit(int); +extern int mpacpi(int); /* * sipi.c