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