xref: /dragonfly/sys/platform/pc64/apic/ioapic_abi.c (revision d0d42ea0)
1 /*
2  * Copyright (c) 1991 The Regents of the University of California.
3  * Copyright (c) 1996, by Steve Passe.  All rights reserved.
4  * Copyright (c) 2005,2008 The DragonFly Project.  All rights reserved.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The DragonFly Project
8  * by Matthew Dillon <dillon@backplane.com>
9  *
10  * This code is derived from software contributed to Berkeley by
11  * William Jolitz.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  *
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in
21  *    the documentation and/or other materials provided with the
22  *    distribution.
23  * 3. Neither the name of The DragonFly Project nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific, prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
30  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
31  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
33  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
35  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
37  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38  * SUCH DAMAGE.
39  *
40  * $DragonFly: src/sys/platform/pc64/apic/apic_abi.c,v 1.1 2008/08/29 17:07:12 dillon Exp $
41  */
42 
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/machintr.h>
47 #include <sys/interrupt.h>
48 #include <sys/bus.h>
49 #include <sys/rman.h>
50 #include <sys/thread2.h>
51 
52 #include <machine/smp.h>
53 #include <machine/segments.h>
54 #include <machine/md_var.h>
55 #include <machine/intr_machdep.h>
56 #include <machine/globaldata.h>
57 
58 #include <machine_base/isa/isa_intr.h>
59 #include <machine_base/icu/icu.h>
60 #include <machine_base/icu/icu_var.h>
61 #include <machine_base/apic/ioapic.h>
62 #include <machine_base/apic/ioapic_abi.h>
63 #include <machine_base/apic/ioapic_ipl.h>
64 #include <machine_base/apic/apicreg.h>
65 
66 #include <dev/acpica5/acpi_sci_var.h>
67 
68 #define IOAPIC_HWI_VECTORS	IDT_HWI_VECTORS
69 
70 extern inthand_t
71 	IDTVEC(ioapic_intr0),
72 	IDTVEC(ioapic_intr1),
73 	IDTVEC(ioapic_intr2),
74 	IDTVEC(ioapic_intr3),
75 	IDTVEC(ioapic_intr4),
76 	IDTVEC(ioapic_intr5),
77 	IDTVEC(ioapic_intr6),
78 	IDTVEC(ioapic_intr7),
79 	IDTVEC(ioapic_intr8),
80 	IDTVEC(ioapic_intr9),
81 	IDTVEC(ioapic_intr10),
82 	IDTVEC(ioapic_intr11),
83 	IDTVEC(ioapic_intr12),
84 	IDTVEC(ioapic_intr13),
85 	IDTVEC(ioapic_intr14),
86 	IDTVEC(ioapic_intr15),
87 	IDTVEC(ioapic_intr16),
88 	IDTVEC(ioapic_intr17),
89 	IDTVEC(ioapic_intr18),
90 	IDTVEC(ioapic_intr19),
91 	IDTVEC(ioapic_intr20),
92 	IDTVEC(ioapic_intr21),
93 	IDTVEC(ioapic_intr22),
94 	IDTVEC(ioapic_intr23),
95 	IDTVEC(ioapic_intr24),
96 	IDTVEC(ioapic_intr25),
97 	IDTVEC(ioapic_intr26),
98 	IDTVEC(ioapic_intr27),
99 	IDTVEC(ioapic_intr28),
100 	IDTVEC(ioapic_intr29),
101 	IDTVEC(ioapic_intr30),
102 	IDTVEC(ioapic_intr31),
103 	IDTVEC(ioapic_intr32),
104 	IDTVEC(ioapic_intr33),
105 	IDTVEC(ioapic_intr34),
106 	IDTVEC(ioapic_intr35),
107 	IDTVEC(ioapic_intr36),
108 	IDTVEC(ioapic_intr37),
109 	IDTVEC(ioapic_intr38),
110 	IDTVEC(ioapic_intr39),
111 	IDTVEC(ioapic_intr40),
112 	IDTVEC(ioapic_intr41),
113 	IDTVEC(ioapic_intr42),
114 	IDTVEC(ioapic_intr43),
115 	IDTVEC(ioapic_intr44),
116 	IDTVEC(ioapic_intr45),
117 	IDTVEC(ioapic_intr46),
118 	IDTVEC(ioapic_intr47),
119 	IDTVEC(ioapic_intr48),
120 	IDTVEC(ioapic_intr49),
121 	IDTVEC(ioapic_intr50),
122 	IDTVEC(ioapic_intr51),
123 	IDTVEC(ioapic_intr52),
124 	IDTVEC(ioapic_intr53),
125 	IDTVEC(ioapic_intr54),
126 	IDTVEC(ioapic_intr55),
127 	IDTVEC(ioapic_intr56),
128 	IDTVEC(ioapic_intr57),
129 	IDTVEC(ioapic_intr58),
130 	IDTVEC(ioapic_intr59),
131 	IDTVEC(ioapic_intr60),
132 	IDTVEC(ioapic_intr61),
133 	IDTVEC(ioapic_intr62),
134 	IDTVEC(ioapic_intr63),
135 	IDTVEC(ioapic_intr64),
136 	IDTVEC(ioapic_intr65),
137 	IDTVEC(ioapic_intr66),
138 	IDTVEC(ioapic_intr67),
139 	IDTVEC(ioapic_intr68),
140 	IDTVEC(ioapic_intr69),
141 	IDTVEC(ioapic_intr70),
142 	IDTVEC(ioapic_intr71),
143 	IDTVEC(ioapic_intr72),
144 	IDTVEC(ioapic_intr73),
145 	IDTVEC(ioapic_intr74),
146 	IDTVEC(ioapic_intr75),
147 	IDTVEC(ioapic_intr76),
148 	IDTVEC(ioapic_intr77),
149 	IDTVEC(ioapic_intr78),
150 	IDTVEC(ioapic_intr79),
151 	IDTVEC(ioapic_intr80),
152 	IDTVEC(ioapic_intr81),
153 	IDTVEC(ioapic_intr82),
154 	IDTVEC(ioapic_intr83),
155 	IDTVEC(ioapic_intr84),
156 	IDTVEC(ioapic_intr85),
157 	IDTVEC(ioapic_intr86),
158 	IDTVEC(ioapic_intr87),
159 	IDTVEC(ioapic_intr88),
160 	IDTVEC(ioapic_intr89),
161 	IDTVEC(ioapic_intr90),
162 	IDTVEC(ioapic_intr91),
163 	IDTVEC(ioapic_intr92),
164 	IDTVEC(ioapic_intr93),
165 	IDTVEC(ioapic_intr94),
166 	IDTVEC(ioapic_intr95),
167 	IDTVEC(ioapic_intr96),
168 	IDTVEC(ioapic_intr97),
169 	IDTVEC(ioapic_intr98),
170 	IDTVEC(ioapic_intr99),
171 	IDTVEC(ioapic_intr100),
172 	IDTVEC(ioapic_intr101),
173 	IDTVEC(ioapic_intr102),
174 	IDTVEC(ioapic_intr103),
175 	IDTVEC(ioapic_intr104),
176 	IDTVEC(ioapic_intr105),
177 	IDTVEC(ioapic_intr106),
178 	IDTVEC(ioapic_intr107),
179 	IDTVEC(ioapic_intr108),
180 	IDTVEC(ioapic_intr109),
181 	IDTVEC(ioapic_intr110),
182 	IDTVEC(ioapic_intr111),
183 	IDTVEC(ioapic_intr112),
184 	IDTVEC(ioapic_intr113),
185 	IDTVEC(ioapic_intr114),
186 	IDTVEC(ioapic_intr115),
187 	IDTVEC(ioapic_intr116),
188 	IDTVEC(ioapic_intr117),
189 	IDTVEC(ioapic_intr118),
190 	IDTVEC(ioapic_intr119),
191 	IDTVEC(ioapic_intr120),
192 	IDTVEC(ioapic_intr121),
193 	IDTVEC(ioapic_intr122),
194 	IDTVEC(ioapic_intr123),
195 	IDTVEC(ioapic_intr124),
196 	IDTVEC(ioapic_intr125),
197 	IDTVEC(ioapic_intr126),
198 	IDTVEC(ioapic_intr127),
199 	IDTVEC(ioapic_intr128),
200 	IDTVEC(ioapic_intr129),
201 	IDTVEC(ioapic_intr130),
202 	IDTVEC(ioapic_intr131),
203 	IDTVEC(ioapic_intr132),
204 	IDTVEC(ioapic_intr133),
205 	IDTVEC(ioapic_intr134),
206 	IDTVEC(ioapic_intr135),
207 	IDTVEC(ioapic_intr136),
208 	IDTVEC(ioapic_intr137),
209 	IDTVEC(ioapic_intr138),
210 	IDTVEC(ioapic_intr139),
211 	IDTVEC(ioapic_intr140),
212 	IDTVEC(ioapic_intr141),
213 	IDTVEC(ioapic_intr142),
214 	IDTVEC(ioapic_intr143),
215 	IDTVEC(ioapic_intr144),
216 	IDTVEC(ioapic_intr145),
217 	IDTVEC(ioapic_intr146),
218 	IDTVEC(ioapic_intr147),
219 	IDTVEC(ioapic_intr148),
220 	IDTVEC(ioapic_intr149),
221 	IDTVEC(ioapic_intr150),
222 	IDTVEC(ioapic_intr151),
223 	IDTVEC(ioapic_intr152),
224 	IDTVEC(ioapic_intr153),
225 	IDTVEC(ioapic_intr154),
226 	IDTVEC(ioapic_intr155),
227 	IDTVEC(ioapic_intr156),
228 	IDTVEC(ioapic_intr157),
229 	IDTVEC(ioapic_intr158),
230 	IDTVEC(ioapic_intr159),
231 	IDTVEC(ioapic_intr160),
232 	IDTVEC(ioapic_intr161),
233 	IDTVEC(ioapic_intr162),
234 	IDTVEC(ioapic_intr163),
235 	IDTVEC(ioapic_intr164),
236 	IDTVEC(ioapic_intr165),
237 	IDTVEC(ioapic_intr166),
238 	IDTVEC(ioapic_intr167),
239 	IDTVEC(ioapic_intr168),
240 	IDTVEC(ioapic_intr169),
241 	IDTVEC(ioapic_intr170),
242 	IDTVEC(ioapic_intr171),
243 	IDTVEC(ioapic_intr172),
244 	IDTVEC(ioapic_intr173),
245 	IDTVEC(ioapic_intr174),
246 	IDTVEC(ioapic_intr175),
247 	IDTVEC(ioapic_intr176),
248 	IDTVEC(ioapic_intr177),
249 	IDTVEC(ioapic_intr178),
250 	IDTVEC(ioapic_intr179),
251 	IDTVEC(ioapic_intr180),
252 	IDTVEC(ioapic_intr181),
253 	IDTVEC(ioapic_intr182),
254 	IDTVEC(ioapic_intr183),
255 	IDTVEC(ioapic_intr184),
256 	IDTVEC(ioapic_intr185),
257 	IDTVEC(ioapic_intr186),
258 	IDTVEC(ioapic_intr187),
259 	IDTVEC(ioapic_intr188),
260 	IDTVEC(ioapic_intr189),
261 	IDTVEC(ioapic_intr190),
262 	IDTVEC(ioapic_intr191);
263 
264 static inthand_t *ioapic_intr[IOAPIC_HWI_VECTORS] = {
265 	&IDTVEC(ioapic_intr0),
266 	&IDTVEC(ioapic_intr1),
267 	&IDTVEC(ioapic_intr2),
268 	&IDTVEC(ioapic_intr3),
269 	&IDTVEC(ioapic_intr4),
270 	&IDTVEC(ioapic_intr5),
271 	&IDTVEC(ioapic_intr6),
272 	&IDTVEC(ioapic_intr7),
273 	&IDTVEC(ioapic_intr8),
274 	&IDTVEC(ioapic_intr9),
275 	&IDTVEC(ioapic_intr10),
276 	&IDTVEC(ioapic_intr11),
277 	&IDTVEC(ioapic_intr12),
278 	&IDTVEC(ioapic_intr13),
279 	&IDTVEC(ioapic_intr14),
280 	&IDTVEC(ioapic_intr15),
281 	&IDTVEC(ioapic_intr16),
282 	&IDTVEC(ioapic_intr17),
283 	&IDTVEC(ioapic_intr18),
284 	&IDTVEC(ioapic_intr19),
285 	&IDTVEC(ioapic_intr20),
286 	&IDTVEC(ioapic_intr21),
287 	&IDTVEC(ioapic_intr22),
288 	&IDTVEC(ioapic_intr23),
289 	&IDTVEC(ioapic_intr24),
290 	&IDTVEC(ioapic_intr25),
291 	&IDTVEC(ioapic_intr26),
292 	&IDTVEC(ioapic_intr27),
293 	&IDTVEC(ioapic_intr28),
294 	&IDTVEC(ioapic_intr29),
295 	&IDTVEC(ioapic_intr30),
296 	&IDTVEC(ioapic_intr31),
297 	&IDTVEC(ioapic_intr32),
298 	&IDTVEC(ioapic_intr33),
299 	&IDTVEC(ioapic_intr34),
300 	&IDTVEC(ioapic_intr35),
301 	&IDTVEC(ioapic_intr36),
302 	&IDTVEC(ioapic_intr37),
303 	&IDTVEC(ioapic_intr38),
304 	&IDTVEC(ioapic_intr39),
305 	&IDTVEC(ioapic_intr40),
306 	&IDTVEC(ioapic_intr41),
307 	&IDTVEC(ioapic_intr42),
308 	&IDTVEC(ioapic_intr43),
309 	&IDTVEC(ioapic_intr44),
310 	&IDTVEC(ioapic_intr45),
311 	&IDTVEC(ioapic_intr46),
312 	&IDTVEC(ioapic_intr47),
313 	&IDTVEC(ioapic_intr48),
314 	&IDTVEC(ioapic_intr49),
315 	&IDTVEC(ioapic_intr50),
316 	&IDTVEC(ioapic_intr51),
317 	&IDTVEC(ioapic_intr52),
318 	&IDTVEC(ioapic_intr53),
319 	&IDTVEC(ioapic_intr54),
320 	&IDTVEC(ioapic_intr55),
321 	&IDTVEC(ioapic_intr56),
322 	&IDTVEC(ioapic_intr57),
323 	&IDTVEC(ioapic_intr58),
324 	&IDTVEC(ioapic_intr59),
325 	&IDTVEC(ioapic_intr60),
326 	&IDTVEC(ioapic_intr61),
327 	&IDTVEC(ioapic_intr62),
328 	&IDTVEC(ioapic_intr63),
329 	&IDTVEC(ioapic_intr64),
330 	&IDTVEC(ioapic_intr65),
331 	&IDTVEC(ioapic_intr66),
332 	&IDTVEC(ioapic_intr67),
333 	&IDTVEC(ioapic_intr68),
334 	&IDTVEC(ioapic_intr69),
335 	&IDTVEC(ioapic_intr70),
336 	&IDTVEC(ioapic_intr71),
337 	&IDTVEC(ioapic_intr72),
338 	&IDTVEC(ioapic_intr73),
339 	&IDTVEC(ioapic_intr74),
340 	&IDTVEC(ioapic_intr75),
341 	&IDTVEC(ioapic_intr76),
342 	&IDTVEC(ioapic_intr77),
343 	&IDTVEC(ioapic_intr78),
344 	&IDTVEC(ioapic_intr79),
345 	&IDTVEC(ioapic_intr80),
346 	&IDTVEC(ioapic_intr81),
347 	&IDTVEC(ioapic_intr82),
348 	&IDTVEC(ioapic_intr83),
349 	&IDTVEC(ioapic_intr84),
350 	&IDTVEC(ioapic_intr85),
351 	&IDTVEC(ioapic_intr86),
352 	&IDTVEC(ioapic_intr87),
353 	&IDTVEC(ioapic_intr88),
354 	&IDTVEC(ioapic_intr89),
355 	&IDTVEC(ioapic_intr90),
356 	&IDTVEC(ioapic_intr91),
357 	&IDTVEC(ioapic_intr92),
358 	&IDTVEC(ioapic_intr93),
359 	&IDTVEC(ioapic_intr94),
360 	&IDTVEC(ioapic_intr95),
361 	&IDTVEC(ioapic_intr96),
362 	&IDTVEC(ioapic_intr97),
363 	&IDTVEC(ioapic_intr98),
364 	&IDTVEC(ioapic_intr99),
365 	&IDTVEC(ioapic_intr100),
366 	&IDTVEC(ioapic_intr101),
367 	&IDTVEC(ioapic_intr102),
368 	&IDTVEC(ioapic_intr103),
369 	&IDTVEC(ioapic_intr104),
370 	&IDTVEC(ioapic_intr105),
371 	&IDTVEC(ioapic_intr106),
372 	&IDTVEC(ioapic_intr107),
373 	&IDTVEC(ioapic_intr108),
374 	&IDTVEC(ioapic_intr109),
375 	&IDTVEC(ioapic_intr110),
376 	&IDTVEC(ioapic_intr111),
377 	&IDTVEC(ioapic_intr112),
378 	&IDTVEC(ioapic_intr113),
379 	&IDTVEC(ioapic_intr114),
380 	&IDTVEC(ioapic_intr115),
381 	&IDTVEC(ioapic_intr116),
382 	&IDTVEC(ioapic_intr117),
383 	&IDTVEC(ioapic_intr118),
384 	&IDTVEC(ioapic_intr119),
385 	&IDTVEC(ioapic_intr120),
386 	&IDTVEC(ioapic_intr121),
387 	&IDTVEC(ioapic_intr122),
388 	&IDTVEC(ioapic_intr123),
389 	&IDTVEC(ioapic_intr124),
390 	&IDTVEC(ioapic_intr125),
391 	&IDTVEC(ioapic_intr126),
392 	&IDTVEC(ioapic_intr127),
393 	&IDTVEC(ioapic_intr128),
394 	&IDTVEC(ioapic_intr129),
395 	&IDTVEC(ioapic_intr130),
396 	&IDTVEC(ioapic_intr131),
397 	&IDTVEC(ioapic_intr132),
398 	&IDTVEC(ioapic_intr133),
399 	&IDTVEC(ioapic_intr134),
400 	&IDTVEC(ioapic_intr135),
401 	&IDTVEC(ioapic_intr136),
402 	&IDTVEC(ioapic_intr137),
403 	&IDTVEC(ioapic_intr138),
404 	&IDTVEC(ioapic_intr139),
405 	&IDTVEC(ioapic_intr140),
406 	&IDTVEC(ioapic_intr141),
407 	&IDTVEC(ioapic_intr142),
408 	&IDTVEC(ioapic_intr143),
409 	&IDTVEC(ioapic_intr144),
410 	&IDTVEC(ioapic_intr145),
411 	&IDTVEC(ioapic_intr146),
412 	&IDTVEC(ioapic_intr147),
413 	&IDTVEC(ioapic_intr148),
414 	&IDTVEC(ioapic_intr149),
415 	&IDTVEC(ioapic_intr150),
416 	&IDTVEC(ioapic_intr151),
417 	&IDTVEC(ioapic_intr152),
418 	&IDTVEC(ioapic_intr153),
419 	&IDTVEC(ioapic_intr154),
420 	&IDTVEC(ioapic_intr155),
421 	&IDTVEC(ioapic_intr156),
422 	&IDTVEC(ioapic_intr157),
423 	&IDTVEC(ioapic_intr158),
424 	&IDTVEC(ioapic_intr159),
425 	&IDTVEC(ioapic_intr160),
426 	&IDTVEC(ioapic_intr161),
427 	&IDTVEC(ioapic_intr162),
428 	&IDTVEC(ioapic_intr163),
429 	&IDTVEC(ioapic_intr164),
430 	&IDTVEC(ioapic_intr165),
431 	&IDTVEC(ioapic_intr166),
432 	&IDTVEC(ioapic_intr167),
433 	&IDTVEC(ioapic_intr168),
434 	&IDTVEC(ioapic_intr169),
435 	&IDTVEC(ioapic_intr170),
436 	&IDTVEC(ioapic_intr171),
437 	&IDTVEC(ioapic_intr172),
438 	&IDTVEC(ioapic_intr173),
439 	&IDTVEC(ioapic_intr174),
440 	&IDTVEC(ioapic_intr175),
441 	&IDTVEC(ioapic_intr176),
442 	&IDTVEC(ioapic_intr177),
443 	&IDTVEC(ioapic_intr178),
444 	&IDTVEC(ioapic_intr179),
445 	&IDTVEC(ioapic_intr180),
446 	&IDTVEC(ioapic_intr181),
447 	&IDTVEC(ioapic_intr182),
448 	&IDTVEC(ioapic_intr183),
449 	&IDTVEC(ioapic_intr184),
450 	&IDTVEC(ioapic_intr185),
451 	&IDTVEC(ioapic_intr186),
452 	&IDTVEC(ioapic_intr187),
453 	&IDTVEC(ioapic_intr188),
454 	&IDTVEC(ioapic_intr189),
455 	&IDTVEC(ioapic_intr190),
456 	&IDTVEC(ioapic_intr191)
457 };
458 
459 #define IOAPIC_HWI_SYSCALL	(IDT_OFFSET_SYSCALL - IDT_OFFSET)
460 
461 static struct ioapic_irqmap {
462 	int			im_type;	/* IOAPIC_IMT_ */
463 	enum intr_trigger	im_trig;
464 	enum intr_polarity	im_pola;
465 	int			im_gsi;
466 	uint32_t		im_flags;	/* IOAPIC_IMF_ */
467 } ioapic_irqmaps[MAXCPU][IOAPIC_HWI_VECTORS];
468 
469 #define IOAPIC_IMT_UNUSED	0
470 #define IOAPIC_IMT_RESERVED	1
471 #define IOAPIC_IMT_LINE		2
472 #define IOAPIC_IMT_SYSCALL	3
473 
474 #define IOAPIC_IMT_ISHWI(map)	((map)->im_type != IOAPIC_IMT_RESERVED && \
475 				 (map)->im_type != IOAPIC_IMT_SYSCALL)
476 
477 #define IOAPIC_IMF_CONF		0x1
478 
479 extern void	IOAPIC_INTREN(int);
480 extern void	IOAPIC_INTRDIS(int);
481 
482 extern int	imcr_present;
483 
484 static void	ioapic_abi_intr_enable(int);
485 static void	ioapic_abi_intr_disable(int);
486 static void	ioapic_abi_intr_setup(int, int);
487 static void	ioapic_abi_intr_teardown(int);
488 static void	ioapic_abi_intr_config(int,
489 		    enum intr_trigger, enum intr_polarity);
490 static int	ioapic_abi_intr_cpuid(int);
491 
492 static void	ioapic_abi_finalize(void);
493 static void	ioapic_abi_cleanup(void);
494 static void	ioapic_abi_setdefault(void);
495 static void	ioapic_abi_stabilize(void);
496 static void	ioapic_abi_initmap(void);
497 static void	ioapic_abi_rman_setup(struct rman *);
498 
499 static int	ioapic_abi_gsi_cpuid(int, int);
500 
501 struct machintr_abi MachIntrABI_IOAPIC = {
502 	MACHINTR_IOAPIC,
503 	.intr_disable	= ioapic_abi_intr_disable,
504 	.intr_enable	= ioapic_abi_intr_enable,
505 	.intr_setup	= ioapic_abi_intr_setup,
506 	.intr_teardown	= ioapic_abi_intr_teardown,
507 	.intr_config	= ioapic_abi_intr_config,
508 	.intr_cpuid	= ioapic_abi_intr_cpuid,
509 
510 	.finalize	= ioapic_abi_finalize,
511 	.cleanup	= ioapic_abi_cleanup,
512 	.setdefault	= ioapic_abi_setdefault,
513 	.stabilize	= ioapic_abi_stabilize,
514 	.initmap	= ioapic_abi_initmap,
515 	.rman_setup	= ioapic_abi_rman_setup
516 };
517 
518 static int	ioapic_abi_extint_irq = -1;
519 static int	ioapic_abi_line_irq_max;
520 static int	ioapic_abi_gsi_balance;
521 
522 struct ioapic_irqinfo	ioapic_irqs[IOAPIC_HWI_VECTORS];
523 
524 static void
525 ioapic_abi_intr_enable(int irq)
526 {
527 	if (irq < 0 || irq >= IOAPIC_HWI_VECTORS) {
528 		kprintf("ioapic_abi_intr_enable invalid irq %d\n", irq);
529 		return;
530 	}
531 	IOAPIC_INTREN(irq);
532 }
533 
534 static void
535 ioapic_abi_intr_disable(int irq)
536 {
537 	if (irq < 0 || irq >= IOAPIC_HWI_VECTORS) {
538 		kprintf("ioapic_abi_intr_disable invalid irq %d\n", irq);
539 		return;
540 	}
541 	IOAPIC_INTRDIS(irq);
542 }
543 
544 static void
545 ioapic_abi_finalize(void)
546 {
547 	KKASSERT(MachIntrABI.type == MACHINTR_IOAPIC);
548 	KKASSERT(ioapic_enable);
549 
550 	/*
551 	 * If an IMCR is present, program bit 0 to disconnect the 8259
552 	 * from the BSP.
553 	 */
554 	if (imcr_present) {
555 		outb(0x22, 0x70);	/* select IMCR */
556 		outb(0x23, 0x01);	/* disconnect 8259 */
557 	}
558 }
559 
560 /*
561  * This routine is called after physical interrupts are enabled but before
562  * the critical section is released.  We need to clean out any interrupts
563  * that had already been posted to the cpu.
564  */
565 static void
566 ioapic_abi_cleanup(void)
567 {
568 	bzero(mdcpu->gd_ipending, sizeof(mdcpu->gd_ipending));
569 }
570 
571 /* Must never be called */
572 static void
573 ioapic_abi_stabilize(void)
574 {
575 	panic("ioapic_stabilize is called\n");
576 }
577 
578 static void
579 ioapic_abi_intr_setup(int intr, int flags)
580 {
581 	int vector, select;
582 	uint32_t value;
583 	register_t ef;
584 
585 	KKASSERT(intr >= 0 && intr < IOAPIC_HWI_VECTORS &&
586 	    intr != IOAPIC_HWI_SYSCALL);
587 	KKASSERT(ioapic_irqs[intr].io_addr != NULL);
588 
589 	ef = read_rflags();
590 	cpu_disable_intr();
591 
592 	vector = IDT_OFFSET + intr;
593 
594 	/*
595 	 * Now reprogram the vector in the IO APIC.  In order to avoid
596 	 * losing an EOI for a level interrupt, which is vector based,
597 	 * make sure that the IO APIC is programmed for edge-triggering
598 	 * first, then reprogrammed with the new vector.  This should
599 	 * clear the IRR bit.
600 	 */
601 	imen_lock();
602 
603 	select = ioapic_irqs[intr].io_idx;
604 	value = ioapic_read(ioapic_irqs[intr].io_addr, select);
605 	value |= IOART_INTMSET;
606 
607 	ioapic_write(ioapic_irqs[intr].io_addr, select,
608 	    (value & ~APIC_TRIGMOD_MASK));
609 	ioapic_write(ioapic_irqs[intr].io_addr, select,
610 	    (value & ~IOART_INTVEC) | vector);
611 
612 	imen_unlock();
613 
614 	machintr_intr_enable(intr);
615 
616 	write_rflags(ef);
617 }
618 
619 static void
620 ioapic_abi_intr_teardown(int intr)
621 {
622 	int vector, select;
623 	uint32_t value;
624 	register_t ef;
625 
626 	KKASSERT(intr >= 0 && intr < IOAPIC_HWI_VECTORS &&
627 	    intr != IOAPIC_HWI_SYSCALL);
628 	KKASSERT(ioapic_irqs[intr].io_addr != NULL);
629 
630 	ef = read_rflags();
631 	cpu_disable_intr();
632 
633 	/*
634 	 * Teardown an interrupt vector.  The vector should already be
635 	 * installed in the cpu's IDT, but make sure.
636 	 */
637 	machintr_intr_disable(intr);
638 
639 	vector = IDT_OFFSET + intr;
640 
641 	/*
642 	 * In order to avoid losing an EOI for a level interrupt, which
643 	 * is vector based, make sure that the IO APIC is programmed for
644 	 * edge-triggering first, then reprogrammed with the new vector.
645 	 * This should clear the IRR bit.
646 	 */
647 	imen_lock();
648 
649 	select = ioapic_irqs[intr].io_idx;
650 	value = ioapic_read(ioapic_irqs[intr].io_addr, select);
651 
652 	ioapic_write(ioapic_irqs[intr].io_addr, select,
653 	    (value & ~APIC_TRIGMOD_MASK));
654 	ioapic_write(ioapic_irqs[intr].io_addr, select,
655 	    (value & ~IOART_INTVEC) | vector);
656 
657 	imen_unlock();
658 
659 	write_rflags(ef);
660 }
661 
662 static void
663 ioapic_abi_setdefault(void)
664 {
665 	int intr;
666 
667 	for (intr = 0; intr < IOAPIC_HWI_VECTORS; ++intr) {
668 		if (intr == IOAPIC_HWI_SYSCALL)
669 			continue;
670 		setidt(IDT_OFFSET + intr, ioapic_intr[intr], SDT_SYSIGT,
671 		       SEL_KPL, 0);
672 	}
673 }
674 
675 static void
676 ioapic_abi_initmap(void)
677 {
678 	int cpu;
679 
680 	kgetenv_int("hw.ioapic.gsi.balance", &ioapic_abi_gsi_balance);
681 
682 	/*
683 	 * NOTE: ncpus is not ready yet
684 	 */
685 	for (cpu = 0; cpu < MAXCPU; ++cpu) {
686 		int i;
687 
688 		for (i = 0; i < IOAPIC_HWI_VECTORS; ++i)
689 			ioapic_irqmaps[cpu][i].im_gsi = -1;
690 		ioapic_irqmaps[cpu][IOAPIC_HWI_SYSCALL].im_type =
691 		    IOAPIC_IMT_SYSCALL;
692 	}
693 }
694 
695 void
696 ioapic_abi_set_irqmap(int irq, int gsi, enum intr_trigger trig,
697     enum intr_polarity pola)
698 {
699 	struct ioapic_irqinfo *info;
700 	struct ioapic_irqmap *map;
701 	void *ioaddr;
702 	int pin, cpuid;
703 
704 	KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL);
705 	KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW);
706 
707 	KKASSERT(irq >= 0 && irq < IOAPIC_HWI_VECTORS);
708 	if (irq > ioapic_abi_line_irq_max)
709 		ioapic_abi_line_irq_max = irq;
710 
711 	cpuid = ioapic_abi_gsi_cpuid(irq, gsi);
712 
713 	map = &ioapic_irqmaps[cpuid][irq];
714 
715 	KKASSERT(map->im_type == IOAPIC_IMT_UNUSED);
716 	map->im_type = IOAPIC_IMT_LINE;
717 
718 	map->im_gsi = gsi;
719 	map->im_trig = trig;
720 	map->im_pola = pola;
721 
722 	if (bootverbose) {
723 		kprintf("IOAPIC: irq %d -> gsi %d %s/%s\n",
724 			irq, map->im_gsi,
725 			intr_str_trigger(map->im_trig),
726 			intr_str_polarity(map->im_pola));
727 	}
728 
729 	pin = ioapic_gsi_pin(map->im_gsi);
730 	ioaddr = ioapic_gsi_ioaddr(map->im_gsi);
731 
732 	info = &ioapic_irqs[irq];
733 
734 	imen_lock();
735 
736 	info->io_addr = ioaddr;
737 	info->io_idx = IOAPIC_REDTBL + (2 * pin);
738 	info->io_flags = IOAPIC_IRQI_FLAG_MASKED;
739 	if (map->im_trig == INTR_TRIGGER_LEVEL)
740 		info->io_flags |= IOAPIC_IRQI_FLAG_LEVEL;
741 
742 	ioapic_pin_setup(ioaddr, pin, IDT_OFFSET + irq,
743 	    map->im_trig, map->im_pola, cpuid);
744 
745 	imen_unlock();
746 }
747 
748 void
749 ioapic_abi_fixup_irqmap(void)
750 {
751 	int cpu;
752 
753 	for (cpu = 0; cpu < ncpus; ++cpu) {
754 		int i;
755 
756 		for (i = 0; i < ISA_IRQ_CNT; ++i) {
757 			struct ioapic_irqmap *map = &ioapic_irqmaps[cpu][i];
758 
759 			if (map->im_type == IOAPIC_IMT_UNUSED) {
760 				map->im_type = IOAPIC_IMT_RESERVED;
761 				if (bootverbose) {
762 					kprintf("IOAPIC: "
763 					    "cpu%d irq %d reserved\n", cpu, i);
764 				}
765 			}
766 		}
767 	}
768 
769 	ioapic_abi_line_irq_max += 1;
770 	if (bootverbose)
771 		kprintf("IOAPIC: line irq max %d\n", ioapic_abi_line_irq_max);
772 }
773 
774 int
775 ioapic_abi_find_gsi(int gsi, enum intr_trigger trig, enum intr_polarity pola)
776 {
777 	int cpu;
778 
779 	KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL);
780 	KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW);
781 
782 	for (cpu = 0; cpu < ncpus; ++cpu) {
783 		int irq;
784 
785 		for (irq = 0; irq < ioapic_abi_line_irq_max; ++irq) {
786 			const struct ioapic_irqmap *map =
787 			    &ioapic_irqmaps[cpu][irq];
788 
789 			if (map->im_gsi == gsi) {
790 				KKASSERT(map->im_type == IOAPIC_IMT_LINE);
791 
792 				if (map->im_flags & IOAPIC_IMF_CONF) {
793 					if (map->im_trig != trig ||
794 					    map->im_pola != pola)
795 						return -1;
796 				}
797 				return irq;
798 			}
799 		}
800 	}
801 	return -1;
802 }
803 
804 int
805 ioapic_abi_find_irq(int irq, enum intr_trigger trig, enum intr_polarity pola)
806 {
807 	int cpu;
808 
809 	KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL);
810 	KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW);
811 
812 	if (irq < 0 || irq >= ioapic_abi_line_irq_max)
813 		return -1;
814 
815 	for (cpu = 0; cpu < ncpus; ++cpu) {
816 		const struct ioapic_irqmap *map = &ioapic_irqmaps[cpu][irq];
817 
818 		if (map->im_type == IOAPIC_IMT_LINE) {
819 			if (map->im_flags & IOAPIC_IMF_CONF) {
820 				if (map->im_trig != trig ||
821 				    map->im_pola != pola)
822 					return -1;
823 			}
824 			return irq;
825 		}
826 	}
827 	return -1;
828 }
829 
830 static void
831 ioapic_abi_intr_config(int irq, enum intr_trigger trig, enum intr_polarity pola)
832 {
833 	struct ioapic_irqinfo *info;
834 	struct ioapic_irqmap *map = NULL;
835 	void *ioaddr;
836 	int pin, cpuid;
837 
838 	KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL);
839 	KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW);
840 
841 	KKASSERT(irq >= 0 && irq < ioapic_abi_line_irq_max);
842 	for (cpuid = 0; cpuid < ncpus; ++cpuid) {
843 		map = &ioapic_irqmaps[cpuid][irq];
844 		if (map->im_type == IOAPIC_IMT_LINE)
845 			break;
846 	}
847 	KKASSERT(cpuid < ncpus);
848 
849 #ifdef notyet
850 	if (map->im_flags & IOAPIC_IMF_CONF) {
851 		if (trig != map->im_trig) {
852 			panic("ioapic_intr_config: trig %s -> %s\n",
853 			      intr_str_trigger(map->im_trig),
854 			      intr_str_trigger(trig));
855 		}
856 		if (pola != map->im_pola) {
857 			panic("ioapic_intr_config: pola %s -> %s\n",
858 			      intr_str_polarity(map->im_pola),
859 			      intr_str_polarity(pola));
860 		}
861 		return;
862 	}
863 #endif
864 	map->im_flags |= IOAPIC_IMF_CONF;
865 
866 	if (trig == map->im_trig && pola == map->im_pola)
867 		return;
868 
869 	if (bootverbose) {
870 		kprintf("IOAPIC: irq %d, gsi %d %s/%s -> %s/%s\n",
871 			irq, map->im_gsi,
872 			intr_str_trigger(map->im_trig),
873 			intr_str_polarity(map->im_pola),
874 			intr_str_trigger(trig),
875 			intr_str_polarity(pola));
876 	}
877 	map->im_trig = trig;
878 	map->im_pola = pola;
879 
880 	pin = ioapic_gsi_pin(map->im_gsi);
881 	ioaddr = ioapic_gsi_ioaddr(map->im_gsi);
882 
883 	info = &ioapic_irqs[irq];
884 
885 	imen_lock();
886 
887 	info->io_flags &= ~IOAPIC_IRQI_FLAG_LEVEL;
888 	if (map->im_trig == INTR_TRIGGER_LEVEL)
889 		info->io_flags |= IOAPIC_IRQI_FLAG_LEVEL;
890 
891 	ioapic_pin_setup(ioaddr, pin, IDT_OFFSET + irq,
892 	    map->im_trig, map->im_pola, cpuid);
893 
894 	imen_unlock();
895 }
896 
897 int
898 ioapic_abi_extint_irqmap(int irq)
899 {
900 	struct ioapic_irqinfo *info;
901 	struct ioapic_irqmap *map;
902 	void *ioaddr;
903 	int pin, error, vec;
904 
905 	/* XXX only irq0 is allowed */
906 	KKASSERT(irq == 0);
907 
908 	vec = IDT_OFFSET + irq;
909 
910 	if (ioapic_abi_extint_irq == irq)
911 		return 0;
912 	else if (ioapic_abi_extint_irq >= 0)
913 		return EEXIST;
914 
915 	error = icu_ioapic_extint(irq, vec);
916 	if (error)
917 		return error;
918 
919 	/* ExtINT is always targeted to cpu0 */
920 	map = &ioapic_irqmaps[0][irq];
921 
922 	KKASSERT(map->im_type == IOAPIC_IMT_RESERVED ||
923 		 map->im_type == IOAPIC_IMT_LINE);
924 	if (map->im_type == IOAPIC_IMT_LINE) {
925 		if (map->im_flags & IOAPIC_IMF_CONF)
926 			return EEXIST;
927 	}
928 	ioapic_abi_extint_irq = irq;
929 
930 	map->im_type = IOAPIC_IMT_LINE;
931 	map->im_trig = INTR_TRIGGER_EDGE;
932 	map->im_pola = INTR_POLARITY_HIGH;
933 	map->im_flags = IOAPIC_IMF_CONF;
934 
935 	map->im_gsi = ioapic_extpin_gsi();
936 	KKASSERT(map->im_gsi >= 0);
937 
938 	if (bootverbose) {
939 		kprintf("IOAPIC: irq %d -> extint gsi %d %s/%s\n",
940 			irq, map->im_gsi,
941 			intr_str_trigger(map->im_trig),
942 			intr_str_polarity(map->im_pola));
943 	}
944 
945 	pin = ioapic_gsi_pin(map->im_gsi);
946 	ioaddr = ioapic_gsi_ioaddr(map->im_gsi);
947 
948 	info = &ioapic_irqs[irq];
949 
950 	imen_lock();
951 
952 	info->io_addr = ioaddr;
953 	info->io_idx = IOAPIC_REDTBL + (2 * pin);
954 	info->io_flags = IOAPIC_IRQI_FLAG_MASKED;
955 
956 	ioapic_extpin_setup(ioaddr, pin, vec);
957 
958 	imen_unlock();
959 
960 	return 0;
961 }
962 
963 static int
964 ioapic_abi_intr_cpuid(int irq)
965 {
966 	const struct ioapic_irqmap *map = NULL;
967 	int cpuid;
968 
969 	KKASSERT(irq >= 0 && irq < ioapic_abi_line_irq_max);
970 
971 	for (cpuid = 0; cpuid < ncpus; ++cpuid) {
972 		map = &ioapic_irqmaps[cpuid][irq];
973 		if (map->im_type == IOAPIC_IMT_LINE)
974 			return cpuid;
975 	}
976 
977 	/* XXX some drivers tries to peek at reserved IRQs */
978 	for (cpuid = 0; cpuid < ncpus; ++cpuid) {
979 		map = &ioapic_irqmaps[cpuid][irq];
980 		KKASSERT(map->im_type == IOAPIC_IMT_RESERVED);
981 	}
982 	return 0;
983 }
984 
985 static int
986 ioapic_abi_gsi_cpuid(int irq, int gsi)
987 {
988 	char envpath[32];
989 	int cpuid = -1;
990 
991 	KKASSERT(gsi >= 0);
992 
993 	if (irq == 0 || gsi == 0) {
994 		if (bootverbose) {
995 			kprintf("IOAPIC: irq %d, gsi %d -> cpu0 (0)\n",
996 			    irq, gsi);
997 		}
998 		return 0;
999 	}
1000 
1001 	if (irq == acpi_sci_irqno()) {
1002 		if (bootverbose) {
1003 			kprintf("IOAPIC: irq %d, gsi %d -> cpu0 (sci)\n",
1004 			    irq, gsi);
1005 		}
1006 		return 0;
1007 	}
1008 
1009 	ksnprintf(envpath, sizeof(envpath), "hw.ioapic.gsi.%d.cpu", gsi);
1010 	kgetenv_int(envpath, &cpuid);
1011 
1012 	if (cpuid < 0) {
1013 		if (!ioapic_abi_gsi_balance) {
1014 			if (bootverbose) {
1015 				kprintf("IOAPIC: irq %d, gsi %d -> cpu0 "
1016 				    "(fixed)\n", irq, gsi);
1017 			}
1018 			return 0;
1019 		}
1020 
1021 		cpuid = gsi % ncpus;
1022 		if (bootverbose) {
1023 			kprintf("IOAPIC: irq %d, gsi %d -> cpu%d (auto)\n",
1024 			    irq, gsi, cpuid);
1025 		}
1026 	} else if (cpuid >= ncpus) {
1027 		cpuid = ncpus - 1;
1028 		if (bootverbose) {
1029 			kprintf("IOAPIC: irq %d, gsi %d -> cpu%d (fixup)\n",
1030 			    irq, gsi, cpuid);
1031 		}
1032 	} else {
1033 		if (bootverbose) {
1034 			kprintf("IOAPIC: irq %d, gsi %d -> cpu%d (user)\n",
1035 			    irq, gsi, cpuid);
1036 		}
1037 	}
1038 	return cpuid;
1039 }
1040 
1041 static void
1042 ioapic_abi_rman_setup(struct rman *rm)
1043 {
1044 	int start, end, i;
1045 
1046 	KASSERT(rm->rm_cpuid >= 0 && rm->rm_cpuid < MAXCPU,
1047 	    ("invalid rman cpuid %d", rm->rm_cpuid));
1048 
1049 	start = end = -1;
1050 	for (i = 0; i < IOAPIC_HWI_VECTORS; ++i) {
1051 		const struct ioapic_irqmap *map =
1052 		    &ioapic_irqmaps[rm->rm_cpuid][i];
1053 
1054 		if (start < 0) {
1055 			if (IOAPIC_IMT_ISHWI(map))
1056 				start = end = i;
1057 		} else {
1058 			if (IOAPIC_IMT_ISHWI(map)) {
1059 				end = i;
1060 			} else {
1061 				KKASSERT(end >= 0);
1062 				if (bootverbose) {
1063 					kprintf("IOAPIC: rman cpu%d %d - %d\n",
1064 					    rm->rm_cpuid, start, end);
1065 				}
1066 				if (rman_manage_region(rm, start, end)) {
1067 					panic("rman_manage_region"
1068 					    "(cpu%d %d - %d)", rm->rm_cpuid,
1069 					    start, end);
1070 				}
1071 				start = end = -1;
1072 			}
1073 		}
1074 	}
1075 	if (start >= 0) {
1076 		KKASSERT(end >= 0);
1077 		if (bootverbose) {
1078 			kprintf("IOAPIC: rman cpu%d %d - %d\n",
1079 			    rm->rm_cpuid, start, end);
1080 		}
1081 		if (rman_manage_region(rm, start, end)) {
1082 			panic("rman_manage_region(cpu%d %d - %d)",
1083 			    rm->rm_cpuid, start, end);
1084 		}
1085 	}
1086 }
1087