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