Merge branch 'vendor/AWK'
[dragonfly.git] / sys / platform / pc64 / acpica5 / 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/apic/lapic.h>
41 #include <machine_base/apic/ioapic.h>
42
43 #include "acpi_sdt.h"
44 #include "acpi_sdt_var.h"
45
46 extern int naps;
47
48 #define MADT_VPRINTF(fmt, arg...) \
49 do { \
50         if (bootverbose) \
51                 kprintf("ACPI MADT: " fmt , ##arg); \
52 } while (0)
53
54 /* Multiple APIC Description Table */
55 struct acpi_madt {
56         struct acpi_sdth        madt_hdr;
57         uint32_t                madt_lapic_addr;
58         uint32_t                madt_flags;
59         uint8_t                 madt_ents[1];
60 } __packed;
61
62 /* Common parts of MADT APIC structure */
63 struct acpi_madt_ent {
64         uint8_t                 me_type;        /* MADT_ENT_ */
65         uint8_t                 me_len;
66 } __packed;
67
68 #define MADT_ENT_LAPIC          0
69 #define MADT_ENT_IOAPIC         1
70 #define MADT_ENT_INTSRC         2
71 #define MADT_ENT_LAPIC_ADDR     5
72
73 /* MADT Processor Local APIC */
74 struct acpi_madt_lapic {
75         struct acpi_madt_ent    ml_hdr;
76         uint8_t                 ml_cpu_id;
77         uint8_t                 ml_apic_id;
78         uint32_t                ml_flags;       /* MADT_LAPIC_ */
79 } __packed;
80
81 #define MADT_LAPIC_ENABLED      0x1
82
83 /* MADT I/O APIC */
84 struct acpi_madt_ioapic {
85         struct acpi_madt_ent    mio_hdr;
86         uint8_t                 mio_apic_id;
87         uint8_t                 mio_reserved;
88         uint32_t                mio_addr;
89         uint32_t                mio_gsi_base;
90 } __packed;
91
92 /* MADT Interrupt Source Override */
93 struct acpi_madt_intsrc {
94         struct acpi_madt_ent    mint_hdr;
95         uint8_t                 mint_bus;       /* MADT_INT_BUS_ */
96         uint8_t                 mint_src;
97         uint32_t                mint_gsi;
98         uint16_t                mint_flags;     /* MADT_INT_ */
99 } __packed;
100
101 #define MADT_INT_BUS_ISA        0
102
103 #define MADT_INT_POLA_MASK      0x3
104 #define MADT_INT_POLA_SHIFT     0
105 #define MADT_INT_POLA_CONFORM   0
106 #define MADT_INT_POLA_HIGH      1
107 #define MADT_INT_POLA_RSVD      2
108 #define MADT_INT_POLA_LOW       3
109 #define MADT_INT_TRIG_MASK      0xc
110 #define MADT_INT_TRIG_SHIFT     2
111 #define MADT_INT_TRIG_CONFORM   0
112 #define MADT_INT_TRIG_EDGE      1
113 #define MADT_INT_TRIG_RSVD      2
114 #define MADT_INT_TRIG_LEVEL     3
115
116 /* MADT Local APIC Address Override */
117 struct acpi_madt_lapic_addr {
118         struct acpi_madt_ent    mla_hdr;
119         uint16_t                mla_reserved;
120         uint64_t                mla_lapic_addr;
121 } __packed;
122
123 typedef int                     (*madt_iter_t)(void *,
124                                     const struct acpi_madt_ent *);
125
126 static int                      madt_check(vm_paddr_t);
127 static int                      madt_iterate_entries(struct acpi_madt *,
128                                     madt_iter_t, void *);
129
130 static vm_paddr_t               madt_lapic_pass1(void);
131 static int                      madt_lapic_pass2(int);
132
133 static void                     madt_lapic_enumerate(struct lapic_enumerator *);
134 static int                      madt_lapic_probe(struct lapic_enumerator *);
135
136 static void                     madt_ioapic_enumerate(
137                                     struct ioapic_enumerator *);
138 static int                      madt_ioapic_probe(struct ioapic_enumerator *);
139
140 static vm_paddr_t               madt_phyaddr;
141
142 static void
143 madt_probe(void)
144 {
145         vm_paddr_t madt_paddr;
146
147         KKASSERT(madt_phyaddr == 0);
148
149         madt_paddr = sdt_search(ACPI_MADT_SIG);
150         if (madt_paddr == 0) {
151                 kprintf("madt_probe: can't locate MADT\n");
152                 return;
153         }
154
155         /* Preliminary checks */
156         if (madt_check(madt_paddr)) {
157                 kprintf("madt_probe: madt_check failed\n");
158                 return;
159         }
160
161         madt_phyaddr = madt_paddr;
162 }
163 SYSINIT(madt_probe, SI_BOOT2_PRESMP, SI_ORDER_SECOND, madt_probe, 0);
164
165 static int
166 madt_check(vm_paddr_t madt_paddr)
167 {
168         struct acpi_madt *madt;
169         int error = 0;
170
171         KKASSERT(madt_paddr != 0);
172
173         madt = sdt_sdth_map(madt_paddr);
174         KKASSERT(madt != NULL);
175
176         /*
177          * MADT in ACPI specification 1.0 - 4.0
178          */
179         if (madt->madt_hdr.sdth_rev < 1 || madt->madt_hdr.sdth_rev > 3) {
180                 kprintf("madt_check: unsupported MADT revision %d\n",
181                         madt->madt_hdr.sdth_rev);
182                 error = EOPNOTSUPP;
183                 goto back;
184         }
185
186         if (madt->madt_hdr.sdth_len <
187             sizeof(*madt) - sizeof(madt->madt_ents)) {
188                 kprintf("madt_check: invalid MADT length %u\n",
189                         madt->madt_hdr.sdth_len);
190                 error = EINVAL;
191                 goto back;
192         }
193 back:
194         sdt_sdth_unmap(&madt->madt_hdr);
195         return error;
196 }
197
198 static int
199 madt_iterate_entries(struct acpi_madt *madt, madt_iter_t func, void *arg)
200 {
201         int size, cur, error;
202
203         size = madt->madt_hdr.sdth_len -
204                (sizeof(*madt) - sizeof(madt->madt_ents));
205         cur = 0;
206         error = 0;
207
208         while (size - cur > sizeof(struct acpi_madt_ent)) {
209                 const struct acpi_madt_ent *ent;
210
211                 ent = (const struct acpi_madt_ent *)&madt->madt_ents[cur];
212                 if (ent->me_len < sizeof(*ent)) {
213                         kprintf("madt_iterate_entries: invalid MADT "
214                                 "entry len %d\n", ent->me_len);
215                         error = EINVAL;
216                         break;
217                 }
218                 if (ent->me_len > (size - cur)) {
219                         kprintf("madt_iterate_entries: invalid MADT "
220                                 "entry len %d, > table length\n", ent->me_len);
221                         error = EINVAL;
222                         break;
223                 }
224
225                 cur += ent->me_len;
226
227                 /*
228                  * Only Local APIC, I/O APIC and Interrupt Source Override
229                  * are defined in ACPI specification 1.0 - 4.0
230                  */
231                 switch (ent->me_type) {
232                 case MADT_ENT_LAPIC:
233                         if (ent->me_len < sizeof(struct acpi_madt_lapic)) {
234                                 kprintf("madt_iterate_entries: invalid MADT "
235                                         "lapic entry len %d\n", ent->me_len);
236                                 error = EINVAL;
237                         }
238                         break;
239
240                 case MADT_ENT_IOAPIC:
241                         if (ent->me_len < sizeof(struct acpi_madt_ioapic)) {
242                                 kprintf("madt_iterate_entries: invalid MADT "
243                                         "ioapic entry len %d\n", ent->me_len);
244                                 error = EINVAL;
245                         }
246                         break;
247
248                 case MADT_ENT_INTSRC:
249                         if (ent->me_len < sizeof(struct acpi_madt_intsrc)) {
250                                 kprintf("madt_iterate_entries: invalid MADT "
251                                         "intsrc entry len %d\n",
252                                         ent->me_len);
253                                 error = EINVAL;
254                         }
255                         break;
256                 }
257                 if (error)
258                         break;
259
260                 error = func(arg, ent);
261                 if (error)
262                         break;
263         }
264         return error;
265 }
266
267 static int
268 madt_lapic_pass1_callback(void *xarg, const struct acpi_madt_ent *ent)
269 {
270         const struct acpi_madt_lapic_addr *lapic_addr_ent;
271         uint64_t *addr64 = xarg;
272
273         if (ent->me_type != MADT_ENT_LAPIC_ADDR)
274                 return 0;
275         if (ent->me_len < sizeof(*lapic_addr_ent)) {
276                 kprintf("madt_lapic_pass1: "
277                         "invalid LAPIC address override length\n");
278                 return 0;
279         }
280         lapic_addr_ent = (const struct acpi_madt_lapic_addr *)ent;
281
282         *addr64 = lapic_addr_ent->mla_lapic_addr;
283         return 0;
284 }
285
286 static vm_paddr_t
287 madt_lapic_pass1(void)
288 {
289         struct acpi_madt *madt;
290         vm_paddr_t lapic_addr;
291         uint64_t lapic_addr64;
292         int error;
293
294         KKASSERT(madt_phyaddr != 0);
295
296         madt = sdt_sdth_map(madt_phyaddr);
297         KKASSERT(madt != NULL);
298
299         MADT_VPRINTF("LAPIC address 0x%x, flags %#x\n",
300                      madt->madt_lapic_addr, madt->madt_flags);
301         lapic_addr = madt->madt_lapic_addr;
302
303         lapic_addr64 = 0;
304         error = madt_iterate_entries(madt, madt_lapic_pass1_callback,
305                                      &lapic_addr64);
306         if (error)
307                 panic("madt_iterate_entries(pass1) failed\n");
308
309         if (lapic_addr64 != 0) {
310                 kprintf("ACPI MADT: 64bits lapic address 0x%lx\n",
311                         lapic_addr64);
312                 lapic_addr = lapic_addr64;
313         }
314
315         sdt_sdth_unmap(&madt->madt_hdr);
316
317         return lapic_addr;
318 }
319
320 struct madt_lapic_pass2_cbarg {
321         int     cpu;
322         int     bsp_found;
323         int     bsp_apic_id;
324 };
325
326 static int
327 madt_lapic_pass2_callback(void *xarg, const struct acpi_madt_ent *ent)
328 {
329         const struct acpi_madt_lapic *lapic_ent;
330         struct madt_lapic_pass2_cbarg *arg = xarg;
331
332         if (ent->me_type != MADT_ENT_LAPIC)
333                 return 0;
334
335         lapic_ent = (const struct acpi_madt_lapic *)ent;
336         if (lapic_ent->ml_flags & MADT_LAPIC_ENABLED) {
337                 MADT_VPRINTF("cpu id %d, apic id %d\n",
338                              lapic_ent->ml_cpu_id, lapic_ent->ml_apic_id);
339                 if (lapic_ent->ml_apic_id == arg->bsp_apic_id) {
340                         lapic_set_cpuid(0, lapic_ent->ml_apic_id);
341                         arg->bsp_found = 1;
342                 } else {
343                         lapic_set_cpuid(arg->cpu, lapic_ent->ml_apic_id);
344                         arg->cpu++;
345                 }
346         }
347         return 0;
348 }
349
350 static int
351 madt_lapic_pass2(int bsp_apic_id)
352 {
353         struct acpi_madt *madt;
354         struct madt_lapic_pass2_cbarg arg;
355         int error;
356
357         MADT_VPRINTF("BSP apic id %d\n", bsp_apic_id);
358
359         KKASSERT(madt_phyaddr != 0);
360
361         madt = sdt_sdth_map(madt_phyaddr);
362         KKASSERT(madt != NULL);
363
364         bzero(&arg, sizeof(arg));
365         arg.cpu = 1;
366         arg.bsp_apic_id = bsp_apic_id;
367
368         error = madt_iterate_entries(madt, madt_lapic_pass2_callback, &arg);
369         if (error)
370                 panic("madt_iterate_entries(pass2) failed\n");
371
372         KKASSERT(arg.bsp_found);
373         naps = arg.cpu - 1; /* exclude BSP */
374
375         sdt_sdth_unmap(&madt->madt_hdr);
376
377         return 0;
378 }
379
380 struct madt_lapic_probe_cbarg {
381         int             cpu_count;
382         vm_paddr_t      lapic_addr;
383 };
384
385 static int
386 madt_lapic_probe_callback(void *xarg, const struct acpi_madt_ent *ent)
387 {
388         struct madt_lapic_probe_cbarg *arg = xarg;
389
390         if (ent->me_type == MADT_ENT_LAPIC) {
391                 const struct acpi_madt_lapic *lapic_ent;
392
393                 lapic_ent = (const struct acpi_madt_lapic *)ent;
394                 if (lapic_ent->ml_flags & MADT_LAPIC_ENABLED)
395                         arg->cpu_count++;
396         } else if (ent->me_type == MADT_ENT_LAPIC_ADDR) {
397                 const struct acpi_madt_lapic_addr *lapic_addr_ent;
398
399                 if (ent->me_len < sizeof(*lapic_addr_ent)) {
400                         kprintf("madt_lapic_probe: "
401                                 "invalid LAPIC address override length\n");
402                         return 0;
403                 }
404                 lapic_addr_ent = (const struct acpi_madt_lapic_addr *)ent;
405
406                 if (lapic_addr_ent->mla_lapic_addr != 0)
407                         arg->lapic_addr = lapic_addr_ent->mla_lapic_addr;
408         }
409         return 0;
410 }
411
412 static int
413 madt_lapic_probe(struct lapic_enumerator *e)
414 {
415         struct madt_lapic_probe_cbarg arg;
416         struct acpi_madt *madt;
417         int error;
418
419         if (madt_phyaddr == 0)
420                 return ENXIO;
421
422         madt = sdt_sdth_map(madt_phyaddr);
423         KKASSERT(madt != NULL);
424
425         bzero(&arg, sizeof(arg));
426         arg.lapic_addr = madt->madt_lapic_addr;
427
428         error = madt_iterate_entries(madt, madt_lapic_probe_callback, &arg);
429         if (!error) {
430                 if (arg.cpu_count == 0) {
431                         kprintf("madt_lapic_probe: no CPU is found\n");
432                         error = EOPNOTSUPP;
433                 }
434                 if (arg.lapic_addr == 0) {
435                         kprintf("madt_lapic_probe: zero LAPIC address\n");
436                         error = EOPNOTSUPP;
437                 }
438         }
439
440         sdt_sdth_unmap(&madt->madt_hdr);
441         return error;
442 }
443
444 static void
445 madt_lapic_enumerate(struct lapic_enumerator *e)
446 {
447         vm_paddr_t lapic_addr;
448         int bsp_apic_id;
449
450         KKASSERT(madt_phyaddr != 0);
451
452         lapic_addr = madt_lapic_pass1();
453         if (lapic_addr == 0)
454                 panic("madt_lapic_enumerate: no local apic\n");
455
456         lapic_map(lapic_addr);
457
458         bsp_apic_id = APIC_ID(lapic->id);
459         if (madt_lapic_pass2(bsp_apic_id))
460                 panic("madt_lapic_enumerate: madt_lapic_pass2 failed\n");
461 }
462
463 static struct lapic_enumerator  madt_lapic_enumerator = {
464         .lapic_prio = LAPIC_ENUM_PRIO_MADT,
465         .lapic_probe = madt_lapic_probe,
466         .lapic_enumerate = madt_lapic_enumerate
467 };
468
469 static void
470 madt_lapic_enum_register(void)
471 {
472         int prio;
473
474         prio = LAPIC_ENUM_PRIO_MADT;
475         kgetenv_int("hw.madt_lapic_prio", &prio);
476         madt_lapic_enumerator.lapic_prio = prio;
477
478         lapic_enumerator_register(&madt_lapic_enumerator);
479 }
480 SYSINIT(madt_lapic, SI_BOOT2_PRESMP, SI_ORDER_ANY, madt_lapic_enum_register, 0);
481
482 struct madt_ioapic_probe_cbarg {
483         int     ioapic_cnt;
484         int     gsi_base0;
485 };
486
487 static int
488 madt_ioapic_probe_callback(void *xarg, const struct acpi_madt_ent *ent)
489 {
490         struct madt_ioapic_probe_cbarg *arg = xarg;
491
492         if (ent->me_type == MADT_ENT_INTSRC) {
493                 const struct acpi_madt_intsrc *intsrc_ent;
494                 int trig, pola;
495
496                 intsrc_ent = (const struct acpi_madt_intsrc *)ent;
497
498                 /* XXX magic number */
499                 if (intsrc_ent->mint_src >= 16) {
500                         kprintf("madt_ioapic_probe: invalid intsrc irq (%d)\n",
501                                 intsrc_ent->mint_src);
502                         return EINVAL;
503                 }
504
505                 if (intsrc_ent->mint_bus != MADT_INT_BUS_ISA) {
506                         kprintf("ACPI MADT: warning intsrc irq %d "
507                                 "bus is not ISA (%d)\n",
508                                 intsrc_ent->mint_src, intsrc_ent->mint_bus);
509                 }
510
511                 trig = (intsrc_ent->mint_flags & MADT_INT_TRIG_MASK) >>
512                        MADT_INT_TRIG_SHIFT;
513                 if (trig == MADT_INT_TRIG_RSVD) {
514                         kprintf("ACPI MADT: warning invalid intsrc irq %d "
515                                 "trig, reserved\n", intsrc_ent->mint_src);
516                 } else if (trig == MADT_INT_TRIG_LEVEL) {
517                         MADT_VPRINTF("warning invalid intsrc irq %d "
518                             "trig, level\n", intsrc_ent->mint_src);
519                 }
520
521                 pola = (intsrc_ent->mint_flags & MADT_INT_POLA_MASK) >>
522                        MADT_INT_POLA_SHIFT;
523                 if (pola == MADT_INT_POLA_RSVD) {
524                         kprintf("ACPI MADT: warning invalid intsrc irq %d "
525                                 "pola, reserved\n", intsrc_ent->mint_src);
526                 } else if (pola == MADT_INT_POLA_LOW) {
527                         MADT_VPRINTF("warning invalid intsrc irq %d "
528                             "pola, low\n", intsrc_ent->mint_src);
529                 }
530         } else if (ent->me_type == MADT_ENT_IOAPIC) {
531                 const struct acpi_madt_ioapic *ioapic_ent;
532
533                 ioapic_ent = (const struct acpi_madt_ioapic *)ent;
534                 if (ioapic_ent->mio_addr == 0) {
535                         kprintf("madt_ioapic_probe: zero IOAPIC address\n");
536                         return EINVAL;
537                 }
538
539                 arg->ioapic_cnt++;
540                 if (ioapic_ent->mio_gsi_base == 0)
541                         arg->gsi_base0 = 1;
542         }
543         return 0;
544 }
545
546 static int
547 madt_ioapic_probe(struct ioapic_enumerator *e)
548 {
549         struct madt_ioapic_probe_cbarg arg;
550         struct acpi_madt *madt;
551         int error;
552
553         if (madt_phyaddr == 0)
554                 return ENXIO;
555
556         madt = sdt_sdth_map(madt_phyaddr);
557         KKASSERT(madt != NULL);
558
559         bzero(&arg, sizeof(arg));
560
561         error = madt_iterate_entries(madt, madt_ioapic_probe_callback, &arg);
562         if (!error) {
563                 if (arg.ioapic_cnt == 0) {
564                         kprintf("madt_ioapic_probe: no IOAPIC\n");
565                         error = ENXIO;
566                 }
567                 if (!arg.gsi_base0) {
568                         kprintf("madt_ioapic_probe: no GSI base 0\n");
569                         error = EINVAL;
570                 }
571         }
572
573         sdt_sdth_unmap(&madt->madt_hdr);
574         return error;
575 }
576
577 static int
578 madt_ioapic_enum_callback(void *xarg, const struct acpi_madt_ent *ent)
579 {
580         if (ent->me_type == MADT_ENT_INTSRC) {
581                 const struct acpi_madt_intsrc *intsrc_ent;
582                 enum intr_trigger trig;
583                 enum intr_polarity pola;
584 #ifdef foo
585                 int ent_trig, ent_pola;
586 #endif
587
588                 intsrc_ent = (const struct acpi_madt_intsrc *)ent;
589
590                 KKASSERT(intsrc_ent->mint_src < 16);
591                 if (intsrc_ent->mint_bus != MADT_INT_BUS_ISA)
592                         return 0;
593
594 #ifdef foo
595                 ent_trig = (intsrc_ent->mint_flags & MADT_INT_TRIG_MASK) >>
596                     MADT_INT_TRIG_SHIFT;
597                 if (ent_trig == MADT_INT_TRIG_RSVD)
598                         return 0;
599                 else if (ent_trig == MADT_INT_TRIG_LEVEL)
600                         trig = INTR_TRIGGER_LEVEL;
601                 else
602                         trig = INTR_TRIGGER_EDGE;
603
604                 ent_pola = (intsrc_ent->mint_flags & MADT_INT_POLA_MASK) >>
605                     MADT_INT_POLA_SHIFT;
606                 if (ent_pola == MADT_INT_POLA_RSVD)
607                         return 0;
608                 else if (ent_pola == MADT_INT_POLA_LOW)
609                         pola = INTR_POLARITY_LOW;
610                 else
611                         pola = INTR_POLARITY_HIGH;
612 #else
613                 /*
614                  * We ignore the polarity and trigger changes, since
615                  * most of them are wrong or useless at best.
616                  */
617                 if (intsrc_ent->mint_src == intsrc_ent->mint_gsi) {
618                         /* Nothing changed */
619                         return 0;
620                 }
621                 trig = INTR_TRIGGER_EDGE;
622                 pola = INTR_POLARITY_HIGH;
623 #endif
624
625                 MADT_VPRINTF("INTSRC irq %d -> gsi %u %s/%s\n",
626                              intsrc_ent->mint_src, intsrc_ent->mint_gsi,
627                              intr_str_trigger(trig), intr_str_polarity(pola));
628                 ioapic_intsrc(intsrc_ent->mint_src, intsrc_ent->mint_gsi,
629                               trig, pola);
630         } else if (ent->me_type == MADT_ENT_IOAPIC) {
631                 const struct acpi_madt_ioapic *ioapic_ent;
632                 uint32_t ver;
633                 void *addr;
634                 int npin;
635
636                 ioapic_ent = (const struct acpi_madt_ioapic *)ent;
637                 MADT_VPRINTF("IOAPIC addr 0x%08x, apic id %d, gsi base %u\n",
638                              ioapic_ent->mio_addr, ioapic_ent->mio_apic_id,
639                              ioapic_ent->mio_gsi_base);
640
641                 addr = ioapic_map(ioapic_ent->mio_addr);
642
643                 ver = ioapic_read(addr, IOAPIC_VER);
644                 npin = ((ver & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1;
645
646                 ioapic_add(addr, ioapic_ent->mio_gsi_base, npin);
647         }
648         return 0;
649 }
650
651 static void
652 madt_ioapic_enumerate(struct ioapic_enumerator *e)
653 {
654         struct acpi_madt *madt;
655         int error;
656
657         KKASSERT(madt_phyaddr != 0);
658
659         madt = sdt_sdth_map(madt_phyaddr);
660         KKASSERT(madt != NULL);
661
662         error = madt_iterate_entries(madt, madt_ioapic_enum_callback, NULL);
663         if (error)
664                 panic("madt_ioapic_enumerate failed\n");
665
666         sdt_sdth_unmap(&madt->madt_hdr);
667 }
668
669 static struct ioapic_enumerator madt_ioapic_enumerator = {
670         .ioapic_prio = IOAPIC_ENUM_PRIO_MADT,
671         .ioapic_probe = madt_ioapic_probe,
672         .ioapic_enumerate = madt_ioapic_enumerate
673 };
674
675 static void
676 madt_ioapic_enum_register(void)
677 {
678         int prio;
679
680         prio = IOAPIC_ENUM_PRIO_MADT;
681         kgetenv_int("hw.madt_ioapic_prio", &prio);
682         madt_ioapic_enumerator.ioapic_prio = prio;
683
684         ioapic_enumerator_register(&madt_ioapic_enumerator);
685 }
686 SYSINIT(madt_ioapic, SI_BOOT2_PRESMP, SI_ORDER_ANY,
687         madt_ioapic_enum_register, 0);