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
262
|
/*
* 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;
Bus* bus;
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 mpintrassign(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[];
|