17dd7cddfSDavid du Colombier /* 27dd7cddfSDavid du Colombier * MultiProcessor Specification Version 1.[14]. 37dd7cddfSDavid du Colombier */ 47dd7cddfSDavid du Colombier typedef struct { /* floating pointer */ 57dd7cddfSDavid du Colombier uchar signature[4]; /* "_MP_" */ 67dd7cddfSDavid du Colombier long physaddr; /* physical address of MP configuration table */ 77dd7cddfSDavid du Colombier uchar length; /* 1 */ 87dd7cddfSDavid du Colombier uchar specrev; /* [14] */ 97dd7cddfSDavid du Colombier uchar checksum; /* all bytes must add up to 0 */ 107dd7cddfSDavid du Colombier uchar type; /* MP system configuration type */ 117dd7cddfSDavid du Colombier uchar imcrp; 127dd7cddfSDavid du Colombier uchar reserved[3]; 137dd7cddfSDavid du Colombier } _MP_; 147dd7cddfSDavid du Colombier 157dd7cddfSDavid du Colombier typedef struct { /* configuration table header */ 167dd7cddfSDavid du Colombier uchar signature[4]; /* "PCMP" */ 177dd7cddfSDavid du Colombier ushort length; /* total table length */ 187dd7cddfSDavid du Colombier uchar version; /* [14] */ 197dd7cddfSDavid du Colombier uchar checksum; /* all bytes must add up to 0 */ 207dd7cddfSDavid du Colombier uchar product[20]; /* product id */ 217dd7cddfSDavid du Colombier ulong oemtable; /* OEM table pointer */ 227dd7cddfSDavid du Colombier ushort oemlength; /* OEM table length */ 237dd7cddfSDavid du Colombier ushort entry; /* entry count */ 247dd7cddfSDavid du Colombier ulong lapicbase; /* address of local APIC */ 257dd7cddfSDavid du Colombier ushort xlength; /* extended table length */ 267dd7cddfSDavid du Colombier uchar xchecksum; /* extended table checksum */ 277dd7cddfSDavid du Colombier uchar reserved; 287dd7cddfSDavid du Colombier } PCMP; 297dd7cddfSDavid du Colombier 307dd7cddfSDavid du Colombier typedef struct { /* processor table entry */ 317dd7cddfSDavid du Colombier uchar type; /* entry type (0) */ 327dd7cddfSDavid du Colombier uchar apicno; /* local APIC id */ 337dd7cddfSDavid du Colombier uchar version; /* local APIC verison */ 347dd7cddfSDavid du Colombier uchar flags; /* CPU flags */ 357dd7cddfSDavid du Colombier uchar signature[4]; /* CPU signature */ 367dd7cddfSDavid du Colombier ulong feature; /* feature flags from CPUID instruction */ 377dd7cddfSDavid du Colombier uchar reserved[8]; 387dd7cddfSDavid du Colombier } PCMPprocessor; 397dd7cddfSDavid du Colombier 407dd7cddfSDavid du Colombier typedef struct { /* bus table entry */ 417dd7cddfSDavid du Colombier uchar type; /* entry type (1) */ 427dd7cddfSDavid du Colombier uchar busno; /* bus id */ 437dd7cddfSDavid du Colombier char string[6]; /* bus type string */ 447dd7cddfSDavid du Colombier } PCMPbus; 457dd7cddfSDavid du Colombier 467dd7cddfSDavid du Colombier typedef struct { /* I/O APIC table entry */ 477dd7cddfSDavid du Colombier uchar type; /* entry type (2) */ 487dd7cddfSDavid du Colombier uchar apicno; /* I/O APIC id */ 497dd7cddfSDavid du Colombier uchar version; /* I/O APIC version */ 507dd7cddfSDavid du Colombier uchar flags; /* I/O APIC flags */ 517dd7cddfSDavid du Colombier ulong addr; /* I/O APIC address */ 527dd7cddfSDavid du Colombier } PCMPioapic; 537dd7cddfSDavid du Colombier 547dd7cddfSDavid du Colombier typedef struct { /* interrupt table entry */ 557dd7cddfSDavid du Colombier uchar type; /* entry type ([34]) */ 567dd7cddfSDavid du Colombier uchar intr; /* interrupt type */ 577dd7cddfSDavid du Colombier ushort flags; /* interrupt flag */ 587dd7cddfSDavid du Colombier uchar busno; /* source bus id */ 597dd7cddfSDavid du Colombier uchar irq; /* source bus irq */ 607dd7cddfSDavid du Colombier uchar apicno; /* destination APIC id */ 617dd7cddfSDavid du Colombier uchar intin; /* destination APIC [L]INTIN# */ 627dd7cddfSDavid du Colombier } PCMPintr; 637dd7cddfSDavid du Colombier 647dd7cddfSDavid du Colombier typedef struct { /* system address space mapping entry */ 657dd7cddfSDavid du Colombier uchar type; /* entry type (128) */ 667dd7cddfSDavid du Colombier uchar length; /* of this entry (20) */ 677dd7cddfSDavid du Colombier uchar busno; /* bus id */ 687dd7cddfSDavid du Colombier uchar addrtype; 697dd7cddfSDavid du Colombier ulong addrbase[2]; 707dd7cddfSDavid du Colombier ulong addrlength[2]; 717dd7cddfSDavid du Colombier } PCMPsasm; 727dd7cddfSDavid du Colombier 737dd7cddfSDavid du Colombier typedef struct { /* bus hierarchy descriptor entry */ 747dd7cddfSDavid du Colombier uchar type; /* entry type (129) */ 757dd7cddfSDavid du Colombier uchar length; /* of this entry (8) */ 767dd7cddfSDavid du Colombier uchar busno; /* bus id */ 777dd7cddfSDavid du Colombier uchar info; /* bus info */ 787dd7cddfSDavid du Colombier uchar parent; /* parent bus */ 797dd7cddfSDavid du Colombier uchar reserved[3]; 807dd7cddfSDavid du Colombier } PCMPhierarchy; 817dd7cddfSDavid du Colombier 827dd7cddfSDavid du Colombier typedef struct { /* compatibility bus address space modifier entry */ 837dd7cddfSDavid du Colombier uchar type; /* entry type (130) */ 847dd7cddfSDavid du Colombier uchar length; /* of this entry (8) */ 857dd7cddfSDavid du Colombier uchar busno; /* bus id */ 867dd7cddfSDavid du Colombier uchar modifier; /* address modifier */ 877dd7cddfSDavid du Colombier ulong range; /* predefined range list */ 887dd7cddfSDavid du Colombier } PCMPcbasm; 897dd7cddfSDavid du Colombier 907dd7cddfSDavid du Colombier enum { /* table entry types */ 917dd7cddfSDavid du Colombier PcmpPROCESSOR = 0x00, /* one entry per processor */ 927dd7cddfSDavid du Colombier PcmpBUS = 0x01, /* one entry per bus */ 937dd7cddfSDavid du Colombier PcmpIOAPIC = 0x02, /* one entry per I/O APIC */ 947dd7cddfSDavid du Colombier PcmpIOINTR = 0x03, /* one entry per bus interrupt source */ 957dd7cddfSDavid du Colombier PcmpLINTR = 0x04, /* one entry per system interrupt source */ 967dd7cddfSDavid du Colombier 977dd7cddfSDavid du Colombier PcmpSASM = 0x80, 987dd7cddfSDavid du Colombier PcmpHIERARCHY = 0x81, 997dd7cddfSDavid du Colombier PcmpCBASM = 0x82, 1007dd7cddfSDavid du Colombier 1017dd7cddfSDavid du Colombier /* PCMPprocessor and PCMPioapic flags */ 1027dd7cddfSDavid du Colombier PcmpEN = 0x01, /* enabled */ 1037dd7cddfSDavid du Colombier PcmpBP = 0x02, /* bootstrap processor */ 1047dd7cddfSDavid du Colombier 1057dd7cddfSDavid du Colombier /* PCMPiointr and PCMPlintr flags */ 1067dd7cddfSDavid du Colombier PcmpPOMASK = 0x03, /* polarity conforms to specifications of bus */ 1077dd7cddfSDavid du Colombier PcmpHIGH = 0x01, /* active high */ 1087dd7cddfSDavid du Colombier PcmpLOW = 0x03, /* active low */ 1097dd7cddfSDavid du Colombier PcmpELMASK = 0x0C, /* trigger mode of APIC input signals */ 1107dd7cddfSDavid du Colombier PcmpEDGE = 0x04, /* edge-triggered */ 1117dd7cddfSDavid du Colombier PcmpLEVEL = 0x0C, /* level-triggered */ 1127dd7cddfSDavid du Colombier 1137dd7cddfSDavid du Colombier /* PCMPiointr and PCMPlintr interrupt type */ 1147dd7cddfSDavid du Colombier PcmpINT = 0x00, /* vectored interrupt from APIC Rdt */ 1157dd7cddfSDavid du Colombier PcmpNMI = 0x01, /* non-maskable interrupt */ 1167dd7cddfSDavid du Colombier PcmpSMI = 0x02, /* system management interrupt */ 1177dd7cddfSDavid du Colombier PcmpExtINT = 0x03, /* vectored interrupt from external PIC */ 1187dd7cddfSDavid du Colombier 1197dd7cddfSDavid du Colombier /* PCMPsasm addrtype */ 1207dd7cddfSDavid du Colombier PcmpIOADDR = 0x00, /* I/O address */ 1217dd7cddfSDavid du Colombier PcmpMADDR = 0x01, /* memory address */ 1227dd7cddfSDavid du Colombier PcmpPADDR = 0x02, /* prefetch address */ 1237dd7cddfSDavid du Colombier 1247dd7cddfSDavid du Colombier /* PCMPhierarchy info */ 1257dd7cddfSDavid du Colombier PcmpSD = 0x01, /* subtractive decode bus */ 1267dd7cddfSDavid du Colombier 1277dd7cddfSDavid du Colombier /* PCMPcbasm modifier */ 1287dd7cddfSDavid du Colombier PcmpPR = 0x01, /* predefined range list */ 1297dd7cddfSDavid du Colombier }; 1307dd7cddfSDavid du Colombier 1317dd7cddfSDavid du Colombier /* 1327dd7cddfSDavid du Colombier * Condensed form of the MP Configuration Table. 1337dd7cddfSDavid du Colombier * This is created during a single pass through the MP Configuration 1347dd7cddfSDavid du Colombier * table. 1357dd7cddfSDavid du Colombier */ 1367dd7cddfSDavid du Colombier typedef struct Aintr Aintr; 1377dd7cddfSDavid du Colombier typedef struct Bus Bus; 1387dd7cddfSDavid du Colombier typedef struct Apic Apic; 1397dd7cddfSDavid du Colombier 1407dd7cddfSDavid du Colombier typedef struct Bus { 1417dd7cddfSDavid du Colombier uchar type; 1427dd7cddfSDavid du Colombier uchar busno; 1437dd7cddfSDavid du Colombier uchar po; 1447dd7cddfSDavid du Colombier uchar el; 1457dd7cddfSDavid du Colombier 1467dd7cddfSDavid du Colombier Aintr* aintr; /* interrupts tied to this bus */ 1477dd7cddfSDavid du Colombier Bus* next; 1487dd7cddfSDavid du Colombier } Bus; 1497dd7cddfSDavid du Colombier 1507dd7cddfSDavid du Colombier typedef struct Aintr { 1517dd7cddfSDavid du Colombier PCMPintr* intr; 1527dd7cddfSDavid du Colombier Apic* apic; 1537dd7cddfSDavid du Colombier Aintr* next; 1547dd7cddfSDavid du Colombier }; 1557dd7cddfSDavid du Colombier 1567dd7cddfSDavid du Colombier typedef struct Apic { 1577dd7cddfSDavid du Colombier int type; 1587dd7cddfSDavid du Colombier int apicno; 1597dd7cddfSDavid du Colombier ulong* addr; /* register base address */ 160ea15f0ccSDavid du Colombier ulong paddr; 1617dd7cddfSDavid du Colombier int flags; /* PcmpBP|PcmpEN */ 1627dd7cddfSDavid du Colombier 1637dd7cddfSDavid du Colombier Lock; /* I/O APIC: register access */ 1647dd7cddfSDavid du Colombier int mre; /* I/O APIC: maximum redirection entry */ 1657dd7cddfSDavid du Colombier 1667dd7cddfSDavid du Colombier int lintr[2]; /* Local APIC */ 1677dd7cddfSDavid du Colombier int machno; 168*bd2f1373SDavid du Colombier 169*bd2f1373SDavid du Colombier int online; 1707dd7cddfSDavid du Colombier } Apic; 1717dd7cddfSDavid du Colombier 1727dd7cddfSDavid du Colombier enum { 173*bd2f1373SDavid du Colombier MaxAPICNO = 254, /* 255 is physical broadcast */ 1747dd7cddfSDavid du Colombier }; 1757dd7cddfSDavid du Colombier 1767dd7cddfSDavid du Colombier enum { /* I/O APIC registers */ 1777dd7cddfSDavid du Colombier IoapicID = 0x00, /* ID */ 1787dd7cddfSDavid du Colombier IoapicVER = 0x01, /* version */ 1797dd7cddfSDavid du Colombier IoapicARB = 0x02, /* arbitration ID */ 1807dd7cddfSDavid du Colombier IoapicRDT = 0x10, /* redirection table */ 1817dd7cddfSDavid du Colombier }; 1827dd7cddfSDavid du Colombier 1837dd7cddfSDavid du Colombier /* 1847dd7cddfSDavid du Colombier * Common bits for 1857dd7cddfSDavid du Colombier * I/O APIC Redirection Table Entry; 1867dd7cddfSDavid du Colombier * Local APIC Local Interrupt Vector Table; 1877dd7cddfSDavid du Colombier * Local APIC Inter-Processor Interrupt; 1887dd7cddfSDavid du Colombier * Local APIC Timer Vector Table. 1897dd7cddfSDavid du Colombier */ 1907dd7cddfSDavid du Colombier enum { 1917dd7cddfSDavid du Colombier ApicFIXED = 0x00000000, /* [10:8] Delivery Mode */ 1927dd7cddfSDavid du Colombier ApicLOWEST = 0x00000100, /* Lowest priority */ 1937dd7cddfSDavid du Colombier ApicSMI = 0x00000200, /* System Management Interrupt */ 1947dd7cddfSDavid du Colombier ApicRR = 0x00000300, /* Remote Read */ 1957dd7cddfSDavid du Colombier ApicNMI = 0x00000400, 1967dd7cddfSDavid du Colombier ApicINIT = 0x00000500, /* INIT/RESET */ 1977dd7cddfSDavid du Colombier ApicSTARTUP = 0x00000600, /* Startup IPI */ 1987dd7cddfSDavid du Colombier ApicExtINT = 0x00000700, 1997dd7cddfSDavid du Colombier 2007dd7cddfSDavid du Colombier ApicPHYSICAL = 0x00000000, /* [11] Destination Mode (RW) */ 2017dd7cddfSDavid du Colombier ApicLOGICAL = 0x00000800, 2027dd7cddfSDavid du Colombier 2037dd7cddfSDavid du Colombier ApicDELIVS = 0x00001000, /* [12] Delivery Status (RO) */ 2047dd7cddfSDavid du Colombier ApicHIGH = 0x00000000, /* [13] Interrupt Input Pin Polarity (RW) */ 2057dd7cddfSDavid du Colombier ApicLOW = 0x00002000, 2067dd7cddfSDavid du Colombier ApicRemoteIRR = 0x00004000, /* [14] Remote IRR (RO) */ 2077dd7cddfSDavid du Colombier ApicEDGE = 0x00000000, /* [15] Trigger Mode (RW) */ 2087dd7cddfSDavid du Colombier ApicLEVEL = 0x00008000, 2097dd7cddfSDavid du Colombier ApicIMASK = 0x00010000, /* [16] Interrupt Mask */ 2107dd7cddfSDavid du Colombier }; 2117dd7cddfSDavid du Colombier 2120ef97810SDavid du Colombier extern void ioapicinit(Apic*, int); 2137dd7cddfSDavid du Colombier extern void ioapicrdtr(Apic*, int, int*, int*); 2147dd7cddfSDavid du Colombier extern void ioapicrdtw(Apic*, int, int, int); 2150ef97810SDavid du Colombier 2160ef97810SDavid du Colombier extern void lapicclock(Ureg*, void*); 2177dd7cddfSDavid du Colombier extern int lapiceoi(int); 2180ef97810SDavid du Colombier extern void lapicerror(Ureg*, void*); 2194fafed5dSDavid du Colombier extern void lapicicrw(ulong, ulong); 2200ef97810SDavid du Colombier extern void lapicinit(Apic*); 2214de34a7eSDavid du Colombier extern void lapicintroff(void); 2220ef97810SDavid du Colombier extern void lapicintron(void); 2230ef97810SDavid du Colombier extern int lapicisr(int); 2240ef97810SDavid du Colombier extern void lapicnmidisable(void); 2250ef97810SDavid du Colombier extern void lapicnmienable(void); 2260ef97810SDavid du Colombier extern void lapiconline(void); 2270ef97810SDavid du Colombier extern void lapicspurious(Ureg*, void*); 2280ef97810SDavid du Colombier extern void lapicstartap(Apic*, int); 2290ef97810SDavid du Colombier extern void lapictimerset(uvlong); 2307dd7cddfSDavid du Colombier 2317dd7cddfSDavid du Colombier extern void mpinit(void); 2327dd7cddfSDavid du Colombier extern int mpintrenable(Vctl*); 2330ef97810SDavid du Colombier extern void mpshutdown(void); 2347dd7cddfSDavid du Colombier 2357dd7cddfSDavid du Colombier extern _MP_ *_mp_; 236