xref: /dragonfly/sys/platform/pc64/x86_64/mptable.c (revision 38c2ea22)
1 /*
2  * Copyright (c) 1996, by Steve Passe
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. The name of the developer may NOT be used to endorse or promote products
11  *    derived from this software without specific prior written permission.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  * $FreeBSD: src/sys/i386/i386/mp_machdep.c,v 1.115.2.15 2003/03/14 21:22:35 jhb Exp $
26  */
27 
28 #include "opt_cpu.h"
29 
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/sysctl.h>
34 #include <sys/malloc.h>
35 #include <sys/memrange.h>
36 #include <sys/cons.h>	/* cngetc() */
37 #include <sys/machintr.h>
38 
39 #include <sys/mplock2.h>
40 
41 #include <vm/vm.h>
42 #include <vm/vm_param.h>
43 #include <vm/pmap.h>
44 #include <vm/vm_kern.h>
45 #include <vm/vm_extern.h>
46 #include <sys/lock.h>
47 #include <vm/vm_map.h>
48 #include <sys/user.h>
49 #ifdef GPROF
50 #include <sys/gmon.h>
51 #endif
52 
53 #include <machine/smp.h>
54 #include <machine_base/isa/isa_intr.h>
55 #include <machine_base/apic/apicreg.h>
56 #include <machine/atomic.h>
57 #include <machine/cpufunc.h>
58 #include <machine/cputypes.h>
59 #include <machine_base/apic/lapic.h>
60 #include <machine_base/apic/ioapic.h>
61 #include <machine/psl.h>
62 #include <machine/segments.h>
63 #include <machine/tss.h>
64 #include <machine/specialreg.h>
65 #include <machine/globaldata.h>
66 #include <machine/pmap_inval.h>
67 #include <machine/mptable.h>
68 
69 #include <machine/md_var.h>		/* setidt() */
70 #include <machine_base/icu/icu.h>	/* IPIs */
71 #include <machine_base/apic/ioapic_abi.h>
72 #include <machine/intr_machdep.h>	/* IPIs */
73 
74 extern u_int	base_memory;
75 extern u_long	ebda_addr;
76 extern int	imcr_present;
77 extern int	naps;
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 void	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 ((id_mask & CPUMASK(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 ((id_mask & CPUMASK(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 ((id_mask & CPUMASK(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 < 32) {
661 		arg->ht_apicid_mask |= 1 << ent->apic_id;
662 	} else if (arg->ht_fixup) {
663 		kprintf("MPTABLE: lapic id > 32, 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 = PROCENTRY_FLAG_EN;
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 = APIC_ID(lapic->id);
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 void
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;
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 	if (arg1.ht_fixup) {
780 		logical_cpus = mptable_hyperthread_fixup(arg1.ht_apicid_mask,
781 							 arg1.cpu_count);
782 		if (logical_cpus != 0)
783 			arg1.cpu_count *= logical_cpus;
784 	}
785 	naps = arg1.cpu_count - 1;	/* subtract the BSP */
786 
787 	/*
788 	 * Link logical CPU id to local apic id
789 	 */
790 	bzero(&arg2, sizeof(arg2));
791 	arg2.cpu = 1;
792 	arg2.logical_cpus = logical_cpus;
793 
794 	error = mptable_iterate_entries(cth,
795 		    mptable_lapic_pass2_callback, &arg2);
796 	if (error)
797 		panic("mptable_iterate_entries(lapic_pass2) failed");
798 	KKASSERT(arg2.found_bsp);
799 
800 	/* Map local apic */
801 	lapic_map(lapic_addr);
802 
803 	mptable_unmap(&mpt);
804 }
805 
806 struct mptable_lapic_probe_cbarg {
807 	int	cpu_count;
808 	int	found_bsp;
809 };
810 
811 static int
812 mptable_lapic_probe_callback(void *xarg, const void *pos, int type)
813 {
814 	const struct PROCENTRY *ent;
815 	struct mptable_lapic_probe_cbarg *arg = xarg;
816 
817 	if (type != 0)
818 		return 0;
819 	ent = pos;
820 
821 	if ((ent->cpu_flags & PROCENTRY_FLAG_EN) == 0)
822 		return 0;
823 	arg->cpu_count++;
824 
825 	if (ent->cpu_flags & PROCENTRY_FLAG_BP) {
826 		if (arg->found_bsp) {
827 			kprintf("more than one BSP in base MP table\n");
828 			return EINVAL;
829 		}
830 		arg->found_bsp = 1;
831 	}
832 	return 0;
833 }
834 
835 static int
836 mptable_lapic_probe(struct lapic_enumerator *e)
837 {
838 	struct mptable_pos mpt;
839 	struct mptable_lapic_probe_cbarg arg;
840 	mpcth_t cth;
841 	int error;
842 
843 	if (mptable_fps_phyaddr == 0)
844 		return ENXIO;
845 
846 	if (mptable_use_default)
847 		return 0;
848 
849 	error = mptable_map(&mpt);
850 	if (error)
851 		return error;
852 	KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt));
853 
854 	error = EINVAL;
855 	cth = mpt.mp_cth;
856 
857 	if (cth->apic_address == 0)
858 		goto done;
859 
860 	bzero(&arg, sizeof(arg));
861 	error = mptable_iterate_entries(cth,
862 		    mptable_lapic_probe_callback, &arg);
863 	if (!error) {
864 		if (arg.cpu_count == 0) {
865 			kprintf("MP table contains no processor entries\n");
866 			error = EINVAL;
867 		} else if (!arg.found_bsp) {
868 			kprintf("MP table does not contains BSP entry\n");
869 			error = EINVAL;
870 		}
871 	}
872 done:
873 	mptable_unmap(&mpt);
874 	return error;
875 }
876 
877 static struct lapic_enumerator	mptable_lapic_enumerator = {
878 	.lapic_prio = LAPIC_ENUM_PRIO_MPTABLE,
879 	.lapic_probe = mptable_lapic_probe,
880 	.lapic_enumerate = mptable_lapic_enumerate
881 };
882 
883 static void
884 mptable_lapic_enum_register(void)
885 {
886 	lapic_enumerator_register(&mptable_lapic_enumerator);
887 }
888 SYSINIT(mptable_lapic, SI_BOOT2_PRESMP, SI_ORDER_ANY,
889 	mptable_lapic_enum_register, 0);
890 
891 static int
892 mptable_ioapic_list_callback(void *xarg, const void *pos, int type)
893 {
894 	const struct IOAPICENTRY *ent;
895 	struct mptable_ioapic *nioapic, *ioapic;
896 
897 	if (type != 2)
898 		return 0;
899 	ent = pos;
900 
901 	if ((ent->apic_flags & IOAPICENTRY_FLAG_EN) == 0)
902 		return 0;
903 
904 	if (ent->apic_address == 0) {
905 		kprintf("mptable_ioapic_create_list: zero IOAPIC addr\n");
906 		return EINVAL;
907 	}
908 
909 	TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) {
910 		if (ioapic->mio_apic_id == ent->apic_id) {
911 			kprintf("mptable_ioapic_create_list: duplicated "
912 				"apic id %d\n", ioapic->mio_apic_id);
913 			return EINVAL;
914 		}
915 		if (ioapic->mio_addr == ent->apic_address) {
916 			kprintf("mptable_ioapic_create_list: overlapped "
917 				"IOAPIC addr 0x%08x", ioapic->mio_addr);
918 			return EINVAL;
919 		}
920 	}
921 
922 	nioapic = kmalloc(sizeof(*nioapic), M_DEVBUF, M_WAITOK | M_ZERO);
923 	nioapic->mio_apic_id = ent->apic_id;
924 	nioapic->mio_addr = ent->apic_address;
925 
926 	/*
927 	 * Create IOAPIC list in ascending order of APIC ID
928 	 */
929 	TAILQ_FOREACH_REVERSE(ioapic, &mptable_ioapic_list,
930 	    mptable_ioapic_list, mio_link) {
931 		if (nioapic->mio_apic_id > ioapic->mio_apic_id) {
932 			TAILQ_INSERT_AFTER(&mptable_ioapic_list,
933 			    ioapic, nioapic, mio_link);
934 			break;
935 		}
936 	}
937 	if (ioapic == NULL)
938 		TAILQ_INSERT_HEAD(&mptable_ioapic_list, nioapic, mio_link);
939 
940 	return 0;
941 }
942 
943 static void
944 mptable_ioapic_create_list(void)
945 {
946 	struct mptable_ioapic *ioapic;
947 	struct mptable_pos mpt;
948 	int idx, error;
949 
950 	if (mptable_fps_phyaddr == 0)
951 		return;
952 
953 	if (mptable_use_default) {
954 		ioapic = kmalloc(sizeof(*ioapic), M_DEVBUF, M_WAITOK | M_ZERO);
955 		ioapic->mio_idx = 0;
956 		ioapic->mio_apic_id = 0;	/* NOTE: any value is ok here */
957 		ioapic->mio_addr = 0xfec00000;	/* XXX magic number */
958 
959 		TAILQ_INSERT_HEAD(&mptable_ioapic_list, ioapic, mio_link);
960 		return;
961 	}
962 
963 	error = mptable_map(&mpt);
964 	if (error)
965 		panic("mptable_ioapic_create_list: mptable_map failed");
966 	KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt));
967 
968 	error = mptable_iterate_entries(mpt.mp_cth,
969 		    mptable_ioapic_list_callback, NULL);
970 	if (error) {
971 		while ((ioapic = TAILQ_FIRST(&mptable_ioapic_list)) != NULL) {
972 			TAILQ_REMOVE(&mptable_ioapic_list, ioapic, mio_link);
973 			kfree(ioapic, M_DEVBUF);
974 		}
975 		goto done;
976 	}
977 
978 	/*
979 	 * Assign index number for each IOAPIC
980 	 */
981 	idx = 0;
982 	TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) {
983 		ioapic->mio_idx = idx;
984 		++idx;
985 	}
986 done:
987 	mptable_unmap(&mpt);
988 }
989 SYSINIT(mptable_ioapic_list, SI_BOOT2_PRESMP, SI_ORDER_SECOND,
990 	mptable_ioapic_create_list, 0);
991 
992 static int
993 mptable_pci_int_callback(void *xarg, const void *pos, int type)
994 {
995 	const struct mptable_bus_info *bus_info = xarg;
996 	const struct mptable_ioapic *ioapic;
997 	const struct mptable_bus *bus;
998 	struct mptable_pci_int *pci_int;
999 	const struct INTENTRY *ent;
1000 	int pci_pin, pci_dev;
1001 
1002 	if (type != 3)
1003 		return 0;
1004 	ent = pos;
1005 
1006 	if (ent->int_type != 0)
1007 		return 0;
1008 
1009 	TAILQ_FOREACH(bus, &bus_info->mbi_list, mb_link) {
1010 		if (bus->mb_type == MPTABLE_BUS_PCI &&
1011 		    bus->mb_id == ent->src_bus_id)
1012 			break;
1013 	}
1014 	if (bus == NULL)
1015 		return 0;
1016 
1017 	TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) {
1018 		if (ioapic->mio_apic_id == ent->dst_apic_id)
1019 			break;
1020 	}
1021 	if (ioapic == NULL) {
1022 		kprintf("MPTABLE: warning PCI int dst apic id %d "
1023 			"does not exist\n", ent->dst_apic_id);
1024 		return 0;
1025 	}
1026 
1027 	pci_pin = ent->src_bus_irq & 0x3;
1028 	pci_dev = (ent->src_bus_irq >> 2) & 0x1f;
1029 
1030 	TAILQ_FOREACH(pci_int, &mptable_pci_int_list, mpci_link) {
1031 		if (pci_int->mpci_bus == ent->src_bus_id &&
1032 		    pci_int->mpci_dev == pci_dev &&
1033 		    pci_int->mpci_pin == pci_pin) {
1034 			if (pci_int->mpci_ioapic_idx == ioapic->mio_idx &&
1035 			    pci_int->mpci_ioapic_pin == ent->dst_apic_int) {
1036 				kprintf("MPTABLE: warning duplicated "
1037 					"PCI int entry for "
1038 					"bus %d, dev %d, pin %d\n",
1039 					pci_int->mpci_bus,
1040 					pci_int->mpci_dev,
1041 					pci_int->mpci_pin);
1042 				return 0;
1043 			} else {
1044 				kprintf("mptable_pci_int_register: "
1045 					"conflict PCI int entry for "
1046 					"bus %d, dev %d, pin %d, "
1047 					"IOAPIC %d.%d -> %d.%d\n",
1048 					pci_int->mpci_bus,
1049 					pci_int->mpci_dev,
1050 					pci_int->mpci_pin,
1051 					pci_int->mpci_ioapic_idx,
1052 					pci_int->mpci_ioapic_pin,
1053 					ioapic->mio_idx,
1054 					ent->dst_apic_int);
1055 				return EINVAL;
1056 			}
1057 		}
1058 	}
1059 
1060 	pci_int = kmalloc(sizeof(*pci_int), M_DEVBUF, M_WAITOK | M_ZERO);
1061 
1062 	pci_int->mpci_bus = ent->src_bus_id;
1063 	pci_int->mpci_dev = pci_dev;
1064 	pci_int->mpci_pin = pci_pin;
1065 	pci_int->mpci_ioapic_idx = ioapic->mio_idx;
1066 	pci_int->mpci_ioapic_pin = ent->dst_apic_int;
1067 
1068 	TAILQ_INSERT_TAIL(&mptable_pci_int_list, pci_int, mpci_link);
1069 
1070 	return 0;
1071 }
1072 
1073 static void
1074 mptable_pci_int_register(void)
1075 {
1076 	struct mptable_bus_info bus_info;
1077 	const struct mptable_bus *bus;
1078 	struct mptable_pci_int *pci_int;
1079 	struct mptable_pos mpt;
1080 	int error, force_pci0, npcibus;
1081 	mpcth_t cth;
1082 
1083 	if (mptable_fps_phyaddr == 0)
1084 		return;
1085 
1086 	if (mptable_use_default)
1087 		return;
1088 
1089 	if (TAILQ_EMPTY(&mptable_ioapic_list))
1090 		return;
1091 
1092 	error = mptable_map(&mpt);
1093 	if (error)
1094 		panic("mptable_pci_int_register: mptable_map failed");
1095 	KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt));
1096 
1097 	cth = mpt.mp_cth;
1098 
1099 	mptable_bus_info_alloc(cth, &bus_info);
1100 	if (TAILQ_EMPTY(&bus_info.mbi_list))
1101 		goto done;
1102 
1103 	force_pci0 = 0;
1104 	npcibus = 0;
1105 	TAILQ_FOREACH(bus, &bus_info.mbi_list, mb_link) {
1106 		if (bus->mb_type == MPTABLE_BUS_PCI)
1107 			++npcibus;
1108 	}
1109 	if (npcibus == 0) {
1110 		mptable_bus_info_free(&bus_info);
1111 		goto done;
1112 	} else if (npcibus == 1) {
1113 		force_pci0 = 1;
1114 	}
1115 
1116 	error = mptable_iterate_entries(cth,
1117 		    mptable_pci_int_callback, &bus_info);
1118 
1119 	mptable_bus_info_free(&bus_info);
1120 
1121 	if (error) {
1122 		while ((pci_int = TAILQ_FIRST(&mptable_pci_int_list)) != NULL) {
1123 			TAILQ_REMOVE(&mptable_pci_int_list, pci_int, mpci_link);
1124 			kfree(pci_int, M_DEVBUF);
1125 		}
1126 		goto done;
1127 	}
1128 
1129 	if (force_pci0) {
1130 		TAILQ_FOREACH(pci_int, &mptable_pci_int_list, mpci_link)
1131 			pci_int->mpci_bus = 0;
1132 	}
1133 done:
1134 	mptable_unmap(&mpt);
1135 }
1136 SYSINIT(mptable_pci, SI_BOOT2_PRESMP, SI_ORDER_ANY,
1137 	mptable_pci_int_register, 0);
1138 
1139 struct mptable_ioapic_probe_cbarg {
1140 	const struct mptable_bus_info *bus_info;
1141 };
1142 
1143 static int
1144 mptable_ioapic_probe_callback(void *xarg, const void *pos, int type)
1145 {
1146 	struct mptable_ioapic_probe_cbarg *arg = xarg;
1147 	const struct mptable_ioapic *ioapic;
1148 	const struct mptable_bus *bus;
1149 	const struct INTENTRY *ent;
1150 
1151 	if (type != 3)
1152 		return 0;
1153 	ent = pos;
1154 
1155 	if (ent->int_type != 0)
1156 		return 0;
1157 
1158 	TAILQ_FOREACH(bus, &arg->bus_info->mbi_list, mb_link) {
1159 		if (bus->mb_type == MPTABLE_BUS_ISA &&
1160 		    bus->mb_id == ent->src_bus_id)
1161 			break;
1162 	}
1163 	if (bus == NULL)
1164 		return 0;
1165 
1166 	TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) {
1167 		if (ioapic->mio_apic_id == ent->dst_apic_id)
1168 			break;
1169 	}
1170 	if (ioapic == NULL) {
1171 		kprintf("MPTABLE: warning ISA int dst apic id %d "
1172 			"does not exist\n", ent->dst_apic_id);
1173 		return 0;
1174 	}
1175 
1176 	/* XXX magic number */
1177 	if (ent->src_bus_irq >= ISA_IRQ_CNT) {
1178 		kprintf("mptable_ioapic_probe: invalid ISA irq (%d)\n",
1179 			ent->src_bus_irq);
1180 		return EINVAL;
1181 	}
1182 	return 0;
1183 }
1184 
1185 static int
1186 mptable_ioapic_probe(struct ioapic_enumerator *e)
1187 {
1188 	struct mptable_ioapic_probe_cbarg arg;
1189 	struct mptable_bus_info bus_info;
1190 	struct mptable_pos mpt;
1191 	mpcth_t cth;
1192 	int error;
1193 
1194 	if (mptable_fps_phyaddr == 0)
1195 		return ENXIO;
1196 
1197 	if (mptable_use_default)
1198 		return 0;
1199 
1200 	if (TAILQ_EMPTY(&mptable_ioapic_list))
1201 		return ENXIO;
1202 
1203 	error = mptable_map(&mpt);
1204 	if (error)
1205 		panic("mptable_ioapic_probe: mptable_map failed");
1206 	KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt));
1207 
1208 	cth = mpt.mp_cth;
1209 
1210 	mptable_bus_info_alloc(cth, &bus_info);
1211 
1212 	bzero(&arg, sizeof(arg));
1213 	arg.bus_info = &bus_info;
1214 
1215 	error = mptable_iterate_entries(cth,
1216 		    mptable_ioapic_probe_callback, &arg);
1217 
1218 	mptable_bus_info_free(&bus_info);
1219 	mptable_unmap(&mpt);
1220 
1221 	return error;
1222 }
1223 
1224 struct mptable_ioapic_int_cbarg {
1225 	const struct mptable_bus_info *bus_info;
1226 	int	ioapic_nint;
1227 };
1228 
1229 static int
1230 mptable_ioapic_int_callback(void *xarg, const void *pos, int type)
1231 {
1232 	struct mptable_ioapic_int_cbarg *arg = xarg;
1233 	const struct mptable_ioapic *ioapic;
1234 	const struct mptable_bus *bus;
1235 	const struct INTENTRY *ent;
1236 	int gsi;
1237 
1238 	if (type != 3)
1239 		return 0;
1240 
1241 	arg->ioapic_nint++;
1242 
1243 	ent = pos;
1244 	if (ent->int_type != 0)
1245 		return 0;
1246 
1247 	TAILQ_FOREACH(bus, &arg->bus_info->mbi_list, mb_link) {
1248 		if (bus->mb_type == MPTABLE_BUS_ISA &&
1249 		    bus->mb_id == ent->src_bus_id)
1250 			break;
1251 	}
1252 	if (bus == NULL)
1253 		return 0;
1254 
1255 	TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) {
1256 		if (ioapic->mio_apic_id == ent->dst_apic_id)
1257 			break;
1258 	}
1259 	if (ioapic == NULL) {
1260 		kprintf("MPTABLE: warning ISA int dst apic id %d "
1261 			"does not exist\n", ent->dst_apic_id);
1262 		return 0;
1263 	}
1264 
1265 	if (ent->dst_apic_int >= ioapic->mio_npin) {
1266 		panic("mptable_ioapic_enumerate: invalid I/O APIC "
1267 		      "pin %d, should be < %d",
1268 		      ent->dst_apic_int, ioapic->mio_npin);
1269 	}
1270 	gsi = ioapic->mio_gsi_base + ent->dst_apic_int;
1271 
1272 	if (ent->src_bus_irq != gsi) {
1273 		if (bootverbose) {
1274 			kprintf("MPTABLE: INTSRC irq %d -> GSI %d\n",
1275 				ent->src_bus_irq, gsi);
1276 		}
1277 		ioapic_intsrc(ent->src_bus_irq, gsi,
1278 		    INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH);
1279 	}
1280 	return 0;
1281 }
1282 
1283 static void
1284 mptable_ioapic_enumerate(struct ioapic_enumerator *e)
1285 {
1286 	struct mptable_bus_info bus_info;
1287 	struct mptable_ioapic *ioapic;
1288 	struct mptable_pos mpt;
1289 	mpcth_t cth;
1290 	int error;
1291 
1292 	KKASSERT(mptable_fps_phyaddr != 0);
1293 	KKASSERT(!TAILQ_EMPTY(&mptable_ioapic_list));
1294 
1295 	TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) {
1296 		const struct mptable_ioapic *prev_ioapic;
1297 		uint32_t ver;
1298 		void *addr;
1299 
1300 		addr = ioapic_map(ioapic->mio_addr);
1301 
1302 		ver = ioapic_read(addr, IOAPIC_VER);
1303 		ioapic->mio_npin = ((ver & IOART_VER_MAXREDIR)
1304 				    >> MAXREDIRSHIFT) + 1;
1305 
1306 		prev_ioapic = TAILQ_PREV(ioapic,
1307 				mptable_ioapic_list, mio_link);
1308 		if (prev_ioapic == NULL) {
1309 			ioapic->mio_gsi_base = 0;
1310 		} else {
1311 			ioapic->mio_gsi_base =
1312 				prev_ioapic->mio_gsi_base +
1313 				prev_ioapic->mio_npin;
1314 		}
1315 		ioapic_add(addr, ioapic->mio_gsi_base, ioapic->mio_npin);
1316 
1317 		if (bootverbose) {
1318 			kprintf("MPTABLE: IOAPIC addr 0x%08x, "
1319 				"apic id %d, idx %d, gsi base %d, npin %d\n",
1320 				ioapic->mio_addr,
1321 				ioapic->mio_apic_id,
1322 				ioapic->mio_idx,
1323 				ioapic->mio_gsi_base,
1324 				ioapic->mio_npin);
1325 		}
1326 	}
1327 
1328 	if (mptable_use_default) {
1329 		if (bootverbose)
1330 			kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 (default)\n");
1331 		ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH);
1332 		return;
1333 	}
1334 
1335 	error = mptable_map(&mpt);
1336 	if (error)
1337 		panic("mptable_ioapic_probe: mptable_map failed");
1338 	KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt));
1339 
1340 	cth = mpt.mp_cth;
1341 
1342 	mptable_bus_info_alloc(cth, &bus_info);
1343 
1344 	if (TAILQ_EMPTY(&bus_info.mbi_list)) {
1345 		if (bootverbose)
1346 			kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 (no bus)\n");
1347 		ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH);
1348 	} else {
1349 		struct mptable_ioapic_int_cbarg arg;
1350 
1351 		bzero(&arg, sizeof(arg));
1352 		arg.bus_info = &bus_info;
1353 
1354 		error = mptable_iterate_entries(cth,
1355 			    mptable_ioapic_int_callback, &arg);
1356 		if (error)
1357 			panic("mptable_ioapic_int failed");
1358 
1359 		if (arg.ioapic_nint == 0) {
1360 			if (bootverbose) {
1361 				kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 "
1362 					"(no int)\n");
1363 			}
1364 			ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE,
1365 			    INTR_POLARITY_HIGH);
1366 		}
1367 	}
1368 
1369 	mptable_bus_info_free(&bus_info);
1370 
1371 	mptable_unmap(&mpt);
1372 }
1373 
1374 static struct ioapic_enumerator	mptable_ioapic_enumerator = {
1375 	.ioapic_prio = IOAPIC_ENUM_PRIO_MPTABLE,
1376 	.ioapic_probe = mptable_ioapic_probe,
1377 	.ioapic_enumerate = mptable_ioapic_enumerate
1378 };
1379 
1380 static void
1381 mptable_ioapic_enum_register(void)
1382 {
1383 	ioapic_enumerator_register(&mptable_ioapic_enumerator);
1384 }
1385 SYSINIT(mptable_ioapic, SI_BOOT2_PRESMP, SI_ORDER_ANY,
1386 	mptable_ioapic_enum_register, 0);
1387 
1388 void
1389 mptable_pci_int_dump(void)
1390 {
1391 	const struct mptable_pci_int *pci_int;
1392 
1393 	if (!bootverbose)
1394 		return;
1395 
1396 	TAILQ_FOREACH(pci_int, &mptable_pci_int_list, mpci_link) {
1397 		kprintf("MPTABLE: %d:%d INT%c -> IOAPIC %d.%d\n",
1398 			pci_int->mpci_bus,
1399 			pci_int->mpci_dev,
1400 			pci_int->mpci_pin + 'A',
1401 			pci_int->mpci_ioapic_idx,
1402 			pci_int->mpci_ioapic_pin);
1403 	}
1404 }
1405 
1406 int
1407 mptable_pci_int_route(int bus, int dev, int pin, int intline)
1408 {
1409 	const struct mptable_pci_int *pci_int;
1410 	int irq = -1;
1411 
1412 	KKASSERT(pin >= 1);
1413 	--pin;	/* zero based */
1414 
1415 	TAILQ_FOREACH(pci_int, &mptable_pci_int_list, mpci_link) {
1416 		if (pci_int->mpci_bus == bus &&
1417 		    pci_int->mpci_dev == dev &&
1418 		    pci_int->mpci_pin == pin)
1419 			break;
1420 	}
1421 	if (pci_int != NULL) {
1422 		int gsi;
1423 
1424 		gsi = ioapic_gsi(pci_int->mpci_ioapic_idx,
1425 			pci_int->mpci_ioapic_pin);
1426 		if (gsi >= 0) {
1427 			irq = ioapic_find_legacy_by_gsi(gsi,
1428 				INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW);
1429 		}
1430 	}
1431 
1432 	if (irq < 0) {
1433 		if (bootverbose) {
1434 			kprintf("MPTABLE: fixed interrupt routing "
1435 				"for %d:%d INT%c\n", bus, dev, pin + 'A');
1436 		}
1437 
1438 		irq = ioapic_find_legacy_by_irq(intline,
1439 			INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW);
1440 	}
1441 
1442 	if (irq >= 0 && bootverbose) {
1443 		kprintf("MPTABLE: %d:%d INT%c routed to irq %d\n",
1444 			bus, dev, pin + 'A', irq);
1445 	}
1446 	return irq;
1447 }
1448