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