nrelease - fix/improve livecd
[dragonfly.git] / sys / platform / pc64 / x86_64 / mptable.c
1 /*
2  * Copyright (c) 1996, by Steve Passe
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. The name of the developer may NOT be used to endorse or promote products
11  *    derived from this software without specific prior written permission.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  * $FreeBSD: src/sys/i386/i386/mp_machdep.c,v 1.115.2.15 2003/03/14 21:22:35 jhb Exp $
26  */
27
28 #include "opt_cpu.h"
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/sysctl.h>
34 #include <sys/malloc.h>
35 #include <sys/memrange.h>
36 #include <sys/cons.h>   /* cngetc() */
37 #include <sys/machintr.h>
38
39 #include <vm/vm.h>
40 #include <vm/vm_param.h>
41 #include <vm/pmap.h>
42 #include <vm/vm_kern.h>
43 #include <vm/vm_extern.h>
44 #include <sys/lock.h>
45 #include <vm/vm_map.h>
46
47 #include <machine/smp.h>
48 #include <machine_base/isa/isa_intr.h>
49 #include <machine_base/apic/apicreg.h>
50 #include <machine_base/apic/apicvar.h>
51 #include <machine/atomic.h>
52 #include <machine/cpufunc.h>
53 #include <machine/cputypes.h>
54 #include <machine_base/apic/lapic.h>
55 #include <machine_base/apic/ioapic.h>
56 #include <machine/psl.h>
57 #include <machine/segments.h>
58 #include <machine/tss.h>
59 #include <machine/specialreg.h>
60 #include <machine/globaldata.h>
61 #include <machine/pmap_inval.h>
62 #include <machine/mptable.h>
63
64 #include <machine/md_var.h>             /* setidt() */
65 #include <machine_base/icu/icu.h>       /* IPIs */
66 #include <machine_base/apic/ioapic_abi.h>
67 #include <machine/intr_machdep.h>       /* IPIs */
68
69 extern u_int    base_memory;            /* in kilobytes, see machdep.c */
70 extern u_long   ebda_addr;
71 extern int      imcr_present;
72 extern int      naps;
73
74 static int      force_enable = 0;
75 TUNABLE_INT("hw.lapic_force_enable", &force_enable);
76
77 #define BIOS_BASE               (0xf0000)
78 #define BIOS_BASE2              (0xe0000)
79 #define BIOS_SIZE               (0x10000)
80 #define BIOS_COUNT              (BIOS_SIZE/4)
81
82 #define PROCENTRY_FLAG_EN       0x01
83 #define PROCENTRY_FLAG_BP       0x02
84 #define IOAPICENTRY_FLAG_EN     0x01
85
86
87 /* MP Floating Pointer Structure */
88 typedef struct MPFPS {
89         char    signature[4];
90         u_int32_t pap;
91         u_char  length;
92         u_char  spec_rev;
93         u_char  checksum;
94         u_char  mpfb1;
95         u_char  mpfb2;
96         u_char  mpfb3;
97         u_char  mpfb4;
98         u_char  mpfb5;
99 }      *mpfps_t;
100
101 /* MP Configuration Table Header */
102 typedef struct MPCTH {
103         char    signature[4];
104         u_short base_table_length;
105         u_char  spec_rev;
106         u_char  checksum;
107         u_char  oem_id[8];
108         u_char  product_id[12];
109         u_int32_t oem_table_pointer;
110         u_short oem_table_size;
111         u_short entry_count;
112         u_int32_t apic_address;
113         u_short extended_table_length;
114         u_char  extended_table_checksum;
115         u_char  reserved;
116 }      *mpcth_t;
117
118
119 typedef struct PROCENTRY {
120         u_char  type;
121         u_char  apic_id;
122         u_char  apic_version;
123         u_char  cpu_flags;
124         u_int32_t cpu_signature;
125         u_int32_t feature_flags;
126         u_int32_t reserved1;
127         u_int32_t reserved2;
128 }      *proc_entry_ptr;
129
130 typedef struct BUSENTRY {
131         u_char  type;
132         u_char  bus_id;
133         char    bus_type[6];
134 }      *bus_entry_ptr;
135
136 typedef struct IOAPICENTRY {
137         u_char  type;
138         u_char  apic_id;
139         u_char  apic_version;
140         u_char  apic_flags;
141         u_int32_t apic_address;
142 }      *io_apic_entry_ptr;
143
144 typedef struct INTENTRY {
145         u_char  type;
146         u_char  int_type;
147         u_short int_flags;
148         u_char  src_bus_id;
149         u_char  src_bus_irq;
150         u_char  dst_apic_id;
151         u_char  dst_apic_int;
152 }      *int_entry_ptr;
153
154 /* descriptions of MP basetable entries */
155 typedef struct BASETABLE_ENTRY {
156         u_char  type;
157         u_char  length;
158         char    name[16];
159 }       basetable_entry;
160
161 struct mptable_pos {
162         mpfps_t         mp_fps;
163         mpcth_t         mp_cth;
164         vm_size_t       mp_cth_mapsz;   
165 };
166
167 #define MPTABLE_POS_USE_DEFAULT(mpt) \
168         ((mpt)->mp_fps->mpfb1 != 0 || (mpt)->mp_cth == NULL)
169
170 struct mptable_bus {
171         int             mb_id;
172         int             mb_type;        /* MPTABLE_BUS_ */
173         TAILQ_ENTRY(mptable_bus) mb_link;
174 };
175
176 #define MPTABLE_BUS_ISA         0
177 #define MPTABLE_BUS_PCI         1
178
179 struct mptable_bus_info {
180         TAILQ_HEAD(, mptable_bus) mbi_list;
181 };
182
183 struct mptable_pci_int {
184         int             mpci_bus;
185         int             mpci_dev;
186         int             mpci_pin;
187
188         int             mpci_ioapic_idx;
189         int             mpci_ioapic_pin;
190         TAILQ_ENTRY(mptable_pci_int) mpci_link;
191 };
192
193 struct mptable_ioapic {
194         int             mio_idx;
195         int             mio_apic_id;
196         uint32_t        mio_addr;
197         int             mio_gsi_base;
198         int             mio_npin;
199         TAILQ_ENTRY(mptable_ioapic) mio_link;
200 };
201
202 typedef int     (*mptable_iter_func)(void *, const void *, int);
203
204 static int      mptable_iterate_entries(const mpcth_t,
205                     mptable_iter_func, void *);
206 static int      mptable_search(void);
207 static long     mptable_search_sig(u_int32_t target, int count);
208 static int      mptable_hyperthread_fixup(cpumask_t, int);
209 static int      mptable_map(struct mptable_pos *);
210 static void     mptable_unmap(struct mptable_pos *);
211 static void     mptable_bus_info_alloc(const mpcth_t,
212                     struct mptable_bus_info *);
213 static void     mptable_bus_info_free(struct mptable_bus_info *);
214
215 static int      mptable_lapic_probe(struct lapic_enumerator *);
216 static int      mptable_lapic_enumerate(struct lapic_enumerator *);
217 static void     mptable_lapic_default(void);
218
219 static int      mptable_ioapic_probe(struct ioapic_enumerator *);
220 static void     mptable_ioapic_enumerate(struct ioapic_enumerator *);
221
222 static basetable_entry basetable_entry_types[] =
223 {
224         {0, 20, "Processor"},
225         {1, 8, "Bus"},
226         {2, 8, "I/O APIC"},
227         {3, 8, "I/O INT"},
228         {4, 8, "Local INT"}
229 };
230
231 static vm_paddr_t       mptable_fps_phyaddr;
232 static int              mptable_use_default;
233 static TAILQ_HEAD(mptable_pci_int_list, mptable_pci_int) mptable_pci_int_list =
234         TAILQ_HEAD_INITIALIZER(mptable_pci_int_list);
235 static TAILQ_HEAD(mptable_ioapic_list, mptable_ioapic) mptable_ioapic_list =
236         TAILQ_HEAD_INITIALIZER(mptable_ioapic_list);
237
238 static void
239 mptable_probe(void)
240 {
241         struct mptable_pos mpt;
242         int error;
243
244         KKASSERT(mptable_fps_phyaddr == 0);
245
246         mptable_fps_phyaddr = mptable_search();
247         if (mptable_fps_phyaddr == 0)
248                 return;
249
250         error = mptable_map(&mpt);
251         if (error) {
252                 mptable_fps_phyaddr = 0;
253                 return;
254         }
255
256         if (MPTABLE_POS_USE_DEFAULT(&mpt)) {
257                 kprintf("MPTABLE: use default configuration\n");
258                 mptable_use_default = 1;
259         }
260         if (mpt.mp_fps->mpfb2 & 0x80)
261                 imcr_present = 1;
262
263         mptable_unmap(&mpt);
264 }
265 SYSINIT(mptable_probe, SI_BOOT2_PRESMP, SI_ORDER_FIRST, mptable_probe, 0);
266
267 /*
268  * Look for an Intel MP spec table (ie, SMP capable hardware).
269  */
270 static int
271 mptable_search(void)
272 {
273         long    x;
274         u_int32_t target;
275  
276         /* see if EBDA exists */
277         if (ebda_addr != 0) {
278                 /* search first 1K of EBDA */
279                 target = (u_int32_t)ebda_addr;
280                 if ((x = mptable_search_sig(target, 1024 / 4)) > 0)
281                         return x;
282         } else {
283                 /* last 1K of base memory, effective 'top of base' passed in */
284                 target = (u_int32_t)((base_memory - 1) * 1024);
285                 if ((x = mptable_search_sig(target, 1024 / 4)) > 0)
286                         return x;
287         }
288
289         /* search the BIOS */
290         target = (u_int32_t)BIOS_BASE;
291         if ((x = mptable_search_sig(target, BIOS_COUNT)) > 0)
292                 return x;
293
294         /* search the extended BIOS */
295         target = (u_int32_t)BIOS_BASE2;
296         if ((x = mptable_search_sig(target, BIOS_COUNT)) > 0)
297                 return x;
298
299         /* nothing found */
300         return 0;
301 }
302
303 static int
304 mptable_iterate_entries(const mpcth_t cth, mptable_iter_func func, void *arg)
305 {
306         int count, total_size;
307         const void *position;
308
309         KKASSERT(cth->base_table_length >= sizeof(struct MPCTH));
310         total_size = cth->base_table_length - sizeof(struct MPCTH);
311         position = (const uint8_t *)cth + sizeof(struct MPCTH);
312         count = cth->entry_count;
313
314         while (count--) {
315                 int type, error;
316
317                 KKASSERT(total_size >= 0);
318                 if (total_size == 0) {
319                         kprintf("invalid base MP table, "
320                                 "entry count and length mismatch\n");
321                         return EINVAL;
322                 }
323
324                 type = *(const uint8_t *)position;
325                 switch (type) {
326                 case 0: /* processor_entry */
327                 case 1: /* bus_entry */
328                 case 2: /* io_apic_entry */
329                 case 3: /* int_entry */
330                 case 4: /* int_entry */
331                         break;
332                 default:
333                         kprintf("unknown base MP table entry type %d\n", type);
334                         return EINVAL;
335                 }
336
337                 if (total_size < basetable_entry_types[type].length) {
338                         kprintf("invalid base MP table length, "
339                                 "does not contain all entries\n");
340                         return EINVAL;
341                 }
342                 total_size -= basetable_entry_types[type].length;
343
344                 error = func(arg, position, type);
345                 if (error)
346                         return error;
347
348                 position = (const uint8_t *)position +
349                     basetable_entry_types[type].length;
350         }
351         return 0;
352 }
353
354 /*
355  * look for the MP spec signature
356  */
357
358 /* string defined by the Intel MP Spec as identifying the MP table */
359 #define MP_SIG          0x5f504d5f      /* _MP_ */
360 #define NEXT(X)         ((X) += 4)
361 static long
362 mptable_search_sig(u_int32_t target, int count)
363 {
364         vm_size_t map_size;
365         u_int32_t *addr;
366         int x, ret;
367
368         KKASSERT(target != 0);
369
370         map_size = count * sizeof(u_int32_t);
371         addr = pmap_mapdev((vm_paddr_t)target, map_size);
372
373         ret = 0;
374         for (x = 0; x < count; NEXT(x)) {
375                 if (addr[x] == MP_SIG) {
376                         /* make array index a byte index */
377                         ret = target + (x * sizeof(u_int32_t));
378                         break;
379                 }
380         }
381
382         pmap_unmapdev((vm_offset_t)addr, map_size);
383         return ret;
384 }
385
386 static int processor_entry      (const struct PROCENTRY *entry, int cpu);
387
388 /*
389  * Check if we should perform a hyperthreading "fix-up" to
390  * enumerate any logical CPU's that aren't already listed
391  * in the table.
392  *
393  * XXX: We assume that all of the physical CPUs in the
394  * system have the same number of logical CPUs.
395  *
396  * XXX: We assume that APIC ID's are allocated such that
397  * the APIC ID's for a physical processor are aligned
398  * with the number of logical CPU's in the processor.
399  */
400 static int
401 mptable_hyperthread_fixup(cpumask_t id_mask, int cpu_count)
402 {
403         int i, id, lcpus_max, logical_cpus;
404
405         if ((cpu_feature & CPUID_HTT) == 0)
406                 return 0;
407
408         lcpus_max = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
409         if (lcpus_max <= 1)
410                 return 0;
411
412         if (cpu_vendor_id == CPU_VENDOR_INTEL) {
413                 /*
414                  * INSTRUCTION SET REFERENCE, A-M (#253666)
415                  * Page 3-181, Table 3-20
416                  * "The nearest power-of-2 integer that is not smaller
417                  *  than EBX[23:16] is the number of unique initial APIC
418                  *  IDs reserved for addressing different logical
419                  *  processors in a physical package."
420                  */
421                 for (i = 0; ; ++i) {
422                         if ((1 << i) >= lcpus_max) {
423                                 lcpus_max = 1 << i;
424                                 break;
425                         }
426                 }
427         }
428
429         KKASSERT(cpu_count != 0);
430         if (cpu_count == lcpus_max) {
431                 /* We have nothing to fix */
432                 return 0;
433         } else if (cpu_count == 1) {
434                 /* XXX this may be incorrect */
435                 logical_cpus = lcpus_max;
436         } else {
437                 int cur, prev, dist;
438
439                 /*
440                  * Calculate the distances between two nearest
441                  * APIC IDs.  If all such distances are same,
442                  * then it is the number of missing cpus that
443                  * we are going to fill later.
444                  */
445                 dist = cur = prev = -1;
446                 for (id = 0; id < MAXCPU; ++id) {
447                         if (CPUMASK_TESTBIT(id_mask, id) == 0)
448                                 continue;
449
450                         cur = id;
451                         if (prev >= 0) {
452                                 int new_dist = cur - prev;
453
454                                 if (dist < 0)
455                                         dist = new_dist;
456
457                                 /*
458                                  * Make sure that all distances
459                                  * between two nearest APIC IDs
460                                  * are same.
461                                  */
462                                 if (dist != new_dist)
463                                         return 0;
464                         }
465                         prev = cur;
466                 }
467                 if (dist == 1)
468                         return 0;
469
470                 /* Must be power of 2 */
471                 if (dist & (dist - 1))
472                         return 0;
473
474                 /* Can't exceed CPU package capacity */
475                 if (dist > lcpus_max)
476                         logical_cpus = lcpus_max;
477                 else
478                         logical_cpus = dist;
479         }
480
481         /*
482          * For each APIC ID of a CPU that is set in the mask,
483          * scan the other candidate APIC ID's for this
484          * physical processor.  If any of those ID's are
485          * already in the table, then kill the fixup.
486          */
487         for (id = 0; id < MAXCPU; id++) {
488                 if (CPUMASK_TESTBIT(id_mask, id) == 0)
489                         continue;
490                 /* First, make sure we are on a logical_cpus boundary. */
491                 if (id % logical_cpus != 0)
492                         return 0;
493                 for (i = id + 1; i < id + logical_cpus; i++)
494                         if (CPUMASK_TESTBIT(id_mask, i) != 0)
495                                 return 0;
496         }
497         return logical_cpus;
498 }
499
500 static int
501 mptable_map(struct mptable_pos *mpt)
502 {
503         mpfps_t fps = NULL;
504         mpcth_t cth = NULL;
505         vm_size_t cth_mapsz = 0;
506
507         KKASSERT(mptable_fps_phyaddr != 0);
508
509         bzero(mpt, sizeof(*mpt));
510
511         fps = pmap_mapdev(mptable_fps_phyaddr, sizeof(*fps));
512         if (fps->pap != 0) {
513                 /*
514                  * Map configuration table header to get
515                  * the base table size
516                  */
517                 cth = pmap_mapdev(fps->pap, sizeof(*cth));
518                 cth_mapsz = cth->base_table_length;
519                 pmap_unmapdev((vm_offset_t)cth, sizeof(*cth));
520
521                 if (cth_mapsz < sizeof(*cth)) {
522                         kprintf("invalid base MP table length %d\n",
523                                 (int)cth_mapsz);
524                         pmap_unmapdev((vm_offset_t)fps, sizeof(*fps));
525                         return EINVAL;
526                 }
527
528                 /*
529                  * Map the base table
530                  */
531                 cth = pmap_mapdev(fps->pap, cth_mapsz);
532         }
533
534         mpt->mp_fps = fps;
535         mpt->mp_cth = cth;
536         mpt->mp_cth_mapsz = cth_mapsz;
537
538         return 0;
539 }
540
541 static void
542 mptable_unmap(struct mptable_pos *mpt)
543 {
544         if (mpt->mp_cth != NULL) {
545                 pmap_unmapdev((vm_offset_t)mpt->mp_cth, mpt->mp_cth_mapsz);
546                 mpt->mp_cth = NULL;
547                 mpt->mp_cth_mapsz = 0;
548         }
549         if (mpt->mp_fps != NULL) {
550                 pmap_unmapdev((vm_offset_t)mpt->mp_fps, sizeof(*mpt->mp_fps));
551                 mpt->mp_fps = NULL;
552         }
553 }
554
555 static int
556 processor_entry(const struct PROCENTRY *entry, int cpu)
557 {
558         KKASSERT(cpu > 0);
559
560         /* check for usability */
561         if (!(entry->cpu_flags & PROCENTRY_FLAG_EN))
562                 return 0;
563
564         /* check for BSP flag */
565         if (entry->cpu_flags & PROCENTRY_FLAG_BP) {
566                 lapic_set_cpuid(0, entry->apic_id);
567                 return 0;       /* its already been counted */
568         }
569
570         /* add another AP to list, if less than max number of CPUs */
571         else if (cpu < MAXCPU) {
572                 lapic_set_cpuid(cpu, entry->apic_id);
573                 return 1;
574         }
575
576         return 0;
577 }
578
579 static int
580 mptable_bus_info_callback(void *xarg, const void *pos, int type)
581 {
582         struct mptable_bus_info *bus_info = xarg;
583         const struct BUSENTRY *ent;
584         struct mptable_bus *bus;
585
586         if (type != 1)
587                 return 0;
588
589         ent = pos;
590         TAILQ_FOREACH(bus, &bus_info->mbi_list, mb_link) {
591                 if (bus->mb_id == ent->bus_id) {
592                         kprintf("mptable_bus_info_alloc: duplicated bus id "
593                                 "(%d)\n", bus->mb_id);
594                         return EINVAL;
595                 }
596         }
597
598         bus = NULL;
599         if (strncmp(ent->bus_type, "PCI", 3) == 0) {
600                 bus = kmalloc(sizeof(*bus), M_TEMP, M_WAITOK | M_ZERO);
601                 bus->mb_type = MPTABLE_BUS_PCI;
602         } else if (strncmp(ent->bus_type, "ISA", 3) == 0) {
603                 bus = kmalloc(sizeof(*bus), M_TEMP, M_WAITOK | M_ZERO);
604                 bus->mb_type = MPTABLE_BUS_ISA;
605         }
606
607         if (bus != NULL) {
608                 bus->mb_id = ent->bus_id;
609                 TAILQ_INSERT_TAIL(&bus_info->mbi_list, bus, mb_link);
610         }
611         return 0;
612 }
613
614 static void
615 mptable_bus_info_alloc(const mpcth_t cth, struct mptable_bus_info *bus_info)
616 {
617         int error;
618
619         bzero(bus_info, sizeof(*bus_info));
620         TAILQ_INIT(&bus_info->mbi_list);
621
622         error = mptable_iterate_entries(cth, mptable_bus_info_callback, bus_info);
623         if (error)
624                 mptable_bus_info_free(bus_info);
625 }
626
627 static void
628 mptable_bus_info_free(struct mptable_bus_info *bus_info)
629 {
630         struct mptable_bus *bus;
631
632         while ((bus = TAILQ_FIRST(&bus_info->mbi_list)) != NULL) {
633                 TAILQ_REMOVE(&bus_info->mbi_list, bus, mb_link);
634                 kfree(bus, M_TEMP);
635         }
636 }
637
638 struct mptable_lapic_cbarg1 {
639         int     cpu_count;
640         int     ht_fixup;
641         u_int   ht_apicid_mask;
642 };
643
644 static int
645 mptable_lapic_pass1_callback(void *xarg, const void *pos, int type)
646 {
647         const struct PROCENTRY *ent;
648         struct mptable_lapic_cbarg1 *arg = xarg;
649
650         if (type != 0)
651                 return 0;
652         ent = pos;
653
654         if ((ent->cpu_flags & PROCENTRY_FLAG_EN) == 0)
655                 return 0;
656
657         arg->cpu_count++;
658         if (ent->apic_id < 64) {
659                 arg->ht_apicid_mask |= 1UL << ent->apic_id;
660         } else if (arg->ht_fixup) {
661                 kprintf("MPTABLE: lapic id > 64, disable HTT fixup\n");
662                 arg->ht_fixup = 0;
663         }
664         return 0;
665 }
666
667 struct mptable_lapic_cbarg2 {
668         int     cpu;
669         int     logical_cpus;
670         int     found_bsp;
671 };
672
673 static int
674 mptable_lapic_pass2_callback(void *xarg, const void *pos, int type)
675 {
676         const struct PROCENTRY *ent;
677         struct mptable_lapic_cbarg2 *arg = xarg;
678
679         if (type != 0)
680                 return 0;
681         ent = pos;
682
683         if (ent->cpu_flags & PROCENTRY_FLAG_BP) {
684                 KKASSERT(!arg->found_bsp);
685                 arg->found_bsp = 1;
686         }
687
688         if (processor_entry(ent, arg->cpu))
689                 arg->cpu++;
690
691         if (arg->logical_cpus) {
692                 struct PROCENTRY proc;
693                 int i;
694
695                 /*
696                  * Create fake mptable processor entries
697                  * and feed them to processor_entry() to
698                  * enumerate the logical CPUs.
699                  */
700                 bzero(&proc, sizeof(proc));
701                 proc.type = 0;
702                 proc.cpu_flags = (force_enable) ? PROCENTRY_FLAG_EN : ent->cpu_flags;
703                 proc.apic_id = ent->apic_id;
704
705                 for (i = 1; i < arg->logical_cpus; i++) {
706                         proc.apic_id++;
707                         processor_entry(&proc, arg->cpu);
708                         arg->cpu++;
709                 }
710         }
711         return 0;
712 }
713
714 static void
715 mptable_lapic_default(void)
716 {
717         int ap_apicid, bsp_apicid;
718
719         naps = 1; /* exclude BSP */
720
721         /* Map local apic before the id field is accessed */
722         lapic_map(DEFAULT_APIC_BASE);
723
724         bsp_apicid = LAPIC_READID;
725         ap_apicid = (bsp_apicid == 0) ? 1 : 0;
726
727         /* BSP */
728         lapic_set_cpuid(0, bsp_apicid);
729         /* one and only AP */
730         lapic_set_cpuid(1, ap_apicid);
731 }
732
733 /*
734  * Configure:
735  *     naps
736  *     APIC ID <-> CPU ID mappings
737  */
738 static int
739 mptable_lapic_enumerate(struct lapic_enumerator *e)
740 {
741         struct mptable_pos mpt;
742         struct mptable_lapic_cbarg1 arg1;
743         struct mptable_lapic_cbarg2 arg2;
744         mpcth_t cth;
745         int error, logical_cpus = 0;
746         vm_paddr_t lapic_addr;
747
748         if (mptable_use_default) {
749                 mptable_lapic_default();
750                 return 0;
751         }
752  
753         error = mptable_map(&mpt);
754         if (error)
755                 panic("mptable_lapic_enumerate mptable_map failed");
756         KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt));
757
758         cth = mpt.mp_cth;
759  
760         /* Save local apic address */
761         lapic_addr = cth->apic_address;
762         KKASSERT(lapic_addr != 0);
763  
764         /*
765          * Find out how many CPUs do we have
766          */
767         bzero(&arg1, sizeof(arg1));
768         arg1.ht_fixup = 1; /* Apply ht fixup by default */
769
770         error = mptable_iterate_entries(cth,
771                     mptable_lapic_pass1_callback, &arg1);
772         if (error)
773                 panic("mptable_iterate_entries(lapic_pass1) failed");
774         KKASSERT(arg1.cpu_count != 0);
775  
776         /* See if we need to fixup HT logical CPUs. */
777         /*
778          * XXX fixup for cpus >= 32 ? XXX
779          */
780         if (arg1.ht_fixup) {
781                 cpumask_t mask;
782
783                 CPUMASK_ASSZERO(mask);
784                 mask.ary[0] = arg1.ht_apicid_mask;
785                 logical_cpus = mptable_hyperthread_fixup(mask, arg1.cpu_count);
786                 if (logical_cpus != 0)
787                         arg1.cpu_count *= logical_cpus;
788         }
789         naps = arg1.cpu_count - 1;      /* subtract the BSP */
790  
791         /*
792          * Link logical CPU id to local apic id
793          */
794         bzero(&arg2, sizeof(arg2));
795         arg2.cpu = 1;
796         arg2.logical_cpus = logical_cpus;
797
798         error = mptable_iterate_entries(cth,
799                     mptable_lapic_pass2_callback, &arg2);
800         if (error)
801                 panic("mptable_iterate_entries(lapic_pass2) failed");
802         KKASSERT(arg2.found_bsp);
803
804         /* Map local apic */
805         lapic_map(lapic_addr);
806
807         mptable_unmap(&mpt);
808
809         return 0;
810 }
811
812 struct mptable_lapic_probe_cbarg {
813         int     cpu_count;
814         int     found_bsp;
815 };
816
817 static int
818 mptable_lapic_probe_callback(void *xarg, const void *pos, int type)
819 {
820         const struct PROCENTRY *ent;
821         struct mptable_lapic_probe_cbarg *arg = xarg;
822
823         if (type != 0)
824                 return 0;
825         ent = pos;
826
827         if ((ent->cpu_flags & PROCENTRY_FLAG_EN) == 0)
828                 return 0;
829         arg->cpu_count++;
830
831         if (ent->apic_id == APICID_MAX) {
832                 kprintf("MPTABLE: invalid LAPIC apic id %d\n",
833                     ent->apic_id);
834                 return EINVAL;
835         }
836
837         if (ent->cpu_flags & PROCENTRY_FLAG_BP) {
838                 if (arg->found_bsp) {
839                         kprintf("more than one BSP in base MP table\n");
840                         return EINVAL;
841                 }
842                 arg->found_bsp = 1;
843         }
844         return 0;
845 }
846
847 static int
848 mptable_lapic_probe(struct lapic_enumerator *e)
849 {
850         struct mptable_pos mpt;
851         struct mptable_lapic_probe_cbarg arg;
852         mpcth_t cth;
853         int error;
854
855         if (mptable_fps_phyaddr == 0)
856                 return ENXIO;
857
858         if (mptable_use_default)
859                 return 0;
860
861         error = mptable_map(&mpt);
862         if (error)
863                 return error;
864         KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt));
865
866         error = EINVAL;
867         cth = mpt.mp_cth;
868
869         if (cth->apic_address == 0)
870                 goto done;
871
872         bzero(&arg, sizeof(arg));
873         error = mptable_iterate_entries(cth,
874                     mptable_lapic_probe_callback, &arg);
875         if (!error) {
876                 if (arg.cpu_count == 0) {
877                         kprintf("MP table contains no processor entries\n");
878                         error = EINVAL;
879                 } else if (!arg.found_bsp) {
880                         kprintf("MP table does not contains BSP entry\n");
881                         error = EINVAL;
882                 }
883         }
884 done:
885         mptable_unmap(&mpt);
886         return error;
887 }
888
889 static struct lapic_enumerator  mptable_lapic_enumerator = {
890         .lapic_prio = LAPIC_ENUM_PRIO_MPTABLE,
891         .lapic_probe = mptable_lapic_probe,
892         .lapic_enumerate = mptable_lapic_enumerate
893 };
894
895 static void
896 mptable_lapic_enum_register(void)
897 {
898         lapic_enumerator_register(&mptable_lapic_enumerator);
899 }
900 SYSINIT(mptable_lapic, SI_BOOT2_PRESMP, SI_ORDER_ANY,
901         mptable_lapic_enum_register, 0);
902
903 static int
904 mptable_ioapic_list_callback(void *xarg, const void *pos, int type)
905 {
906         const struct IOAPICENTRY *ent;
907         struct mptable_ioapic *nioapic, *ioapic;
908
909         if (type != 2)
910                 return 0;
911         ent = pos;
912
913         if ((ent->apic_flags & IOAPICENTRY_FLAG_EN) == 0)
914                 return 0;
915
916         if (ent->apic_address == 0) {
917                 kprintf("mptable_ioapic_create_list: zero IOAPIC addr\n");
918                 return EINVAL;
919         }
920         if (ent->apic_id == APICID_MAX) {
921                 kprintf("mptable_ioapic_create_list: "
922                     "invalid IOAPIC apic id %d\n", ent->apic_id);
923                 return EINVAL;
924         }
925
926         TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) {
927                 if (ioapic->mio_apic_id == ent->apic_id) {
928                         kprintf("mptable_ioapic_create_list: duplicated "
929                                 "apic id %d\n", ioapic->mio_apic_id);
930                         return EINVAL;
931                 }
932                 if (ioapic->mio_addr == ent->apic_address) {
933                         kprintf("mptable_ioapic_create_list: overlapped "
934                                 "IOAPIC addr 0x%08x", ioapic->mio_addr);
935                         return EINVAL;
936                 }
937         }
938
939         nioapic = kmalloc(sizeof(*nioapic), M_DEVBUF, M_WAITOK | M_ZERO);
940         nioapic->mio_apic_id = ent->apic_id;
941         nioapic->mio_addr = ent->apic_address;
942
943         /*
944          * Create IOAPIC list in ascending order of APIC ID
945          */
946         TAILQ_FOREACH_REVERSE(ioapic, &mptable_ioapic_list,
947             mptable_ioapic_list, mio_link) {
948                 if (nioapic->mio_apic_id > ioapic->mio_apic_id) {
949                         TAILQ_INSERT_AFTER(&mptable_ioapic_list,
950                             ioapic, nioapic, mio_link);
951                         break;
952                 }
953         }
954         if (ioapic == NULL)
955                 TAILQ_INSERT_HEAD(&mptable_ioapic_list, nioapic, mio_link);
956
957         return 0;
958 }
959
960 static void
961 mptable_ioapic_create_list(void)
962 {
963         struct mptable_ioapic *ioapic;
964         struct mptable_pos mpt;
965         int idx, error;
966
967         if (mptable_fps_phyaddr == 0)
968                 return;
969
970         if (mptable_use_default) {
971                 ioapic = kmalloc(sizeof(*ioapic), M_DEVBUF, M_WAITOK | M_ZERO);
972                 ioapic->mio_idx = 0;
973                 ioapic->mio_apic_id = 0;        /* NOTE: any value is ok here */
974                 ioapic->mio_addr = 0xfec00000;  /* XXX magic number */
975
976                 TAILQ_INSERT_HEAD(&mptable_ioapic_list, ioapic, mio_link);
977                 return;
978         }
979
980         error = mptable_map(&mpt);
981         if (error)
982                 panic("mptable_ioapic_create_list: mptable_map failed");
983         KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt));
984
985         error = mptable_iterate_entries(mpt.mp_cth,
986                     mptable_ioapic_list_callback, NULL);
987         if (error) {
988                 while ((ioapic = TAILQ_FIRST(&mptable_ioapic_list)) != NULL) {
989                         TAILQ_REMOVE(&mptable_ioapic_list, ioapic, mio_link);
990                         kfree(ioapic, M_DEVBUF);
991                 }
992                 goto done;
993         }
994
995         /*
996          * Assign index number for each IOAPIC
997          */
998         idx = 0;
999         TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) {
1000                 ioapic->mio_idx = idx;
1001                 ++idx;
1002         }
1003 done:
1004         mptable_unmap(&mpt);
1005 }
1006 SYSINIT(mptable_ioapic_list, SI_BOOT2_PRESMP, SI_ORDER_SECOND,
1007         mptable_ioapic_create_list, 0);
1008
1009 static int
1010 mptable_pci_int_callback(void *xarg, const void *pos, int type)
1011 {
1012         const struct mptable_bus_info *bus_info = xarg;
1013         const struct mptable_ioapic *ioapic;
1014         const struct mptable_bus *bus;
1015         struct mptable_pci_int *pci_int;
1016         const struct INTENTRY *ent;
1017         int pci_pin, pci_dev;
1018
1019         if (type != 3)
1020                 return 0;
1021         ent = pos;
1022
1023         if (ent->int_type != 0)
1024                 return 0;
1025
1026         TAILQ_FOREACH(bus, &bus_info->mbi_list, mb_link) {
1027                 if (bus->mb_type == MPTABLE_BUS_PCI &&
1028                     bus->mb_id == ent->src_bus_id)
1029                         break;
1030         }
1031         if (bus == NULL)
1032                 return 0;
1033
1034         TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) {
1035                 if (ioapic->mio_apic_id == ent->dst_apic_id)
1036                         break;
1037         }
1038         if (ioapic == NULL) {
1039                 if (bootverbose) {
1040                         static char intdis_warned[64];
1041                         int apic_id = ent->dst_apic_id;
1042                         int warn = 0;
1043
1044                         if (apic_id < 0 || apic_id >= sizeof(intdis_warned)) {
1045                                 warn = 1;
1046                         } else if (intdis_warned[apic_id] == 0) {
1047                                 intdis_warned[apic_id] = 1;
1048                                 warn = 1;
1049                         }
1050                         if (warn) {
1051                                 kprintf("MPTABLE: warning PCI int dst apic id "
1052                                     "%d does not exist\n", apic_id);
1053                         }
1054                 }
1055                 return 0;
1056         }
1057
1058         pci_pin = ent->src_bus_irq & 0x3;
1059         pci_dev = (ent->src_bus_irq >> 2) & 0x1f;
1060
1061         TAILQ_FOREACH(pci_int, &mptable_pci_int_list, mpci_link) {
1062                 if (pci_int->mpci_bus == ent->src_bus_id &&
1063                     pci_int->mpci_dev == pci_dev &&
1064                     pci_int->mpci_pin == pci_pin) {
1065                         if (pci_int->mpci_ioapic_idx == ioapic->mio_idx &&
1066                             pci_int->mpci_ioapic_pin == ent->dst_apic_int) {
1067                                 kprintf("MPTABLE: warning duplicated "
1068                                         "PCI int entry for "
1069                                         "bus %d, dev %d, pin %d\n",
1070                                         pci_int->mpci_bus,
1071                                         pci_int->mpci_dev,
1072                                         pci_int->mpci_pin);
1073                                 return 0;
1074                         } else {
1075                                 kprintf("mptable_pci_int_register: "
1076                                         "conflict PCI int entry for "
1077                                         "bus %d, dev %d, pin %d, "
1078                                         "IOAPIC %d.%d -> %d.%d\n",
1079                                         pci_int->mpci_bus,
1080                                         pci_int->mpci_dev,
1081                                         pci_int->mpci_pin,
1082                                         pci_int->mpci_ioapic_idx,
1083                                         pci_int->mpci_ioapic_pin,
1084                                         ioapic->mio_idx,
1085                                         ent->dst_apic_int);
1086                                 return EINVAL;
1087                         }
1088                 }
1089         }
1090
1091         pci_int = kmalloc(sizeof(*pci_int), M_DEVBUF, M_WAITOK | M_ZERO);
1092
1093         pci_int->mpci_bus = ent->src_bus_id;
1094         pci_int->mpci_dev = pci_dev;
1095         pci_int->mpci_pin = pci_pin;
1096         pci_int->mpci_ioapic_idx = ioapic->mio_idx;
1097         pci_int->mpci_ioapic_pin = ent->dst_apic_int;
1098
1099         TAILQ_INSERT_TAIL(&mptable_pci_int_list, pci_int, mpci_link);
1100
1101         return 0;
1102 }
1103
1104 static void
1105 mptable_pci_int_register(void)
1106 {
1107         struct mptable_bus_info bus_info;
1108         const struct mptable_bus *bus;
1109         struct mptable_pci_int *pci_int;
1110         struct mptable_pos mpt;
1111         int error, force_pci0, npcibus;
1112         mpcth_t cth;
1113
1114         if (mptable_fps_phyaddr == 0)
1115                 return;
1116
1117         if (mptable_use_default)
1118                 return;
1119
1120         if (TAILQ_EMPTY(&mptable_ioapic_list))
1121                 return;
1122
1123         error = mptable_map(&mpt);
1124         if (error)
1125                 panic("mptable_pci_int_register: mptable_map failed");
1126         KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt));
1127
1128         cth = mpt.mp_cth;
1129
1130         mptable_bus_info_alloc(cth, &bus_info);
1131         if (TAILQ_EMPTY(&bus_info.mbi_list))
1132                 goto done;
1133
1134         force_pci0 = 0;
1135         npcibus = 0;
1136         TAILQ_FOREACH(bus, &bus_info.mbi_list, mb_link) {
1137                 if (bus->mb_type == MPTABLE_BUS_PCI)
1138                         ++npcibus;
1139         }
1140         if (npcibus == 0) {
1141                 mptable_bus_info_free(&bus_info);
1142                 goto done;
1143         } else if (npcibus == 1) {
1144                 force_pci0 = 1;
1145         }
1146
1147         error = mptable_iterate_entries(cth,
1148                     mptable_pci_int_callback, &bus_info);
1149
1150         mptable_bus_info_free(&bus_info);
1151
1152         if (error) {
1153                 while ((pci_int = TAILQ_FIRST(&mptable_pci_int_list)) != NULL) {
1154                         TAILQ_REMOVE(&mptable_pci_int_list, pci_int, mpci_link);
1155                         kfree(pci_int, M_DEVBUF);
1156                 }
1157                 goto done;
1158         }
1159
1160         if (force_pci0) {
1161                 TAILQ_FOREACH(pci_int, &mptable_pci_int_list, mpci_link)
1162                         pci_int->mpci_bus = 0;
1163         }
1164 done:
1165         mptable_unmap(&mpt);
1166 }
1167 SYSINIT(mptable_pci, SI_BOOT2_PRESMP, SI_ORDER_ANY,
1168         mptable_pci_int_register, 0);
1169
1170 struct mptable_ioapic_probe_cbarg {
1171         const struct mptable_bus_info *bus_info;
1172 };
1173
1174 static int
1175 mptable_ioapic_probe_callback(void *xarg, const void *pos, int type)
1176 {
1177         struct mptable_ioapic_probe_cbarg *arg = xarg;
1178         const struct mptable_ioapic *ioapic;
1179         const struct mptable_bus *bus;
1180         const struct INTENTRY *ent;
1181
1182         if (type != 3)
1183                 return 0;
1184         ent = pos;
1185
1186         if (ent->int_type != 0)
1187                 return 0;
1188
1189         TAILQ_FOREACH(bus, &arg->bus_info->mbi_list, mb_link) {
1190                 if (bus->mb_type == MPTABLE_BUS_ISA &&
1191                     bus->mb_id == ent->src_bus_id)
1192                         break;
1193         }
1194         if (bus == NULL)
1195                 return 0;
1196
1197         TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) {
1198                 if (ioapic->mio_apic_id == ent->dst_apic_id)
1199                         break;
1200         }
1201         if (ioapic == NULL) {
1202                 kprintf("MPTABLE: warning ISA int dst apic id %d "
1203                         "does not exist\n", ent->dst_apic_id);
1204                 return 0;
1205         }
1206
1207         /* XXX magic number */
1208         if (ent->src_bus_irq >= ISA_IRQ_CNT) {
1209                 kprintf("mptable_ioapic_probe: invalid ISA irq (%d)\n",
1210                         ent->src_bus_irq);
1211                 return EINVAL;
1212         }
1213         return 0;
1214 }
1215
1216 static int
1217 mptable_ioapic_probe(struct ioapic_enumerator *e)
1218 {
1219         struct mptable_ioapic_probe_cbarg arg;
1220         struct mptable_bus_info bus_info;
1221         struct mptable_pos mpt;
1222         mpcth_t cth;
1223         int error;
1224
1225         if (mptable_fps_phyaddr == 0)
1226                 return ENXIO;
1227
1228         if (mptable_use_default)
1229                 return 0;
1230
1231         if (TAILQ_EMPTY(&mptable_ioapic_list))
1232                 return ENXIO;
1233
1234         error = mptable_map(&mpt);
1235         if (error)
1236                 panic("mptable_ioapic_probe: mptable_map failed");
1237         KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt));
1238
1239         cth = mpt.mp_cth;
1240
1241         mptable_bus_info_alloc(cth, &bus_info);
1242
1243         bzero(&arg, sizeof(arg));
1244         arg.bus_info = &bus_info;
1245
1246         error = mptable_iterate_entries(cth,
1247                     mptable_ioapic_probe_callback, &arg);
1248
1249         mptable_bus_info_free(&bus_info);
1250         mptable_unmap(&mpt);
1251
1252         return error;
1253 }
1254
1255 struct mptable_ioapic_int_cbarg {
1256         const struct mptable_bus_info *bus_info;
1257         int     ioapic_nint;
1258 };
1259
1260 static int
1261 mptable_ioapic_int_callback(void *xarg, const void *pos, int type)
1262 {
1263         struct mptable_ioapic_int_cbarg *arg = xarg;
1264         const struct mptable_ioapic *ioapic;
1265         const struct mptable_bus *bus;
1266         const struct INTENTRY *ent;
1267         int gsi;
1268
1269         if (type != 3)
1270                 return 0;
1271
1272         arg->ioapic_nint++;
1273
1274         ent = pos;
1275         if (ent->int_type != 0)
1276                 return 0;
1277
1278         TAILQ_FOREACH(bus, &arg->bus_info->mbi_list, mb_link) {
1279                 if (bus->mb_type == MPTABLE_BUS_ISA &&
1280                     bus->mb_id == ent->src_bus_id)
1281                         break;
1282         }
1283         if (bus == NULL)
1284                 return 0;
1285
1286         TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) {
1287                 if (ioapic->mio_apic_id == ent->dst_apic_id)
1288                         break;
1289         }
1290         if (ioapic == NULL) {
1291                 kprintf("MPTABLE: warning ISA int dst apic id %d "
1292                         "does not exist\n", ent->dst_apic_id);
1293                 return 0;
1294         }
1295
1296         if (ent->dst_apic_int >= ioapic->mio_npin) {
1297                 panic("mptable_ioapic_enumerate: invalid I/O APIC "
1298                       "pin %d, should be < %d",
1299                       ent->dst_apic_int, ioapic->mio_npin);
1300         }
1301         gsi = ioapic->mio_gsi_base + ent->dst_apic_int;
1302
1303         if (ent->src_bus_irq != gsi) {
1304                 if (bootverbose) {
1305                         kprintf("MPTABLE: INTSRC irq %d -> GSI %d\n",
1306                                 ent->src_bus_irq, gsi);
1307                 }
1308                 ioapic_intsrc(ent->src_bus_irq, gsi,
1309                     INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH);
1310         }
1311         return 0;
1312 }
1313
1314 static void
1315 mptable_ioapic_enumerate(struct ioapic_enumerator *e)
1316 {
1317         struct mptable_bus_info bus_info;
1318         struct mptable_ioapic *ioapic;
1319         struct mptable_pos mpt;
1320         mpcth_t cth;
1321         int error;
1322
1323         KKASSERT(mptable_fps_phyaddr != 0);
1324         KKASSERT(!TAILQ_EMPTY(&mptable_ioapic_list));
1325
1326         TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) {
1327                 const struct mptable_ioapic *prev_ioapic;
1328                 uint32_t ver;
1329                 void *addr;
1330
1331                 addr = ioapic_map(ioapic->mio_addr);
1332
1333                 ver = ioapic_read(addr, IOAPIC_VER);
1334                 ioapic->mio_npin = ((ver & IOART_VER_MAXREDIR)
1335                                     >> MAXREDIRSHIFT) + 1;
1336
1337                 prev_ioapic = TAILQ_PREV(ioapic,
1338                                 mptable_ioapic_list, mio_link);
1339                 if (prev_ioapic == NULL) {
1340                         ioapic->mio_gsi_base = 0;
1341                 } else {
1342                         ioapic->mio_gsi_base =
1343                                 prev_ioapic->mio_gsi_base +
1344                                 prev_ioapic->mio_npin;
1345                 }
1346                 ioapic_add(addr, ioapic->mio_gsi_base, ioapic->mio_npin);
1347
1348                 if (bootverbose) {
1349                         kprintf("MPTABLE: IOAPIC addr 0x%08x, "
1350                                 "apic id %d, idx %d, gsi base %d, npin %d\n",
1351                                 ioapic->mio_addr,
1352                                 ioapic->mio_apic_id,
1353                                 ioapic->mio_idx,
1354                                 ioapic->mio_gsi_base,
1355                                 ioapic->mio_npin);
1356                 }
1357         }
1358
1359         if (mptable_use_default) {
1360                 if (bootverbose)
1361                         kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 (default)\n");
1362                 ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH);
1363                 return;
1364         }
1365
1366         error = mptable_map(&mpt);
1367         if (error)
1368                 panic("mptable_ioapic_probe: mptable_map failed");
1369         KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt));
1370
1371         cth = mpt.mp_cth;
1372
1373         mptable_bus_info_alloc(cth, &bus_info);
1374
1375         if (TAILQ_EMPTY(&bus_info.mbi_list)) {
1376                 if (bootverbose)
1377                         kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 (no bus)\n");
1378                 ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH);
1379         } else {
1380                 struct mptable_ioapic_int_cbarg arg;
1381
1382                 bzero(&arg, sizeof(arg));
1383                 arg.bus_info = &bus_info;
1384
1385                 error = mptable_iterate_entries(cth,
1386                             mptable_ioapic_int_callback, &arg);
1387                 if (error)
1388                         panic("mptable_ioapic_int failed");
1389
1390                 if (arg.ioapic_nint == 0) {
1391                         if (bootverbose) {
1392                                 kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 "
1393                                         "(no int)\n");
1394                         }
1395                         ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE,
1396                             INTR_POLARITY_HIGH);
1397                 }
1398         }
1399
1400         mptable_bus_info_free(&bus_info);
1401
1402         mptable_unmap(&mpt);
1403 }
1404
1405 static struct ioapic_enumerator mptable_ioapic_enumerator = {
1406         .ioapic_prio = IOAPIC_ENUM_PRIO_MPTABLE,
1407         .ioapic_probe = mptable_ioapic_probe,
1408         .ioapic_enumerate = mptable_ioapic_enumerate
1409 };
1410
1411 static void
1412 mptable_ioapic_enum_register(void)
1413 {
1414         ioapic_enumerator_register(&mptable_ioapic_enumerator);
1415 }
1416 SYSINIT(mptable_ioapic, SI_BOOT2_PRESMP, SI_ORDER_ANY,
1417         mptable_ioapic_enum_register, 0);
1418
1419 void
1420 mptable_pci_int_dump(void)
1421 {
1422         const struct mptable_pci_int *pci_int;
1423
1424         if (!bootverbose)
1425                 return;
1426
1427         TAILQ_FOREACH(pci_int, &mptable_pci_int_list, mpci_link) {
1428                 kprintf("MPTABLE: %d:%d INT%c -> IOAPIC %d.%d\n",
1429                         pci_int->mpci_bus,
1430                         pci_int->mpci_dev,
1431                         pci_int->mpci_pin + 'A',
1432                         pci_int->mpci_ioapic_idx,
1433                         pci_int->mpci_ioapic_pin);
1434         }
1435 }
1436
1437 int
1438 mptable_pci_int_route(int bus, int dev, int pin, int intline)
1439 {
1440         const struct mptable_pci_int *pci_int;
1441         int irq = -1;
1442
1443         KKASSERT(pin >= 1);
1444         --pin;  /* zero based */
1445
1446         TAILQ_FOREACH(pci_int, &mptable_pci_int_list, mpci_link) {
1447                 if (pci_int->mpci_bus == bus &&
1448                     pci_int->mpci_dev == dev &&
1449                     pci_int->mpci_pin == pin)
1450                         break;
1451         }
1452         if (pci_int != NULL) {
1453                 int gsi;
1454
1455                 gsi = ioapic_gsi(pci_int->mpci_ioapic_idx,
1456                         pci_int->mpci_ioapic_pin);
1457                 if (gsi >= 0) {
1458                         irq = machintr_legacy_intr_find_bygsi(gsi,
1459                                 INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW);
1460                 }
1461         }
1462
1463         if (irq < 0 && intline >= 0) {
1464                 kprintf("MPTABLE: fixed interrupt routing "
1465                     "for %d:%d INT%c\n", bus, dev, pin + 'A');
1466                 irq = machintr_legacy_intr_find(intline,
1467                         INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW);
1468         }
1469
1470         if (irq >= 0 && bootverbose) {
1471                 kprintf("MPTABLE: %d:%d INT%c routed to irq %d\n",
1472                         bus, dev, pin + 'A', irq);
1473         }
1474         return irq;
1475 }