xref: /dragonfly/sys/platform/pc64/apic/ioapic_abi.c (revision 474ba684)
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 
50 #include <machine/smp.h>
51 #include <machine/segments.h>
52 #include <machine/md_var.h>
53 #include <machine/intr_machdep.h>
54 #include <machine_base/icu/icu.h>
55 #include <machine/globaldata.h>
56 
57 #include <sys/thread2.h>
58 
59 #include <machine_base/apic/ioapic_ipl.h>
60 
61 #ifdef SMP /* APIC-IO */
62 
63 extern inthand_t
64 	IDTVEC(ioapic_intr0),
65 	IDTVEC(ioapic_intr1),
66 	IDTVEC(ioapic_intr2),
67 	IDTVEC(ioapic_intr3),
68 	IDTVEC(ioapic_intr4),
69 	IDTVEC(ioapic_intr5),
70 	IDTVEC(ioapic_intr6),
71 	IDTVEC(ioapic_intr7),
72 	IDTVEC(ioapic_intr8),
73 	IDTVEC(ioapic_intr9),
74 	IDTVEC(ioapic_intr10),
75 	IDTVEC(ioapic_intr11),
76 	IDTVEC(ioapic_intr12),
77 	IDTVEC(ioapic_intr13),
78 	IDTVEC(ioapic_intr14),
79 	IDTVEC(ioapic_intr15),
80 	IDTVEC(ioapic_intr16),
81 	IDTVEC(ioapic_intr17),
82 	IDTVEC(ioapic_intr18),
83 	IDTVEC(ioapic_intr19),
84 	IDTVEC(ioapic_intr20),
85 	IDTVEC(ioapic_intr21),
86 	IDTVEC(ioapic_intr22),
87 	IDTVEC(ioapic_intr23),
88 	IDTVEC(ioapic_intr24),
89 	IDTVEC(ioapic_intr25),
90 	IDTVEC(ioapic_intr26),
91 	IDTVEC(ioapic_intr27),
92 	IDTVEC(ioapic_intr28),
93 	IDTVEC(ioapic_intr29),
94 	IDTVEC(ioapic_intr30),
95 	IDTVEC(ioapic_intr31),
96 	IDTVEC(ioapic_intr32),
97 	IDTVEC(ioapic_intr33),
98 	IDTVEC(ioapic_intr34),
99 	IDTVEC(ioapic_intr35),
100 	IDTVEC(ioapic_intr36),
101 	IDTVEC(ioapic_intr37),
102 	IDTVEC(ioapic_intr38),
103 	IDTVEC(ioapic_intr39),
104 	IDTVEC(ioapic_intr40),
105 	IDTVEC(ioapic_intr41),
106 	IDTVEC(ioapic_intr42),
107 	IDTVEC(ioapic_intr43),
108 	IDTVEC(ioapic_intr44),
109 	IDTVEC(ioapic_intr45),
110 	IDTVEC(ioapic_intr46),
111 	IDTVEC(ioapic_intr47),
112 	IDTVEC(ioapic_intr48),
113 	IDTVEC(ioapic_intr49),
114 	IDTVEC(ioapic_intr50),
115 	IDTVEC(ioapic_intr51),
116 	IDTVEC(ioapic_intr52),
117 	IDTVEC(ioapic_intr53),
118 	IDTVEC(ioapic_intr54),
119 	IDTVEC(ioapic_intr55),
120 	IDTVEC(ioapic_intr56),
121 	IDTVEC(ioapic_intr57),
122 	IDTVEC(ioapic_intr58),
123 	IDTVEC(ioapic_intr59),
124 	IDTVEC(ioapic_intr60),
125 	IDTVEC(ioapic_intr61),
126 	IDTVEC(ioapic_intr62),
127 	IDTVEC(ioapic_intr63),
128 	IDTVEC(ioapic_intr64),
129 	IDTVEC(ioapic_intr65),
130 	IDTVEC(ioapic_intr66),
131 	IDTVEC(ioapic_intr67),
132 	IDTVEC(ioapic_intr68),
133 	IDTVEC(ioapic_intr69),
134 	IDTVEC(ioapic_intr70),
135 	IDTVEC(ioapic_intr71),
136 	IDTVEC(ioapic_intr72),
137 	IDTVEC(ioapic_intr73),
138 	IDTVEC(ioapic_intr74),
139 	IDTVEC(ioapic_intr75),
140 	IDTVEC(ioapic_intr76),
141 	IDTVEC(ioapic_intr77),
142 	IDTVEC(ioapic_intr78),
143 	IDTVEC(ioapic_intr79),
144 	IDTVEC(ioapic_intr80),
145 	IDTVEC(ioapic_intr81),
146 	IDTVEC(ioapic_intr82),
147 	IDTVEC(ioapic_intr83),
148 	IDTVEC(ioapic_intr84),
149 	IDTVEC(ioapic_intr85),
150 	IDTVEC(ioapic_intr86),
151 	IDTVEC(ioapic_intr87),
152 	IDTVEC(ioapic_intr88),
153 	IDTVEC(ioapic_intr89),
154 	IDTVEC(ioapic_intr90),
155 	IDTVEC(ioapic_intr91),
156 	IDTVEC(ioapic_intr92),
157 	IDTVEC(ioapic_intr93),
158 	IDTVEC(ioapic_intr94),
159 	IDTVEC(ioapic_intr95),
160 	IDTVEC(ioapic_intr96),
161 	IDTVEC(ioapic_intr97),
162 	IDTVEC(ioapic_intr98),
163 	IDTVEC(ioapic_intr99),
164 	IDTVEC(ioapic_intr100),
165 	IDTVEC(ioapic_intr101),
166 	IDTVEC(ioapic_intr102),
167 	IDTVEC(ioapic_intr103),
168 	IDTVEC(ioapic_intr104),
169 	IDTVEC(ioapic_intr105),
170 	IDTVEC(ioapic_intr106),
171 	IDTVEC(ioapic_intr107),
172 	IDTVEC(ioapic_intr108),
173 	IDTVEC(ioapic_intr109),
174 	IDTVEC(ioapic_intr110),
175 	IDTVEC(ioapic_intr111),
176 	IDTVEC(ioapic_intr112),
177 	IDTVEC(ioapic_intr113),
178 	IDTVEC(ioapic_intr114),
179 	IDTVEC(ioapic_intr115),
180 	IDTVEC(ioapic_intr116),
181 	IDTVEC(ioapic_intr117),
182 	IDTVEC(ioapic_intr118),
183 	IDTVEC(ioapic_intr119),
184 	IDTVEC(ioapic_intr120),
185 	IDTVEC(ioapic_intr121),
186 	IDTVEC(ioapic_intr122),
187 	IDTVEC(ioapic_intr123),
188 	IDTVEC(ioapic_intr124),
189 	IDTVEC(ioapic_intr125),
190 	IDTVEC(ioapic_intr126),
191 	IDTVEC(ioapic_intr127),
192 	IDTVEC(ioapic_intr128),
193 	IDTVEC(ioapic_intr129),
194 	IDTVEC(ioapic_intr130),
195 	IDTVEC(ioapic_intr131),
196 	IDTVEC(ioapic_intr132),
197 	IDTVEC(ioapic_intr133),
198 	IDTVEC(ioapic_intr134),
199 	IDTVEC(ioapic_intr135),
200 	IDTVEC(ioapic_intr136),
201 	IDTVEC(ioapic_intr137),
202 	IDTVEC(ioapic_intr138),
203 	IDTVEC(ioapic_intr139),
204 	IDTVEC(ioapic_intr140),
205 	IDTVEC(ioapic_intr141),
206 	IDTVEC(ioapic_intr142),
207 	IDTVEC(ioapic_intr143),
208 	IDTVEC(ioapic_intr144),
209 	IDTVEC(ioapic_intr145),
210 	IDTVEC(ioapic_intr146),
211 	IDTVEC(ioapic_intr147),
212 	IDTVEC(ioapic_intr148),
213 	IDTVEC(ioapic_intr149),
214 	IDTVEC(ioapic_intr150),
215 	IDTVEC(ioapic_intr151),
216 	IDTVEC(ioapic_intr152),
217 	IDTVEC(ioapic_intr153),
218 	IDTVEC(ioapic_intr154),
219 	IDTVEC(ioapic_intr155),
220 	IDTVEC(ioapic_intr156),
221 	IDTVEC(ioapic_intr157),
222 	IDTVEC(ioapic_intr158),
223 	IDTVEC(ioapic_intr159),
224 	IDTVEC(ioapic_intr160),
225 	IDTVEC(ioapic_intr161),
226 	IDTVEC(ioapic_intr162),
227 	IDTVEC(ioapic_intr163),
228 	IDTVEC(ioapic_intr164),
229 	IDTVEC(ioapic_intr165),
230 	IDTVEC(ioapic_intr166),
231 	IDTVEC(ioapic_intr167),
232 	IDTVEC(ioapic_intr168),
233 	IDTVEC(ioapic_intr169),
234 	IDTVEC(ioapic_intr170),
235 	IDTVEC(ioapic_intr171),
236 	IDTVEC(ioapic_intr172),
237 	IDTVEC(ioapic_intr173),
238 	IDTVEC(ioapic_intr174),
239 	IDTVEC(ioapic_intr175),
240 	IDTVEC(ioapic_intr176),
241 	IDTVEC(ioapic_intr177),
242 	IDTVEC(ioapic_intr178),
243 	IDTVEC(ioapic_intr179),
244 	IDTVEC(ioapic_intr180),
245 	IDTVEC(ioapic_intr181),
246 	IDTVEC(ioapic_intr182),
247 	IDTVEC(ioapic_intr183),
248 	IDTVEC(ioapic_intr184),
249 	IDTVEC(ioapic_intr185),
250 	IDTVEC(ioapic_intr186),
251 	IDTVEC(ioapic_intr187),
252 	IDTVEC(ioapic_intr188),
253 	IDTVEC(ioapic_intr189),
254 	IDTVEC(ioapic_intr190),
255 	IDTVEC(ioapic_intr191);
256 
257 static inthand_t *ioapic_intr[IOAPIC_HWI_VECTORS] = {
258 	&IDTVEC(ioapic_intr0),
259 	&IDTVEC(ioapic_intr1),
260 	&IDTVEC(ioapic_intr2),
261 	&IDTVEC(ioapic_intr3),
262 	&IDTVEC(ioapic_intr4),
263 	&IDTVEC(ioapic_intr5),
264 	&IDTVEC(ioapic_intr6),
265 	&IDTVEC(ioapic_intr7),
266 	&IDTVEC(ioapic_intr8),
267 	&IDTVEC(ioapic_intr9),
268 	&IDTVEC(ioapic_intr10),
269 	&IDTVEC(ioapic_intr11),
270 	&IDTVEC(ioapic_intr12),
271 	&IDTVEC(ioapic_intr13),
272 	&IDTVEC(ioapic_intr14),
273 	&IDTVEC(ioapic_intr15),
274 	&IDTVEC(ioapic_intr16),
275 	&IDTVEC(ioapic_intr17),
276 	&IDTVEC(ioapic_intr18),
277 	&IDTVEC(ioapic_intr19),
278 	&IDTVEC(ioapic_intr20),
279 	&IDTVEC(ioapic_intr21),
280 	&IDTVEC(ioapic_intr22),
281 	&IDTVEC(ioapic_intr23),
282 	&IDTVEC(ioapic_intr24),
283 	&IDTVEC(ioapic_intr25),
284 	&IDTVEC(ioapic_intr26),
285 	&IDTVEC(ioapic_intr27),
286 	&IDTVEC(ioapic_intr28),
287 	&IDTVEC(ioapic_intr29),
288 	&IDTVEC(ioapic_intr30),
289 	&IDTVEC(ioapic_intr31),
290 	&IDTVEC(ioapic_intr32),
291 	&IDTVEC(ioapic_intr33),
292 	&IDTVEC(ioapic_intr34),
293 	&IDTVEC(ioapic_intr35),
294 	&IDTVEC(ioapic_intr36),
295 	&IDTVEC(ioapic_intr37),
296 	&IDTVEC(ioapic_intr38),
297 	&IDTVEC(ioapic_intr39),
298 	&IDTVEC(ioapic_intr40),
299 	&IDTVEC(ioapic_intr41),
300 	&IDTVEC(ioapic_intr42),
301 	&IDTVEC(ioapic_intr43),
302 	&IDTVEC(ioapic_intr44),
303 	&IDTVEC(ioapic_intr45),
304 	&IDTVEC(ioapic_intr46),
305 	&IDTVEC(ioapic_intr47),
306 	&IDTVEC(ioapic_intr48),
307 	&IDTVEC(ioapic_intr49),
308 	&IDTVEC(ioapic_intr50),
309 	&IDTVEC(ioapic_intr51),
310 	&IDTVEC(ioapic_intr52),
311 	&IDTVEC(ioapic_intr53),
312 	&IDTVEC(ioapic_intr54),
313 	&IDTVEC(ioapic_intr55),
314 	&IDTVEC(ioapic_intr56),
315 	&IDTVEC(ioapic_intr57),
316 	&IDTVEC(ioapic_intr58),
317 	&IDTVEC(ioapic_intr59),
318 	&IDTVEC(ioapic_intr60),
319 	&IDTVEC(ioapic_intr61),
320 	&IDTVEC(ioapic_intr62),
321 	&IDTVEC(ioapic_intr63),
322 	&IDTVEC(ioapic_intr64),
323 	&IDTVEC(ioapic_intr65),
324 	&IDTVEC(ioapic_intr66),
325 	&IDTVEC(ioapic_intr67),
326 	&IDTVEC(ioapic_intr68),
327 	&IDTVEC(ioapic_intr69),
328 	&IDTVEC(ioapic_intr70),
329 	&IDTVEC(ioapic_intr71),
330 	&IDTVEC(ioapic_intr72),
331 	&IDTVEC(ioapic_intr73),
332 	&IDTVEC(ioapic_intr74),
333 	&IDTVEC(ioapic_intr75),
334 	&IDTVEC(ioapic_intr76),
335 	&IDTVEC(ioapic_intr77),
336 	&IDTVEC(ioapic_intr78),
337 	&IDTVEC(ioapic_intr79),
338 	&IDTVEC(ioapic_intr80),
339 	&IDTVEC(ioapic_intr81),
340 	&IDTVEC(ioapic_intr82),
341 	&IDTVEC(ioapic_intr83),
342 	&IDTVEC(ioapic_intr84),
343 	&IDTVEC(ioapic_intr85),
344 	&IDTVEC(ioapic_intr86),
345 	&IDTVEC(ioapic_intr87),
346 	&IDTVEC(ioapic_intr88),
347 	&IDTVEC(ioapic_intr89),
348 	&IDTVEC(ioapic_intr90),
349 	&IDTVEC(ioapic_intr91),
350 	&IDTVEC(ioapic_intr92),
351 	&IDTVEC(ioapic_intr93),
352 	&IDTVEC(ioapic_intr94),
353 	&IDTVEC(ioapic_intr95),
354 	&IDTVEC(ioapic_intr96),
355 	&IDTVEC(ioapic_intr97),
356 	&IDTVEC(ioapic_intr98),
357 	&IDTVEC(ioapic_intr99),
358 	&IDTVEC(ioapic_intr100),
359 	&IDTVEC(ioapic_intr101),
360 	&IDTVEC(ioapic_intr102),
361 	&IDTVEC(ioapic_intr103),
362 	&IDTVEC(ioapic_intr104),
363 	&IDTVEC(ioapic_intr105),
364 	&IDTVEC(ioapic_intr106),
365 	&IDTVEC(ioapic_intr107),
366 	&IDTVEC(ioapic_intr108),
367 	&IDTVEC(ioapic_intr109),
368 	&IDTVEC(ioapic_intr110),
369 	&IDTVEC(ioapic_intr111),
370 	&IDTVEC(ioapic_intr112),
371 	&IDTVEC(ioapic_intr113),
372 	&IDTVEC(ioapic_intr114),
373 	&IDTVEC(ioapic_intr115),
374 	&IDTVEC(ioapic_intr116),
375 	&IDTVEC(ioapic_intr117),
376 	&IDTVEC(ioapic_intr118),
377 	&IDTVEC(ioapic_intr119),
378 	&IDTVEC(ioapic_intr120),
379 	&IDTVEC(ioapic_intr121),
380 	&IDTVEC(ioapic_intr122),
381 	&IDTVEC(ioapic_intr123),
382 	&IDTVEC(ioapic_intr124),
383 	&IDTVEC(ioapic_intr125),
384 	&IDTVEC(ioapic_intr126),
385 	&IDTVEC(ioapic_intr127),
386 	&IDTVEC(ioapic_intr128),
387 	&IDTVEC(ioapic_intr129),
388 	&IDTVEC(ioapic_intr130),
389 	&IDTVEC(ioapic_intr131),
390 	&IDTVEC(ioapic_intr132),
391 	&IDTVEC(ioapic_intr133),
392 	&IDTVEC(ioapic_intr134),
393 	&IDTVEC(ioapic_intr135),
394 	&IDTVEC(ioapic_intr136),
395 	&IDTVEC(ioapic_intr137),
396 	&IDTVEC(ioapic_intr138),
397 	&IDTVEC(ioapic_intr139),
398 	&IDTVEC(ioapic_intr140),
399 	&IDTVEC(ioapic_intr141),
400 	&IDTVEC(ioapic_intr142),
401 	&IDTVEC(ioapic_intr143),
402 	&IDTVEC(ioapic_intr144),
403 	&IDTVEC(ioapic_intr145),
404 	&IDTVEC(ioapic_intr146),
405 	&IDTVEC(ioapic_intr147),
406 	&IDTVEC(ioapic_intr148),
407 	&IDTVEC(ioapic_intr149),
408 	&IDTVEC(ioapic_intr150),
409 	&IDTVEC(ioapic_intr151),
410 	&IDTVEC(ioapic_intr152),
411 	&IDTVEC(ioapic_intr153),
412 	&IDTVEC(ioapic_intr154),
413 	&IDTVEC(ioapic_intr155),
414 	&IDTVEC(ioapic_intr156),
415 	&IDTVEC(ioapic_intr157),
416 	&IDTVEC(ioapic_intr158),
417 	&IDTVEC(ioapic_intr159),
418 	&IDTVEC(ioapic_intr160),
419 	&IDTVEC(ioapic_intr161),
420 	&IDTVEC(ioapic_intr162),
421 	&IDTVEC(ioapic_intr163),
422 	&IDTVEC(ioapic_intr164),
423 	&IDTVEC(ioapic_intr165),
424 	&IDTVEC(ioapic_intr166),
425 	&IDTVEC(ioapic_intr167),
426 	&IDTVEC(ioapic_intr168),
427 	&IDTVEC(ioapic_intr169),
428 	&IDTVEC(ioapic_intr170),
429 	&IDTVEC(ioapic_intr171),
430 	&IDTVEC(ioapic_intr172),
431 	&IDTVEC(ioapic_intr173),
432 	&IDTVEC(ioapic_intr174),
433 	&IDTVEC(ioapic_intr175),
434 	&IDTVEC(ioapic_intr176),
435 	&IDTVEC(ioapic_intr177),
436 	&IDTVEC(ioapic_intr178),
437 	&IDTVEC(ioapic_intr179),
438 	&IDTVEC(ioapic_intr180),
439 	&IDTVEC(ioapic_intr181),
440 	&IDTVEC(ioapic_intr182),
441 	&IDTVEC(ioapic_intr183),
442 	&IDTVEC(ioapic_intr184),
443 	&IDTVEC(ioapic_intr185),
444 	&IDTVEC(ioapic_intr186),
445 	&IDTVEC(ioapic_intr187),
446 	&IDTVEC(ioapic_intr188),
447 	&IDTVEC(ioapic_intr189),
448 	&IDTVEC(ioapic_intr190),
449 	&IDTVEC(ioapic_intr191)
450 };
451 
452 #define IOAPIC_HWI_SYSCALL	(IDT_OFFSET_SYSCALL - IDT_OFFSET)
453 
454 static struct ioapic_irqmap {
455 	int			im_type;	/* IOAPIC_IMT_ */
456 	enum intr_trigger	im_trig;
457 	int			im_gsi;
458 } ioapic_irqmaps[MAX_HARDINTS];	/* XXX MAX_HARDINTS may not be correct */
459 
460 #define IOAPIC_IMT_UNUSED	0
461 #define IOAPIC_IMT_RESERVED	1
462 #define IOAPIC_IMT_LINE		2
463 #define IOAPIC_IMT_SYSCALL	3
464 
465 extern void	IOAPIC_INTREN(int);
466 extern void	IOAPIC_INTRDIS(int);
467 
468 static int	ioapic_setvar(int, const void *);
469 static int	ioapic_getvar(int, void *);
470 static int	ioapic_vectorctl(int, int, int);
471 static void	ioapic_finalize(void);
472 static void	ioapic_cleanup(void);
473 static void	ioapic_setdefault(void);
474 static void	ioapic_stabilize(void);
475 static void	ioapic_initmap(void);
476 
477 static int	ioapic_imcr_present;
478 
479 struct machintr_abi MachIntrABI_IOAPIC = {
480 	MACHINTR_IOAPIC,
481 	.intrdis	= IOAPIC_INTRDIS,
482 	.intren		= IOAPIC_INTREN,
483 	.vectorctl	= ioapic_vectorctl,
484 	.setvar		= ioapic_setvar,
485 	.getvar		= ioapic_getvar,
486 	.finalize	= ioapic_finalize,
487 	.cleanup	= ioapic_cleanup,
488 	.setdefault	= ioapic_setdefault,
489 	.stabilize	= ioapic_stabilize,
490 	.initmap	= ioapic_initmap
491 };
492 
493 static int
494 ioapic_setvar(int varid, const void *buf)
495 {
496 	int error = 0;
497 
498 	switch(varid) {
499 	case MACHINTR_VAR_IMCR_PRESENT:
500 		ioapic_imcr_present = *(const int *)buf;
501 		break;
502 
503 	default:
504 		error = ENOENT;
505 		break;
506 	}
507 	return error;
508 }
509 
510 static int
511 ioapic_getvar(int varid, void *buf)
512 {
513 	int error = 0;
514 
515 	switch(varid) {
516 	case MACHINTR_VAR_IMCR_PRESENT:
517 		*(int *)buf = ioapic_imcr_present;
518 		break;
519 
520 	default:
521 		error = ENOENT;
522 		break;
523 	}
524 	return error;
525 }
526 
527 /*
528  * Called from ICU's finalize if I/O APIC is enabled, after BSP's LAPIC
529  * is initialized; some of the BSP's LAPIC configuration are adjusted.
530  *
531  * - disable 'pic mode'.
532  * - disable 'virtual wire mode'.
533  * - switch MachIntrABI
534  * - enable NMI.
535  */
536 static void
537 ioapic_finalize(void)
538 {
539 	register_t ef;
540 	uint32_t temp;
541 
542 	KKASSERT(MachIntrABI.type == MACHINTR_ICU);
543 	KKASSERT(apic_io_enable);
544 
545 	/*
546 	 * If an IMCR is present, program bit 0 to disconnect the 8259
547 	 * from the BSP.  The 8259 may still be connected to LINT0 on
548 	 * the BSP's LAPIC.
549 	 */
550 	if (ioapic_imcr_present) {
551 		outb(0x22, 0x70);	/* select IMCR */
552 		outb(0x23, 0x01);	/* disconnect 8259 */
553 	}
554 
555 	/*
556 	 * Setup LINT0 (the 8259 'virtual wire' connection).  We
557 	 * mask the interrupt, completing the disconnection of the
558 	 * 8259.
559 	 */
560 	temp = lapic->lvt_lint0;
561 	temp |= APIC_LVT_MASKED;
562 	lapic->lvt_lint0 = temp;
563 
564 	crit_enter();
565 
566 	ef = read_rflags();
567 	cpu_disable_intr();
568 
569 	/*
570 	 * 8259 is completely disconnected; switch to IOAPIC MachIntrABI
571 	 * and reconfigure the default IDT entries.
572 	 */
573 	MachIntrABI = MachIntrABI_IOAPIC;
574 	MachIntrABI.setdefault();
575 
576 	write_rflags(ef);
577 
578 	MachIntrABI.cleanup();
579 
580 	crit_exit();
581 
582 	/*
583 	 * Setup LINT1 to handle an NMI
584 	 */
585 	temp = lapic->lvt_lint1;
586 	temp &= ~APIC_LVT_MASKED;
587 	lapic->lvt_lint1 = temp;
588 
589 	if (bootverbose)
590 		apic_dump("ioapic_finalize()");
591 }
592 
593 /*
594  * This routine is called after physical interrupts are enabled but before
595  * the critical section is released.  We need to clean out any interrupts
596  * that had already been posted to the cpu.
597  */
598 static void
599 ioapic_cleanup(void)
600 {
601 	bzero(mdcpu->gd_ipending, sizeof(mdcpu->gd_ipending));
602 }
603 
604 /* Must never be called */
605 static void
606 ioapic_stabilize(void)
607 {
608 	panic("ioapic_stabilize is called\n");
609 }
610 
611 static int
612 ioapic_vectorctl(int op, int intr, int flags)
613 {
614 	int error;
615 	int vector;
616 	int select;
617 	uint32_t value;
618 	register_t ef;
619 
620 	if (intr < 0 || intr >= IOAPIC_HWI_VECTORS ||
621 	    intr == IOAPIC_HWI_SYSCALL)
622 		return EINVAL;
623 
624 	ef = read_rflags();
625 	cpu_disable_intr();
626 	error = 0;
627 
628 	switch(op) {
629 	case MACHINTR_VECTOR_SETUP:
630 		vector = IDT_OFFSET + intr;
631 		setidt(vector, ioapic_intr[intr], SDT_SYSIGT, SEL_KPL, 0);
632 
633 		/*
634 		 * Now reprogram the vector in the IO APIC.  In order to avoid
635 		 * losing an EOI for a level interrupt, which is vector based,
636 		 * make sure that the IO APIC is programmed for edge-triggering
637 		 * first, then reprogrammed with the new vector.  This should
638 		 * clear the IRR bit.
639 		 */
640 		if (int_to_apicintpin[intr].ioapic >= 0) {
641 			imen_lock();
642 
643 			select = int_to_apicintpin[intr].redirindex;
644 			value = ioapic_read(int_to_apicintpin[intr].apic_address,
645 					    select);
646 			value |= IOART_INTMSET;
647 
648 			ioapic_write(int_to_apicintpin[intr].apic_address,
649 				     select, (value & ~APIC_TRIGMOD_MASK));
650 			ioapic_write(int_to_apicintpin[intr].apic_address,
651 				     select, (value & ~IOART_INTVEC) | vector);
652 
653 			imen_unlock();
654 		}
655 
656 		machintr_intren(intr);
657 		break;
658 
659 	case MACHINTR_VECTOR_TEARDOWN:
660 		/*
661 		 * Teardown an interrupt vector.  The vector should already be
662 		 * installed in the cpu's IDT, but make sure.
663 		 */
664 		machintr_intrdis(intr);
665 
666 		vector = IDT_OFFSET + intr;
667 		setidt(vector, ioapic_intr[intr], SDT_SYSIGT, SEL_KPL, 0);
668 
669 		/*
670 		 * In order to avoid losing an EOI for a level interrupt, which
671 		 * is vector based, make sure that the IO APIC is programmed for
672 		 * edge-triggering first, then reprogrammed with the new vector.
673 		 * This should clear the IRR bit.
674 		 */
675 		if (int_to_apicintpin[intr].ioapic >= 0) {
676 			imen_lock();
677 
678 			select = int_to_apicintpin[intr].redirindex;
679 			value = ioapic_read(int_to_apicintpin[intr].apic_address,
680 					    select);
681 
682 			ioapic_write(int_to_apicintpin[intr].apic_address,
683 				     select, (value & ~APIC_TRIGMOD_MASK));
684 			ioapic_write(int_to_apicintpin[intr].apic_address,
685 				     select, (value & ~IOART_INTVEC) | vector);
686 
687 			imen_unlock();
688 		}
689 		break;
690 
691 	default:
692 		error = EOPNOTSUPP;
693 		break;
694 	}
695 
696 	write_rflags(ef);
697 	return error;
698 }
699 
700 static void
701 ioapic_setdefault(void)
702 {
703 	int intr;
704 
705 	for (intr = 0; intr < IOAPIC_HWI_VECTORS; ++intr) {
706 		if (intr == IOAPIC_HWI_SYSCALL)
707 			continue;
708 		setidt(IDT_OFFSET + intr, ioapic_intr[intr], SDT_SYSIGT,
709 		       SEL_KPL, 0);
710 	}
711 }
712 
713 /* XXX magic number */
714 static void
715 ioapic_initmap(void)
716 {
717 	int i;
718 
719 	for (i = 0; i < 16; ++i) {
720 		struct ioapic_irqmap *map = &ioapic_irqmaps[i];
721 
722 		map->im_type = IOAPIC_IMT_LINE;
723 		map->im_trig = INTR_TRIGGER_EDGE;
724 		map->im_gsi = i;
725 	}
726 	ioapic_irqmaps[IOAPIC_HWI_SYSCALL].im_type = IOAPIC_IMT_SYSCALL;
727 }
728 
729 #endif	/* SMP */
730