xref: /dragonfly/sys/platform/pc64/acpica/acpi_madt.c (revision e416ee21)
1 /*
2  * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Sepherosa Ziehau <sepherosa@gmail.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include <sys/param.h>
36 #include <sys/bus.h>
37 #include <sys/kernel.h>
38 #include <sys/systm.h>
39 
40 #include <machine_base/isa/isa_intr.h>
41 #include <machine_base/apic/lapic.h>
42 #include <machine_base/apic/ioapic.h>
43 #include <machine_base/apic/apicvar.h>
44 #include <machine_base/acpica/acpi_md_cpu.h>
45 
46 #include <contrib/dev/acpica/source/include/acpi.h>
47 
48 #include "acpi_sdt_var.h"
49 #include "acpi_sci_var.h"
50 
51 extern int naps;
52 
53 #define MADT_VPRINTF(fmt, arg...) \
54 do { \
55 	if (bootverbose) \
56 		kprintf("ACPI MADT: " fmt , ##arg); \
57 } while (0)
58 
59 #define MADT_INT_BUS_ISA	0
60 
61 typedef int			(*madt_iter_t)(void *,
62 				    const ACPI_SUBTABLE_HEADER *);
63 
64 static int			madt_check(vm_paddr_t);
65 static int			madt_iterate_entries(ACPI_TABLE_MADT *,
66 				    madt_iter_t, void *);
67 
68 static vm_paddr_t		madt_lapic_pass1(void);
69 static int			madt_lapic_pass2(int);
70 
71 static int			madt_lapic_enumerate(struct lapic_enumerator *);
72 static int			madt_lapic_probe(struct lapic_enumerator *);
73 
74 static void			madt_ioapic_enumerate(
75 				    struct ioapic_enumerator *);
76 static int			madt_ioapic_probe(struct ioapic_enumerator *);
77 
78 static vm_paddr_t		madt_phyaddr;
79 
80 static boolean_t		madt_use_x2apic = FALSE;
81 
82 u_int				cpu_id_to_acpi_id[NAPICID];
83 
84 static void
85 madt_probe(void)
86 {
87 	vm_paddr_t madt_paddr;
88 	int i;
89 
90 	for (i = 0; i < NAPICID; ++i)
91 		CPUID_TO_ACPIID(i) = (u_int)-1;
92 
93 	KKASSERT(madt_phyaddr == 0);
94 
95 	madt_paddr = sdt_search(ACPI_SIG_MADT);
96 	if (madt_paddr == 0) {
97 		kprintf("madt_probe: can't locate MADT\n");
98 		return;
99 	}
100 
101 	/* Preliminary checks */
102 	if (madt_check(madt_paddr)) {
103 		kprintf("madt_probe: madt_check failed\n");
104 		return;
105 	}
106 
107 	madt_phyaddr = madt_paddr;
108 }
109 SYSINIT(madt_probe, SI_BOOT2_PRESMP, SI_ORDER_SECOND, madt_probe, 0);
110 
111 static int
112 madt_check(vm_paddr_t madt_paddr)
113 {
114 	ACPI_TABLE_MADT *madt;
115 	int error = 0;
116 
117 	KKASSERT(madt_paddr != 0);
118 
119 	madt = sdt_sdth_map(madt_paddr);
120 	KKASSERT(madt != NULL);
121 
122 	/*
123 	 * MADT in ACPI specification 1.0 - 5.0
124 	 */
125 	if (madt->Header.Revision < 1 || madt->Header.Revision > 3) {
126 		kprintf("madt_check: unknown MADT revision %d\n",
127 			madt->Header.Revision);
128 	}
129 
130 	if (madt->Header.Length < sizeof(*madt)) {
131 		kprintf("madt_check: invalid MADT length %u\n",
132 			madt->Header.Length);
133 		error = EINVAL;
134 		goto back;
135 	}
136 back:
137 	sdt_sdth_unmap(&madt->Header);
138 	return error;
139 }
140 
141 static int
142 madt_iterate_entries(ACPI_TABLE_MADT *madt, madt_iter_t func, void *arg)
143 {
144 	int size, cur, error;
145 
146 	size = madt->Header.Length - sizeof(*madt);
147 	cur = 0;
148 	error = 0;
149 
150 	while (size - cur > sizeof(ACPI_SUBTABLE_HEADER)) {
151 		const ACPI_SUBTABLE_HEADER *ent;
152 
153 		ent = (const ACPI_SUBTABLE_HEADER *)
154 		    ((char *)madt + sizeof(*madt) + cur);
155 		if (ent->Length < sizeof(*ent)) {
156 			kprintf("madt_iterate_entries: invalid MADT "
157 				"entry len %d\n", ent->Length);
158 			error = EINVAL;
159 			break;
160 		}
161 		if (ent->Length > (size - cur)) {
162 			kprintf("madt_iterate_entries: invalid MADT "
163 				"entry len %d, > table length\n", ent->Length);
164 			error = EINVAL;
165 			break;
166 		}
167 
168 		cur += ent->Length;
169 
170 		/*
171 		 * Only Local APIC, I/O APIC and Interrupt Source Override
172 		 * are defined in ACPI specification 1.0 - 5.0
173 		 */
174 		switch (ent->Type) {
175 		case ACPI_MADT_TYPE_LOCAL_APIC:
176 			if (ent->Length < sizeof(ACPI_MADT_LOCAL_APIC)) {
177 				kprintf("madt_iterate_entries: invalid MADT "
178 					"lapic entry len %d\n", ent->Length);
179 				error = EINVAL;
180 			}
181 			break;
182 
183 		case ACPI_MADT_TYPE_LOCAL_X2APIC:
184 			if (ent->Length < sizeof(ACPI_MADT_LOCAL_X2APIC)) {
185 				kprintf("madt_iterate_entries: invalid MADT "
186 					"x2apic entry len %d\n", ent->Length);
187 				error = EINVAL;
188 			}
189 			break;
190 
191 		case ACPI_MADT_TYPE_IO_APIC:
192 			if (ent->Length < sizeof(ACPI_MADT_IO_APIC)) {
193 				kprintf("madt_iterate_entries: invalid MADT "
194 					"ioapic entry len %d\n", ent->Length);
195 				error = EINVAL;
196 			}
197 			break;
198 
199 		case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
200 			if (ent->Length < sizeof(ACPI_MADT_INTERRUPT_OVERRIDE)) {
201 				kprintf("madt_iterate_entries: invalid MADT "
202 					"intsrc entry len %d\n",
203 					ent->Length);
204 				error = EINVAL;
205 			}
206 			break;
207 		}
208 		if (error)
209 			break;
210 
211 		error = func(arg, ent);
212 		if (error)
213 			break;
214 
215 		ent = ACPI_ADD_PTR(ACPI_SUBTABLE_HEADER, ent, ent->Length);
216 	}
217 	return error;
218 }
219 
220 static int
221 madt_lapic_pass1_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent)
222 {
223 	const ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_addr_ent;
224 	uint64_t *addr64 = xarg;
225 
226 	if (ent->Type != ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE)
227 		return 0;
228 	if (ent->Length < sizeof(*lapic_addr_ent)) {
229 		kprintf("madt_lapic_pass1: "
230 			"invalid LAPIC address override length\n");
231 		return 0;
232 	}
233 	lapic_addr_ent = (const ACPI_MADT_LOCAL_APIC_OVERRIDE *)ent;
234 
235 	*addr64 = lapic_addr_ent->Address;
236 	return 0;
237 }
238 
239 static vm_paddr_t
240 madt_lapic_pass1(void)
241 {
242 	ACPI_TABLE_MADT *madt;
243 	vm_paddr_t lapic_addr;
244 	uint64_t lapic_addr64;
245 	int error;
246 
247 	KKASSERT(madt_phyaddr != 0);
248 
249 	madt = sdt_sdth_map(madt_phyaddr);
250 	KKASSERT(madt != NULL);
251 
252 	MADT_VPRINTF("LAPIC address 0x%x, flags %#x\n",
253 		     madt->Address, madt->Flags);
254 	lapic_addr = madt->Address;
255 
256 	lapic_addr64 = 0;
257 	error = madt_iterate_entries(madt, madt_lapic_pass1_callback,
258 				     &lapic_addr64);
259 	if (error)
260 		panic("madt_iterate_entries(pass1) failed");
261 
262 	if (lapic_addr64 != 0) {
263 		kprintf("ACPI MADT: 64bits lapic address 0x%lx\n",
264 			lapic_addr64);
265 		lapic_addr = lapic_addr64;
266 	}
267 
268 	sdt_sdth_unmap(&madt->Header);
269 
270 	return lapic_addr;
271 }
272 
273 struct madt_lapic_pass2_cbarg {
274 	int	cpu;
275 	int	bsp_found;
276 	int	bsp_apic_id;
277 };
278 
279 static int
280 madt_lapic_pass2_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent)
281 {
282 	const ACPI_MADT_LOCAL_APIC *lapic_ent;
283 	struct madt_lapic_pass2_cbarg *arg = xarg;
284 
285 	if (ent->Type != ACPI_MADT_TYPE_LOCAL_APIC)
286 		return 0;
287 
288 	lapic_ent = (const ACPI_MADT_LOCAL_APIC *)ent;
289 	if (lapic_ent->LapicFlags & ACPI_MADT_ENABLED) {
290 		int cpu;
291 
292 		if (lapic_ent->Id == arg->bsp_apic_id) {
293 			cpu = 0;
294 			arg->bsp_found = 1;
295 		} else {
296 			cpu = arg->cpu;
297 			arg->cpu++;
298 		}
299 		MADT_VPRINTF("cpu id %d, acpi id %d, apic id %d\n",
300 		    cpu, lapic_ent->ProcessorId, lapic_ent->Id);
301 		lapic_set_cpuid(cpu, lapic_ent->Id);
302 		CPUID_TO_ACPIID(cpu) = lapic_ent->ProcessorId;
303 	}
304 	return 0;
305 }
306 
307 static int
308 madt_x2apic_pass2_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent)
309 {
310 	const ACPI_MADT_LOCAL_X2APIC *x2apic_ent;
311 	struct madt_lapic_pass2_cbarg *arg = xarg;
312 
313 	if (ent->Type != ACPI_MADT_TYPE_LOCAL_X2APIC)
314 		return 0;
315 
316 	x2apic_ent = (const ACPI_MADT_LOCAL_X2APIC *)ent;
317 	if (x2apic_ent->LapicFlags & ACPI_MADT_ENABLED) {
318 		int cpu;
319 
320 		if (x2apic_ent->LocalApicId == arg->bsp_apic_id) {
321 			cpu = 0;
322 			arg->bsp_found = 1;
323 		} else {
324 			cpu = arg->cpu;
325 			arg->cpu++;
326 		}
327 		MADT_VPRINTF("cpu id %d, acpi uid %u, apic id %d\n",
328 		    cpu, x2apic_ent->Uid, x2apic_ent->LocalApicId);
329 		lapic_set_cpuid(cpu, x2apic_ent->LocalApicId);
330 		CPUID_TO_ACPIID(cpu) = x2apic_ent->Uid;
331 	}
332 	return 0;
333 }
334 
335 static int
336 madt_lapic_pass2(int bsp_apic_id)
337 {
338 	ACPI_TABLE_MADT *madt;
339 	struct madt_lapic_pass2_cbarg arg;
340 	madt_iter_t func;
341 	int error;
342 
343 	MADT_VPRINTF("BSP apic id %d\n", bsp_apic_id);
344 
345 	KKASSERT(madt_phyaddr != 0);
346 
347 	madt = sdt_sdth_map(madt_phyaddr);
348 	KKASSERT(madt != NULL);
349 
350 	bzero(&arg, sizeof(arg));
351 	arg.cpu = 1;
352 	arg.bsp_apic_id = bsp_apic_id;
353 
354 	if (madt_use_x2apic)
355 		func = madt_x2apic_pass2_callback;
356 	else
357 		func = madt_lapic_pass2_callback;
358 	error = madt_iterate_entries(madt, func, &arg);
359 	if (error)
360 		panic("madt_iterate_entries(pass2) failed");
361 
362 	KKASSERT(arg.bsp_found);
363 	naps = arg.cpu - 1; /* exclude BSP */
364 
365 	sdt_sdth_unmap(&madt->Header);
366 
367 	return 0;
368 }
369 
370 struct madt_lapic_probe_cbarg {
371 	int		x2apic_count;
372 	int		lapic_count;
373 	vm_paddr_t	lapic_addr;
374 };
375 
376 static int
377 madt_lapic_probe_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent)
378 {
379 	struct madt_lapic_probe_cbarg *arg = xarg;
380 
381 	if (ent->Type == ACPI_MADT_TYPE_LOCAL_APIC) {
382 		const ACPI_MADT_LOCAL_APIC *lapic_ent;
383 
384 		lapic_ent = (const ACPI_MADT_LOCAL_APIC *)ent;
385 		if (lapic_ent->LapicFlags & ACPI_MADT_ENABLED) {
386 			arg->lapic_count++;
387 			if (lapic_ent->Id == APICID_MAX) {
388 				kprintf("madt_lapic_probe: "
389 				    "invalid LAPIC apic id %d\n",
390 				    lapic_ent->Id);
391 				return EINVAL;
392 			}
393 		}
394 	} else if (ent->Type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
395 		const ACPI_MADT_LOCAL_X2APIC *x2apic_ent;
396 
397 		x2apic_ent = (const ACPI_MADT_LOCAL_X2APIC *)ent;
398 		if (x2apic_ent->LapicFlags & ACPI_MADT_ENABLED) {
399 			if (x2apic_ent->LocalApicId < APICID_MAX) {
400 				/*
401 				 * XXX we only support APIC ID 0~254 at
402 				 * the moment.
403 				 */
404 				arg->x2apic_count++;
405 			}
406 		}
407 	} else if (ent->Type == ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE) {
408 		const ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_addr_ent;
409 
410 		if (ent->Length < sizeof(*lapic_addr_ent)) {
411 			kprintf("madt_lapic_probe: "
412 				"invalid LAPIC address override length\n");
413 			return 0;
414 		}
415 		lapic_addr_ent = (const ACPI_MADT_LOCAL_APIC_OVERRIDE *)ent;
416 
417 		if (lapic_addr_ent->Address != 0)
418 			arg->lapic_addr = lapic_addr_ent->Address;
419 	}
420 	return 0;
421 }
422 
423 static int
424 madt_lapic_probe(struct lapic_enumerator *e)
425 {
426 	struct madt_lapic_probe_cbarg arg;
427 	ACPI_TABLE_MADT *madt;
428 	int error;
429 
430 	if (madt_phyaddr == 0)
431 		return ENXIO;
432 
433 	madt = sdt_sdth_map(madt_phyaddr);
434 	KKASSERT(madt != NULL);
435 
436 	bzero(&arg, sizeof(arg));
437 	arg.lapic_addr = madt->Address;
438 
439 	error = madt_iterate_entries(madt, madt_lapic_probe_callback, &arg);
440 	if (!error) {
441 		if (arg.lapic_count == 0 && arg.x2apic_count == 0) {
442 			kprintf("madt_lapic_probe: no CPU is found\n");
443 			error = EOPNOTSUPP;
444 		} else if (arg.lapic_count == 0) {
445 			/*
446 			 * ACPI 5.1 says that LOCAL_X2APIC entry should
447 			 * be used only if APIC ID > 255.  While ACPI 6.2
448 			 * removes that constraint, which means that
449 			 * LOCAL_X2APIC entry could be used for any APIC
450 			 * ID.
451 			 *
452 			 * XXX
453 			 * In DragonFlyBSD, we don't support APIC ID >=
454 			 * 255, so LOCAL_X2APIC entries should be ignored,
455 			 * if LOCAL_X2APIC entries are mixed with
456 			 * LOCAL_APIC entries.  LOCAL_X2APIC entries are
457 			 * used, iff only LOCAL_X2APIC entries exist.
458 			 */
459 			madt_use_x2apic = TRUE;
460 			kprintf("MADT: use X2APIC entries\n");
461 		}
462 
463 		if (arg.lapic_addr == 0) {
464 			/*
465 			 * XXX x2apic mode.
466 			 */
467 			kprintf("madt_lapic_probe: zero LAPIC address\n");
468 			error = EOPNOTSUPP;
469 		}
470 	}
471 
472 	sdt_sdth_unmap(&madt->Header);
473 	return error;
474 }
475 
476 static int
477 madt_lapic_enumerate(struct lapic_enumerator *e)
478 {
479 	vm_paddr_t lapic_addr;
480 	int bsp_apic_id;
481 
482 	KKASSERT(madt_phyaddr != 0);
483 
484 	lapic_addr = madt_lapic_pass1();
485 	if (lapic_addr == 0)
486 		panic("madt_lapic_enumerate: no local apic");
487 
488 	lapic_map(lapic_addr);
489 
490 	bsp_apic_id = APIC_ID(lapic->id);
491 	if (bsp_apic_id == APICID_MAX) {
492 		/*
493 		 * XXX
494 		 * Some old brain dead BIOS will set BSP's LAPIC apic id
495 		 * to 255, though all LAPIC entries in MADT are valid.
496 		 */
497 		kprintf("%s invalid BSP LAPIC apic id %d\n", __func__,
498 		    bsp_apic_id);
499 		return EINVAL;
500 	}
501 
502 	if (madt_lapic_pass2(bsp_apic_id))
503 		panic("madt_lapic_enumerate: madt_lapic_pass2 failed");
504 
505 	return 0;
506 }
507 
508 static struct lapic_enumerator	madt_lapic_enumerator = {
509 	.lapic_prio = LAPIC_ENUM_PRIO_MADT,
510 	.lapic_probe = madt_lapic_probe,
511 	.lapic_enumerate = madt_lapic_enumerate
512 };
513 
514 static void
515 madt_lapic_enum_register(void)
516 {
517 	int prio;
518 
519 	prio = LAPIC_ENUM_PRIO_MADT;
520 	kgetenv_int("hw.madt_lapic_prio", &prio);
521 	madt_lapic_enumerator.lapic_prio = prio;
522 
523 	lapic_enumerator_register(&madt_lapic_enumerator);
524 }
525 SYSINIT(madt_lapic, SI_BOOT2_PRESMP, SI_ORDER_ANY, madt_lapic_enum_register, 0);
526 
527 struct madt_ioapic_probe_cbarg {
528 	int	ioapic_cnt;
529 	int	gsi_base0;
530 };
531 
532 static int
533 madt_ioapic_probe_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent)
534 {
535 	struct madt_ioapic_probe_cbarg *arg = xarg;
536 
537 	if (ent->Type == ACPI_MADT_TYPE_INTERRUPT_OVERRIDE) {
538 		const ACPI_MADT_INTERRUPT_OVERRIDE *intsrc_ent;
539 		int trig, pola;
540 
541 		intsrc_ent = (const ACPI_MADT_INTERRUPT_OVERRIDE *)ent;
542 
543 		if (intsrc_ent->SourceIrq >= ISA_IRQ_CNT) {
544 			kprintf("madt_ioapic_probe: invalid intsrc irq (%d)\n",
545 				intsrc_ent->SourceIrq);
546 			return EINVAL;
547 		}
548 
549 		if (intsrc_ent->Bus != MADT_INT_BUS_ISA) {
550 			kprintf("ACPI MADT: warning intsrc irq %d "
551 				"bus is not ISA (%d)\n",
552 				intsrc_ent->SourceIrq, intsrc_ent->Bus);
553 		}
554 
555 		trig = intsrc_ent->IntiFlags & ACPI_MADT_TRIGGER_MASK;
556 		if (trig == ACPI_MADT_TRIGGER_RESERVED) {
557 			kprintf("ACPI MADT: warning invalid intsrc irq %d "
558 				"trig, reserved\n", intsrc_ent->SourceIrq);
559 		} else if (trig == ACPI_MADT_TRIGGER_LEVEL) {
560 			MADT_VPRINTF("warning invalid intsrc irq %d "
561 			    "trig, level\n", intsrc_ent->SourceIrq);
562 		}
563 
564 		pola = intsrc_ent->IntiFlags & ACPI_MADT_POLARITY_MASK;
565 		if (pola == ACPI_MADT_POLARITY_RESERVED) {
566 			kprintf("ACPI MADT: warning invalid intsrc irq %d "
567 				"pola, reserved\n", intsrc_ent->SourceIrq);
568 		} else if (pola == ACPI_MADT_POLARITY_ACTIVE_LOW) {
569 			MADT_VPRINTF("warning invalid intsrc irq %d "
570 			    "pola, low\n", intsrc_ent->SourceIrq);
571 		}
572 	} else if (ent->Type == ACPI_MADT_TYPE_IO_APIC) {
573 		const ACPI_MADT_IO_APIC *ioapic_ent;
574 
575 		ioapic_ent = (const ACPI_MADT_IO_APIC *)ent;
576 		if (ioapic_ent->Address == 0) {
577 			kprintf("madt_ioapic_probe: zero IOAPIC address\n");
578 			return EINVAL;
579 		}
580 		if (ioapic_ent->Id == APICID_MAX) {
581 			kprintf("madt_ioapic_probe: "
582 			    "invalid IOAPIC apic id %d\n",
583 			    ioapic_ent->Id);
584 			return EINVAL;
585 		}
586 
587 		arg->ioapic_cnt++;
588 		if (ioapic_ent->GlobalIrqBase == 0)
589 			arg->gsi_base0 = 1;
590 	}
591 	return 0;
592 }
593 
594 static int
595 madt_ioapic_probe(struct ioapic_enumerator *e)
596 {
597 	struct madt_ioapic_probe_cbarg arg;
598 	ACPI_TABLE_MADT *madt;
599 	int error;
600 
601 	if (madt_phyaddr == 0)
602 		return ENXIO;
603 
604 	madt = sdt_sdth_map(madt_phyaddr);
605 	KKASSERT(madt != NULL);
606 
607 	bzero(&arg, sizeof(arg));
608 
609 	error = madt_iterate_entries(madt, madt_ioapic_probe_callback, &arg);
610 	if (!error) {
611 		if (arg.ioapic_cnt == 0) {
612 			kprintf("madt_ioapic_probe: no IOAPIC\n");
613 			error = ENXIO;
614 		}
615 		if (!arg.gsi_base0) {
616 			kprintf("madt_ioapic_probe: no GSI base 0\n");
617 			error = EINVAL;
618 		}
619 	}
620 
621 	sdt_sdth_unmap(&madt->Header);
622 	return error;
623 }
624 
625 static int
626 madt_ioapic_enum_callback(void *xarg, const ACPI_SUBTABLE_HEADER *ent)
627 {
628 	if (ent->Type == ACPI_MADT_TYPE_INTERRUPT_OVERRIDE) {
629 		const ACPI_MADT_INTERRUPT_OVERRIDE *intsrc_ent;
630 		enum intr_trigger trig;
631 		enum intr_polarity pola;
632 		int ent_trig, ent_pola;
633 
634 		intsrc_ent = (const ACPI_MADT_INTERRUPT_OVERRIDE *)ent;
635 
636 		KKASSERT(intsrc_ent->SourceIrq < ISA_IRQ_CNT);
637 		if (intsrc_ent->Bus != MADT_INT_BUS_ISA)
638 			return 0;
639 
640 		ent_trig = intsrc_ent->IntiFlags & ACPI_MADT_TRIGGER_MASK;
641 		if (ent_trig == ACPI_MADT_TRIGGER_RESERVED)
642 			return 0;
643 		else if (ent_trig == ACPI_MADT_TRIGGER_LEVEL)
644 			trig = INTR_TRIGGER_LEVEL;
645 		else
646 			trig = INTR_TRIGGER_EDGE;
647 
648 		ent_pola = intsrc_ent->IntiFlags & ACPI_MADT_POLARITY_MASK;
649 		if (ent_pola == ACPI_MADT_POLARITY_RESERVED)
650 			return 0;
651 		else if (ent_pola == ACPI_MADT_POLARITY_ACTIVE_LOW)
652 			pola = INTR_POLARITY_LOW;
653 		else
654 			pola = INTR_POLARITY_HIGH;
655 
656 		if (intsrc_ent->SourceIrq == acpi_sci_irqno()) {
657 			acpi_sci_setmode1(trig, pola);
658 			MADT_VPRINTF("SCI irq %d, first test %s/%s\n",
659 			    intsrc_ent->SourceIrq,
660 			    intr_str_trigger(trig), intr_str_polarity(pola));
661 		}
662 
663 		/*
664 		 * We ignore the polarity and trigger changes, since
665 		 * most of them are wrong or useless at best.
666 		 */
667 		if (intsrc_ent->SourceIrq == intsrc_ent->GlobalIrq) {
668 			/* Nothing changed */
669 			return 0;
670 		}
671 		trig = INTR_TRIGGER_EDGE;
672 		pola = INTR_POLARITY_HIGH;
673 
674 		MADT_VPRINTF("INTSRC irq %d -> gsi %u %s/%s\n",
675 			     intsrc_ent->SourceIrq, intsrc_ent->GlobalIrq,
676 			     intr_str_trigger(trig), intr_str_polarity(pola));
677 		ioapic_intsrc(intsrc_ent->SourceIrq, intsrc_ent->GlobalIrq,
678 			      trig, pola);
679 	} else if (ent->Type == ACPI_MADT_TYPE_IO_APIC) {
680 		const ACPI_MADT_IO_APIC *ioapic_ent;
681 		uint32_t ver;
682 		void *addr;
683 		int npin;
684 
685 		ioapic_ent = (const ACPI_MADT_IO_APIC *)ent;
686 		MADT_VPRINTF("IOAPIC addr 0x%08x, apic id %d, gsi base %u\n",
687 			     ioapic_ent->Address, ioapic_ent->Id,
688 			     ioapic_ent->GlobalIrqBase);
689 
690 		addr = ioapic_map(ioapic_ent->Address);
691 
692 		ver = ioapic_read(addr, IOAPIC_VER);
693 		npin = ((ver & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1;
694 
695 		ioapic_add(addr, ioapic_ent->GlobalIrqBase, npin);
696 	}
697 	return 0;
698 }
699 
700 static void
701 madt_ioapic_enumerate(struct ioapic_enumerator *e)
702 {
703 	ACPI_TABLE_MADT *madt;
704 	int error;
705 
706 	KKASSERT(madt_phyaddr != 0);
707 
708 	madt = sdt_sdth_map(madt_phyaddr);
709 	KKASSERT(madt != NULL);
710 
711 	error = madt_iterate_entries(madt, madt_ioapic_enum_callback, NULL);
712 	if (error)
713 		panic("madt_ioapic_enumerate failed");
714 
715 	sdt_sdth_unmap(&madt->Header);
716 }
717 
718 static struct ioapic_enumerator	madt_ioapic_enumerator = {
719 	.ioapic_prio = IOAPIC_ENUM_PRIO_MADT,
720 	.ioapic_probe = madt_ioapic_probe,
721 	.ioapic_enumerate = madt_ioapic_enumerate
722 };
723 
724 static void
725 madt_ioapic_enum_register(void)
726 {
727 	int prio;
728 
729 	prio = IOAPIC_ENUM_PRIO_MADT;
730 	kgetenv_int("hw.madt_ioapic_prio", &prio);
731 	madt_ioapic_enumerator.ioapic_prio = prio;
732 
733 	ioapic_enumerator_register(&madt_ioapic_enumerator);
734 }
735 SYSINIT(madt_ioapic, SI_BOOT2_PRESMP, SI_ORDER_ANY,
736 	madt_ioapic_enum_register, 0);
737