summaryrefslogtreecommitdiff
path: root/sys/src/9/pc/mp.h
blob: 4090f343e2aa2b498636d1fd014266f0d7c77673 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
/*
 * MultiProcessor Specification Version 1.[14].
 */
typedef struct {			/* floating pointer */
	uchar	signature[4];		/* "_MP_" */
	long	physaddr;		/* physical address of MP configuration table */
	uchar	length;			/* 1 */
	uchar	specrev;		/* [14] */
	uchar	checksum;		/* all bytes must add up to 0 */
	uchar	type;			/* MP system configuration type */
	uchar	imcrp;
	uchar	reserved[3];
} _MP_;

#define _MP_sz			(4+4+1+1+1+1+1+3)

typedef struct {			/* configuration table header */
	uchar	signature[4];		/* "PCMP" */
	ushort	length;			/* total table length */
	uchar	version;		/* [14] */
	uchar	checksum;		/* all bytes must add up to 0 */
	uchar	product[20];		/* product id */
	ulong	oemtable;		/* OEM table pointer */
	ushort	oemlength;		/* OEM table length */
	ushort	entry;			/* entry count */
	ulong	lapicbase;		/* address of local APIC */
	ushort	xlength;		/* extended table length */
	uchar	xchecksum;		/* extended table checksum */
	uchar	reserved;
} PCMP;

#define PCMPsz			(4+2+1+1+20+4+2+2+4+2+1+1)

typedef struct {			/* processor table entry */
	uchar	type;			/* entry type (0) */
	uchar	apicno;			/* local APIC id */
	uchar	version;		/* local APIC verison */
	uchar	flags;			/* CPU flags */
	uchar	signature[4];		/* CPU signature */
	ulong	feature;		/* feature flags from CPUID instruction */
	uchar	reserved[8];
} PCMPprocessor;

#define PCMPprocessorsz		(1+1+1+1+4+4+8)

typedef struct {			/* bus table entry */
	uchar	type;			/* entry type (1) */
	uchar	busno;			/* bus id */
	char	string[6];		/* bus type string */
} PCMPbus;

#define PCMPbussz		(1+1+6)

typedef struct {			/* I/O APIC table entry */
	uchar	type;			/* entry type (2) */
	uchar	apicno;			/* I/O APIC id */
	uchar	version;		/* I/O APIC version */
	uchar	flags;			/* I/O APIC flags */
	ulong	addr;			/* I/O APIC address */
} PCMPioapic;

#define PCMPioapicsz		(1+1+1+1+4)

typedef struct {			/* interrupt table entry */
	uchar	type;			/* entry type ([34]) */
	uchar	intr;			/* interrupt type */
	ushort	flags;			/* interrupt flag */
	uchar	busno;			/* source bus id */
	uchar	irq;			/* source bus irq */
	uchar	apicno;			/* destination APIC id */
	uchar	intin;			/* destination APIC [L]INTIN# */
} PCMPintr;

#define PCMPintrsz		(1+1+2+1+1+1+1)

typedef struct {			/* system address space mapping entry */
	uchar	type;			/* entry type (128) */
	uchar	length;			/* of this entry (20) */
	uchar	busno;			/* bus id */
	uchar	addrtype;
	ulong	addrbase[2];
	ulong	addrlength[2];
} PCMPsasm;

#define PCMPsasmsz		(1+1+1+1+8+8)

typedef struct {			/* bus hierarchy descriptor entry */
	uchar	type;			/* entry type (129) */
	uchar	length;			/* of this entry (8) */
	uchar	busno;			/* bus id */
	uchar	info;			/* bus info */
	uchar	parent;			/* parent bus */
	uchar	reserved[3];
} PCMPhierarchy;

#define PCMPhirarchysz		(1+1+1+1+1+3)

typedef struct {			/* compatibility bus address space modifier entry */
	uchar	type;			/* entry type (130) */
	uchar	length;			/* of this entry (8) */
	uchar	busno;			/* bus id */
	uchar	modifier;		/* address modifier */
	ulong	range;			/* predefined range list */
} PCMPcbasm;

#define PCMPcbasmsz		(1+1+1+1+4)

enum {					/* table entry types */
	PcmpPROCESSOR	= 0x00,		/* one entry per processor */
	PcmpBUS		= 0x01,		/* one entry per bus */
	PcmpIOAPIC	= 0x02,		/* one entry per I/O APIC */
	PcmpIOINTR	= 0x03,		/* one entry per bus interrupt source */
	PcmpLINTR	= 0x04,		/* one entry per system interrupt source */

	PcmpSASM	= 0x80,
	PcmpHIERARCHY	= 0x81,
	PcmpCBASM	= 0x82,

					/* PCMPprocessor and PCMPioapic flags */
	PcmpEN		= 0x01,		/* enabled */
	PcmpBP		= 0x02,		/* bootstrap processor */

