xref: /plan9-contrib/sys/src/9/pc/mp.h (revision 1206f3fc1b0aab3e32fa15899d31a9b5bfa82d9f)
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