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