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