acpi: Use X2APIC entries, if there are only X2APIC entries in MADT.
[dragonfly.git] / sys / platform / pc64 / acpica / acpi_madt.c
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);