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