					/* PCMPiointr and PCMPlintr flags */
	PcmpPOMASK	= 0x03,		/* polarity conforms to specifications of bus */
	PcmpHIGH	= 0x01,		/* active high */
	PcmpLOW		= 0x03,		/* active low */
	PcmpELMASK	= 0x0C,		/* trigger mode of APIC input signals */
	PcmpEDGE	= 0x04,		/* edge-triggered */
	PcmpLEVEL	= 0x0C,		/* level-triggered */

					/* PCMPiointr and PCMPlintr interrupt type */
	PcmpINT		= 0x00,		/* vectored interrupt from APIC Rdt */
	PcmpNMI		= 0x01,		/* non-maskable interrupt */
	PcmpSMI		= 0x02,		/* system management interrupt */
	PcmpExtINT	= 0x03,		/* vectored interrupt from external PIC */

					/* PCMPsasm addrtype */
	PcmpIOADDR	= 0x00,		/* I/O address */
	PcmpMADDR	= 0x01,		/* memory address */
	PcmpPADDR	= 0x02,		/* prefetch address */

					/* PCMPhierarchy info */
	PcmpSD		= 0x01,		/* subtractive decode bus */

					/* PCMPcbasm modifier */
	PcmpPR		= 0x01,		/* predefined range list */
};

/*
 * Condensed form of the MP Configuration Table.
 * This is created during a single pass through the MP Configuration
 * table.
 */
typedef struct Aintr Aintr;
typedef struct Bus Bus;
typedef struct Apic Apic;

typedef struct Bus {
	uchar	type;
	uchar	busno;
	uchar	po;
	uchar	el;

	Aintr*	aintr;			/* interrupts tied to this bus */
	Bus*	next;
} Bus;

typedef struct Aintr {
	PCMPintr* intr;
	Apic*	apic;
	Aintr*	next;
};

typedef struct Apic {
	int	type;
	int	apicno;
	ulong*	addr;			/* register base address */
	ulong	paddr;
	int	flags;			/* PcmpBP|PcmpEN */

	Lock;				/* I/O APIC: register access */
	int	mre;			/* I/O APIC: maximum redirection entry */
	int	gsibase;		/* I/O APIC: global system interrupt base (acpi) */

	int	lintr[2];		/* Local APIC */
	int	machno;

	int	online;
} Apic;

enum {
	MaxAPICNO	= 254,		/* 255 is physical broadcast */
};

enum {					/* I/O APIC registers */
	IoapicID	= 0x00,		/* ID */
	IoapicVER	= 0x01,		/* version */
	IoapicARB	= 0x02,		/* arbitration ID */
	IoapicRDT	= 0x10,		/* redirection table */
};

/*
 * Common bits for
 *	I/O APIC Redirection Table Entry;
 *	Local APIC Local Interrupt Vector Table;
 *	Local APIC Inter-Processor Interrupt;
 *	Local APIC Timer Vector Table.
 */
enum {
	ApicFIXED	= 0x00000000,	/* [10:8] Delivery Mode */
	ApicLOWEST	= 0x00000100,	/* Lowest priority */
	ApicSMI		= 0x00000200,	/* System Management Interrupt */
	ApicRR		= 0x00000300,	/* Remote Read */
	ApicNMI		= 0x00000400,
	ApicINIT	= 0x00000500,	/* INIT/RESET */
	ApicSTARTUP	= 0x00000600,	/* Startup IPI */
	ApicExtINT	= 0x00000700,

	ApicPHYSICAL	= 0x00000000,	/* [11] Destination Mode (RW) */
	ApicLOGICAL	= 0x00000800,

	ApicDELIVS	= 0x00001000,	/* [12] Delivery Status (RO) */
	ApicHIGH	= 0x00000000,	/* [13] Interrupt Input Pin Polarity (RW) */
	ApicLOW		= 0x00002000,
	ApicRemoteIRR	= 0x00004000,	/* [14] Remote IRR (RO) */
	ApicEDGE	= 0x00000000,	/* [15] Trigger Mode (RW) */
	ApicLEVEL	= 0x00008000,
	ApicIMASK	= 0x00010000,	/* [16] Interrupt Mask */
};

extern void ioapicinit(Apic*, int);
extern void ioapicrdtr(Apic*, int, int*, int*);
extern void ioapicrdtw(Apic*, int, int, int);

extern void lapicclock(Ureg*, void*);
extern int lapiceoi(int);
extern void lapicerror(Ureg*, void*);
extern void lapicicrw(ulong, ulong);
extern void lapicinit(Apic*);
extern void lapicintroff(void);
extern void lapicintron(void);
extern int lapicisr(int);
extern void lapicnmidisable(void);
extern void lapicnmienable(void);
extern void lapiconline(void);
extern void lapicspurious(Ureg*, void*);
extern void lapicstartap(Apic*, int);
extern void lapictimerset(uvlong);

extern int mpintrinit(Bus*, PCMPintr*, int, int);
extern void mpinit(void);
extern int mpintrenable(Vctl*);
extern void mpshutdown(void);
extern void mpstartap(Apic*);

extern Bus* mpbus;
extern Bus* mpbuslast;
extern int mpisabus;
extern int mpeisabus;
extern Apic *mpioapic[];
extern Apic *mpapic[];