xref: /freebsd/sys/x86/x86/mptable.c (revision aa0a1e58)
1 /*-
2  * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
3  * Copyright (c) 1996, by Steve Passe
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. The name of the developer may NOT be used to endorse or promote products
12  *    derived from this software without specific prior written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include "opt_mptable_force_htt.h"
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/bus.h>
34 #include <sys/kernel.h>
35 #include <sys/malloc.h>
36 
37 #include <vm/vm.h>
38 #include <vm/vm_param.h>
39 #include <vm/pmap.h>
40 
41 #include <x86/apicreg.h>
42 #include <x86/mptable.h>
43 #include <machine/frame.h>
44 #include <machine/intr_machdep.h>
45 #include <machine/apicvar.h>
46 #include <machine/md_var.h>
47 #include <machine/specialreg.h>
48 
49 #include <dev/pci/pcivar.h>
50 
51 /* string defined by the Intel MP Spec as identifying the MP table */
52 #define	MP_SIG			0x5f504d5f	/* _MP_ */
53 
54 #ifdef __amd64__
55 #define	MAX_LAPIC_ID		63	/* Max local APIC ID for HTT fixup */
56 #else
57 #define	MAX_LAPIC_ID		31	/* Max local APIC ID for HTT fixup */
58 #endif
59 
60 #ifdef PC98
61 #define BIOS_BASE		(0xe8000)
62 #define BIOS_SIZE		(0x18000)
63 #else
64 #define BIOS_BASE		(0xf0000)
65 #define BIOS_SIZE		(0x10000)
66 #endif
67 #define BIOS_COUNT		(BIOS_SIZE/4)
68 
69 typedef	void mptable_entry_handler(u_char *entry, void *arg);
70 
71 static basetable_entry basetable_entry_types[] =
72 {
73 	{0, 20, "Processor"},
74 	{1, 8, "Bus"},
75 	{2, 8, "I/O APIC"},
76 	{3, 8, "I/O INT"},
77 	{4, 8, "Local INT"}
78 };
79 
80 typedef struct BUSDATA {
81 	u_char  bus_id;
82 	enum busTypes bus_type;
83 }       bus_datum;
84 
85 typedef struct INTDATA {
86 	u_char  int_type;
87 	u_short int_flags;
88 	u_char  src_bus_id;
89 	u_char  src_bus_irq;
90 	u_char  dst_apic_id;
91 	u_char  dst_apic_int;
92 	u_char	int_vector;
93 }       io_int, local_int;
94 
95 typedef struct BUSTYPENAME {
96 	u_char  type;
97 	char    name[7];
98 }       bus_type_name;
99 
100 /* From MP spec v1.4, table 4-8. */
101 static bus_type_name bus_type_table[] =
102 {
103 	{UNKNOWN_BUSTYPE, "CBUS  "},
104 	{UNKNOWN_BUSTYPE, "CBUSII"},
105 	{EISA, "EISA  "},
106 	{UNKNOWN_BUSTYPE, "FUTURE"},
107 	{UNKNOWN_BUSTYPE, "INTERN"},
108 	{ISA, "ISA   "},
109 	{UNKNOWN_BUSTYPE, "MBI   "},
110 	{UNKNOWN_BUSTYPE, "MBII  "},
111 	{MCA, "MCA   "},
112 	{UNKNOWN_BUSTYPE, "MPI   "},
113 	{UNKNOWN_BUSTYPE, "MPSA  "},
114 	{UNKNOWN_BUSTYPE, "NUBUS "},
115 	{PCI, "PCI   "},
116 	{UNKNOWN_BUSTYPE, "PCMCIA"},
117 	{UNKNOWN_BUSTYPE, "TC    "},
118 	{UNKNOWN_BUSTYPE, "VL    "},
119 	{UNKNOWN_BUSTYPE, "VME   "},
120 	{UNKNOWN_BUSTYPE, "XPRESS"}
121 };
122 
123 /* From MP spec v1.4, table 5-1. */
124 static int default_data[7][5] =
125 {
126 /*   nbus, id0, type0, id1, type1 */
127 	{1, 0, ISA, 255, NOBUS},
128 	{1, 0, EISA, 255, NOBUS},
129 	{1, 0, EISA, 255, NOBUS},
130 	{1, 0, MCA, 255, NOBUS},
131 	{2, 0, ISA, 1, PCI},
132 	{2, 0, EISA, 1, PCI},
133 	{2, 0, MCA, 1, PCI}
134 };
135 
136 struct pci_probe_table_args {
137 	u_char bus;
138 	u_char found;
139 };
140 
141 struct pci_route_interrupt_args {
142 	u_char bus;		/* Source bus. */
143 	u_char irq;		/* Source slot:pin. */
144 	int vector;		/* Return value. */
145 };
146 
147 static mpfps_t mpfps;
148 static mpcth_t mpct;
149 static void *ioapics[MAX_APIC_ID + 1];
150 static bus_datum *busses;
151 static int mptable_nioapics, mptable_nbusses, mptable_maxbusid;
152 static int pci0 = -1;
153 
154 static MALLOC_DEFINE(M_MPTABLE, "mptable", "MP Table Items");
155 
156 static enum intr_polarity conforming_polarity(u_char src_bus,
157 	    u_char src_bus_irq);
158 static enum intr_trigger conforming_trigger(u_char src_bus, u_char src_bus_irq);
159 static enum intr_polarity intentry_polarity(int_entry_ptr intr);
160 static enum intr_trigger intentry_trigger(int_entry_ptr intr);
161 static int	lookup_bus_type(char *name);
162 static void	mptable_count_items(void);
163 static void	mptable_count_items_handler(u_char *entry, void *arg);
164 #ifdef MPTABLE_FORCE_HTT
165 static void	mptable_hyperthread_fixup(u_int id_mask);
166 #endif
167 static void	mptable_parse_apics_and_busses(void);
168 static void	mptable_parse_apics_and_busses_handler(u_char *entry,
169     void *arg);
170 static void	mptable_parse_default_config_ints(void);
171 static void	mptable_parse_ints(void);
172 static void	mptable_parse_ints_handler(u_char *entry, void *arg);
173 static void	mptable_parse_io_int(int_entry_ptr intr);
174 static void	mptable_parse_local_int(int_entry_ptr intr);
175 static void	mptable_pci_probe_table_handler(u_char *entry, void *arg);
176 static void	mptable_pci_route_interrupt_handler(u_char *entry, void *arg);
177 static void	mptable_pci_setup(void);
178 static int	mptable_probe(void);
179 static int	mptable_probe_cpus(void);
180 static void	mptable_probe_cpus_handler(u_char *entry, void *arg __unused);
181 static void	mptable_register(void *dummy);
182 static int	mptable_setup_local(void);
183 static int	mptable_setup_io(void);
184 static void	mptable_walk_table(mptable_entry_handler *handler, void *arg);
185 static int	search_for_sig(u_int32_t target, int count);
186 
187 static struct apic_enumerator mptable_enumerator = {
188 	"MPTable",
189 	mptable_probe,
190 	mptable_probe_cpus,
191 	mptable_setup_local,
192 	mptable_setup_io
193 };
194 
195 /*
196  * look for the MP spec signature
197  */
198 
199 static int
200 search_for_sig(u_int32_t target, int count)
201 {
202 	int     x;
203 	u_int32_t *addr = (u_int32_t *) (KERNBASE + target);
204 
205 	for (x = 0; x < count; x += 4)
206 		if (addr[x] == MP_SIG)
207 			/* make array index a byte index */
208 			return (target + (x * sizeof(u_int32_t)));
209 	return (-1);
210 }
211 
212 static int
213 lookup_bus_type(char *name)
214 {
215 	int     x;
216 
217 	for (x = 0; x < MAX_BUSTYPE; ++x)
218 		if (strncmp(bus_type_table[x].name, name, 6) == 0)
219 			return (bus_type_table[x].type);
220 
221 	return (UNKNOWN_BUSTYPE);
222 }
223 
224 /*
225  * Look for an Intel MP spec table (ie, SMP capable hardware).
226  */
227 static int
228 mptable_probe(void)
229 {
230 	int     x;
231 	u_long  segment;
232 	u_int32_t target;
233 
234 	/* see if EBDA exists */
235 	if ((segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) != 0) {
236 		/* search first 1K of EBDA */
237 		target = (u_int32_t) (segment << 4);
238 		if ((x = search_for_sig(target, 1024 / 4)) >= 0)
239 			goto found;
240 	} else {
241 		/* last 1K of base memory, effective 'top of base' passed in */
242 		target = (u_int32_t) ((basemem * 1024) - 0x400);
243 		if ((x = search_for_sig(target, 1024 / 4)) >= 0)
244 			goto found;
245 	}
246 
247 	/* search the BIOS */
248 	target = (u_int32_t) BIOS_BASE;
249 	if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
250 		goto found;
251 
252 	/* nothing found */
253 	return (ENXIO);
254 
255 found:
256 	mpfps = (mpfps_t)(KERNBASE + x);
257 
258 	/* Map in the configuration table if it exists. */
259 	if (mpfps->config_type != 0) {
260 		if (bootverbose)
261 			printf(
262 		"MP Table version 1.%d found using Default Configuration %d\n",
263 			    mpfps->spec_rev, mpfps->config_type);
264 		if (mpfps->config_type != 5 && mpfps->config_type != 6) {
265 			printf(
266 			"MP Table Default Configuration %d is unsupported\n",
267 			    mpfps->config_type);
268 			return (ENXIO);
269 		}
270 		mpct = NULL;
271 	} else {
272 		if ((uintptr_t)mpfps->pap >= 1024 * 1024) {
273 			printf("%s: Unable to map MP Configuration Table\n",
274 			    __func__);
275 			return (ENXIO);
276 		}
277 		mpct = (mpcth_t)(KERNBASE + (uintptr_t)mpfps->pap);
278 		if (mpct->base_table_length + (uintptr_t)mpfps->pap >=
279 		    1024 * 1024) {
280 			printf("%s: Unable to map end of MP Config Table\n",
281 			    __func__);
282 			return (ENXIO);
283 		}
284 		if (mpct->signature[0] != 'P' || mpct->signature[1] != 'C' ||
285 		    mpct->signature[2] != 'M' || mpct->signature[3] != 'P') {
286 			printf("%s: MP Config Table has bad signature: %c%c%c%c\n",
287 			    __func__, mpct->signature[0], mpct->signature[1],
288 			    mpct->signature[2], mpct->signature[3]);
289 			return (ENXIO);
290 		}
291 		if (bootverbose)
292 			printf(
293 			"MP Configuration Table version 1.%d found at %p\n",
294 			    mpct->spec_rev, mpct);
295 	}
296 
297 	return (-100);
298 }
299 
300 /*
301  * Run through the MP table enumerating CPUs.
302  */
303 static int
304 mptable_probe_cpus(void)
305 {
306 	u_int cpu_mask;
307 
308 	/* Is this a pre-defined config? */
309 	if (mpfps->config_type != 0) {
310 		lapic_create(0, 1);
311 		lapic_create(1, 0);
312 	} else {
313 		cpu_mask = 0;
314 		mptable_walk_table(mptable_probe_cpus_handler, &cpu_mask);
315 #ifdef MPTABLE_FORCE_HTT
316 		mptable_hyperthread_fixup(cpu_mask);
317 #endif
318 	}
319 	return (0);
320 }
321 
322 /*
323  * Initialize the local APIC on the BSP.
324  */
325 static int
326 mptable_setup_local(void)
327 {
328 	vm_paddr_t addr;
329 
330 	/* Is this a pre-defined config? */
331 	printf("MPTable: <");
332 	if (mpfps->config_type != 0) {
333 		addr = DEFAULT_APIC_BASE;
334 		printf("Default Configuration %d", mpfps->config_type);
335 	} else {
336 		addr = mpct->apic_address;
337 		printf("%.*s %.*s", (int)sizeof(mpct->oem_id), mpct->oem_id,
338 		    (int)sizeof(mpct->product_id), mpct->product_id);
339 	}
340 	printf(">\n");
341 	lapic_init(addr);
342 	return (0);
343 }
344 
345 /*
346  * Run through the MP table enumerating I/O APICs.
347  */
348 static int
349 mptable_setup_io(void)
350 {
351 	int i;
352 	u_char byte;
353 
354 	/* First, we count individual items and allocate arrays. */
355 	mptable_count_items();
356 	busses = malloc((mptable_maxbusid + 1) * sizeof(bus_datum), M_MPTABLE,
357 	    M_WAITOK);
358 	for (i = 0; i <= mptable_maxbusid; i++)
359 		busses[i].bus_type = NOBUS;
360 
361 	/* Second, we run through adding I/O APIC's and busses. */
362 	mptable_parse_apics_and_busses();
363 
364 	/* Third, we run through the table tweaking interrupt sources. */
365 	mptable_parse_ints();
366 
367 	/* Fourth, we register all the I/O APIC's. */
368 	for (i = 0; i <= MAX_APIC_ID; i++)
369 		if (ioapics[i] != NULL)
370 			ioapic_register(ioapics[i]);
371 
372 	/* Fifth, we setup data structures to handle PCI interrupt routing. */
373 	mptable_pci_setup();
374 
375 	/* Finally, we throw the switch to enable the I/O APIC's. */
376 	if (mpfps->mpfb2 & MPFB2_IMCR_PRESENT) {
377 		outb(0x22, 0x70);	/* select IMCR */
378 		byte = inb(0x23);	/* current contents */
379 		byte |= 0x01;		/* mask external INTR */
380 		outb(0x23, byte);	/* disconnect 8259s/NMI */
381 	}
382 
383 	return (0);
384 }
385 
386 static void
387 mptable_register(void *dummy __unused)
388 {
389 
390 	apic_register_enumerator(&mptable_enumerator);
391 }
392 SYSINIT(mptable_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST, mptable_register,
393     NULL);
394 
395 /*
396  * Call the handler routine for each entry in the MP config table.
397  */
398 static void
399 mptable_walk_table(mptable_entry_handler *handler, void *arg)
400 {
401 	u_int i;
402 	u_char *entry;
403 
404 	entry = (u_char *)(mpct + 1);
405 	for (i = 0; i < mpct->entry_count; i++) {
406 		switch (*entry) {
407 		case MPCT_ENTRY_PROCESSOR:
408 		case MPCT_ENTRY_IOAPIC:
409 		case MPCT_ENTRY_BUS:
410 		case MPCT_ENTRY_INT:
411 		case MPCT_ENTRY_LOCAL_INT:
412 			break;
413 		default:
414 			panic("%s: Unknown MP Config Entry %d\n", __func__,
415 			    (int)*entry);
416 		}
417 		handler(entry, arg);
418 		entry += basetable_entry_types[*entry].length;
419 	}
420 }
421 
422 static void
423 mptable_probe_cpus_handler(u_char *entry, void *arg)
424 {
425 	proc_entry_ptr proc;
426 	u_int *cpu_mask;
427 
428 	switch (*entry) {
429 	case MPCT_ENTRY_PROCESSOR:
430 		proc = (proc_entry_ptr)entry;
431 		if (proc->cpu_flags & PROCENTRY_FLAG_EN) {
432 			lapic_create(proc->apic_id, proc->cpu_flags &
433 			    PROCENTRY_FLAG_BP);
434 			if (proc->apic_id < MAX_LAPIC_ID) {
435 				cpu_mask = (u_int *)arg;
436 				*cpu_mask |= (1ul << proc->apic_id);
437 			}
438 		}
439 		break;
440 	}
441 }
442 
443 static void
444 mptable_count_items_handler(u_char *entry, void *arg __unused)
445 {
446 	io_apic_entry_ptr apic;
447 	bus_entry_ptr bus;
448 
449 	switch (*entry) {
450 	case MPCT_ENTRY_BUS:
451 		bus = (bus_entry_ptr)entry;
452 		mptable_nbusses++;
453 		if (bus->bus_id > mptable_maxbusid)
454 			mptable_maxbusid = bus->bus_id;
455 		break;
456 	case MPCT_ENTRY_IOAPIC:
457 		apic = (io_apic_entry_ptr)entry;
458 		if (apic->apic_flags & IOAPICENTRY_FLAG_EN)
459 			mptable_nioapics++;
460 		break;
461 	}
462 }
463 
464 /*
465  * Count items in the table.
466  */
467 static void
468 mptable_count_items(void)
469 {
470 
471 	/* Is this a pre-defined config? */
472 	if (mpfps->config_type != 0) {
473 		mptable_nioapics = 1;
474 		switch (mpfps->config_type) {
475 		case 1:
476 		case 2:
477 		case 3:
478 		case 4:
479 			mptable_nbusses = 1;
480 			break;
481 		case 5:
482 		case 6:
483 		case 7:
484 			mptable_nbusses = 2;
485 			break;
486 		default:
487 			panic("Unknown pre-defined MP Table config type %d",
488 			    mpfps->config_type);
489 		}
490 		mptable_maxbusid = mptable_nbusses - 1;
491 	} else
492 		mptable_walk_table(mptable_count_items_handler, NULL);
493 }
494 
495 /*
496  * Add a bus or I/O APIC from an entry in the table.
497  */
498 static void
499 mptable_parse_apics_and_busses_handler(u_char *entry, void *arg __unused)
500 {
501 	io_apic_entry_ptr apic;
502 	bus_entry_ptr bus;
503 	enum busTypes bus_type;
504 	int i;
505 
506 
507 	switch (*entry) {
508 	case MPCT_ENTRY_BUS:
509 		bus = (bus_entry_ptr)entry;
510 		bus_type = lookup_bus_type(bus->bus_type);
511 		if (bus_type == UNKNOWN_BUSTYPE) {
512 			printf("MPTable: Unknown bus %d type \"", bus->bus_id);
513 			for (i = 0; i < 6; i++)
514 				printf("%c", bus->bus_type[i]);
515 			printf("\"\n");
516 		}
517 		busses[bus->bus_id].bus_id = bus->bus_id;
518 		busses[bus->bus_id].bus_type = bus_type;
519 		break;
520 	case MPCT_ENTRY_IOAPIC:
521 		apic = (io_apic_entry_ptr)entry;
522 		if (!(apic->apic_flags & IOAPICENTRY_FLAG_EN))
523 			break;
524 		if (apic->apic_id > MAX_APIC_ID)
525 			panic("%s: I/O APIC ID %d too high", __func__,
526 			    apic->apic_id);
527 		if (ioapics[apic->apic_id] != NULL)
528 			panic("%s: Double APIC ID %d", __func__,
529 			    apic->apic_id);
530 		ioapics[apic->apic_id] = ioapic_create(apic->apic_address,
531 		    apic->apic_id, -1);
532 		break;
533 	default:
534 		break;
535 	}
536 }
537 
538 /*
539  * Enumerate I/O APIC's and busses.
540  */
541 static void
542 mptable_parse_apics_and_busses(void)
543 {
544 
545 	/* Is this a pre-defined config? */
546 	if (mpfps->config_type != 0) {
547 		ioapics[2] = ioapic_create(DEFAULT_IO_APIC_BASE, 2, 0);
548 		busses[0].bus_id = 0;
549 		busses[0].bus_type = default_data[mpfps->config_type - 1][2];
550 		if (mptable_nbusses > 1) {
551 			busses[1].bus_id = 1;
552 			busses[1].bus_type =
553 			    default_data[mpfps->config_type - 1][4];
554 		}
555 	} else
556 		mptable_walk_table(mptable_parse_apics_and_busses_handler,
557 		    NULL);
558 }
559 
560 /*
561  * Determine conforming polarity for a given bus type.
562  */
563 static enum intr_polarity
564 conforming_polarity(u_char src_bus, u_char src_bus_irq)
565 {
566 
567 	KASSERT(src_bus <= mptable_maxbusid, ("bus id %d too large", src_bus));
568 	switch (busses[src_bus].bus_type) {
569 	case ISA:
570 	case EISA:
571 		return (INTR_POLARITY_HIGH);
572 	case PCI:
573 		return (INTR_POLARITY_LOW);
574 	default:
575 		panic("%s: unknown bus type %d", __func__,
576 		    busses[src_bus].bus_type);
577 	}
578 }
579 
580 /*
581  * Determine conforming trigger for a given bus type.
582  */
583 static enum intr_trigger
584 conforming_trigger(u_char src_bus, u_char src_bus_irq)
585 {
586 
587 	KASSERT(src_bus <= mptable_maxbusid, ("bus id %d too large", src_bus));
588 	switch (busses[src_bus].bus_type) {
589 	case ISA:
590 #ifndef PC98
591 		if (elcr_found)
592 			return (elcr_read_trigger(src_bus_irq));
593 		else
594 #endif
595 			return (INTR_TRIGGER_EDGE);
596 	case PCI:
597 		return (INTR_TRIGGER_LEVEL);
598 #ifndef PC98
599 	case EISA:
600 		KASSERT(src_bus_irq < 16, ("Invalid EISA IRQ %d", src_bus_irq));
601 		KASSERT(elcr_found, ("Missing ELCR"));
602 		return (elcr_read_trigger(src_bus_irq));
603 #endif
604 	default:
605 		panic("%s: unknown bus type %d", __func__,
606 		    busses[src_bus].bus_type);
607 	}
608 }
609 
610 static enum intr_polarity
611 intentry_polarity(int_entry_ptr intr)
612 {
613 
614 	switch (intr->int_flags & INTENTRY_FLAGS_POLARITY) {
615 	case INTENTRY_FLAGS_POLARITY_CONFORM:
616 		return (conforming_polarity(intr->src_bus_id,
617 			    intr->src_bus_irq));
618 	case INTENTRY_FLAGS_POLARITY_ACTIVEHI:
619 		return (INTR_POLARITY_HIGH);
620 	case INTENTRY_FLAGS_POLARITY_ACTIVELO:
621 		return (INTR_POLARITY_LOW);
622 	default:
623 		panic("Bogus interrupt flags");
624 	}
625 }
626 
627 static enum intr_trigger
628 intentry_trigger(int_entry_ptr intr)
629 {
630 
631 	switch (intr->int_flags & INTENTRY_FLAGS_TRIGGER) {
632 	case INTENTRY_FLAGS_TRIGGER_CONFORM:
633 		return (conforming_trigger(intr->src_bus_id,
634 			    intr->src_bus_irq));
635 	case INTENTRY_FLAGS_TRIGGER_EDGE:
636 		return (INTR_TRIGGER_EDGE);
637 	case INTENTRY_FLAGS_TRIGGER_LEVEL:
638 		return (INTR_TRIGGER_LEVEL);
639 	default:
640 		panic("Bogus interrupt flags");
641 	}
642 }
643 
644 /*
645  * Parse an interrupt entry for an I/O interrupt routed to a pin on an I/O APIC.
646  */
647 static void
648 mptable_parse_io_int(int_entry_ptr intr)
649 {
650 	void *ioapic;
651 	u_int pin, apic_id;
652 
653 	apic_id = intr->dst_apic_id;
654 	if (intr->dst_apic_id == 0xff) {
655 		/*
656 		 * An APIC ID of 0xff means that the interrupt is connected
657 		 * to the specified pin on all I/O APICs in the system.  If
658 		 * there is only one I/O APIC, then use that APIC to route
659 		 * the interrupts.  If there is more than one I/O APIC, then
660 		 * punt.
661 		 */
662 		if (mptable_nioapics == 1) {
663 			apic_id = 0;
664 			while (ioapics[apic_id] == NULL)
665 				apic_id++;
666 		} else {
667 			printf(
668 			"MPTable: Ignoring global interrupt entry for pin %d\n",
669 			    intr->dst_apic_int);
670 			return;
671 		}
672 	}
673 	if (apic_id > MAX_APIC_ID) {
674 		printf("MPTable: Ignoring interrupt entry for ioapic%d\n",
675 		    intr->dst_apic_id);
676 		return;
677 	}
678 	ioapic = ioapics[apic_id];
679 	if (ioapic == NULL) {
680 		printf(
681 	"MPTable: Ignoring interrupt entry for missing ioapic%d\n",
682 		    apic_id);
683 		return;
684 	}
685 	pin = intr->dst_apic_int;
686 	switch (intr->int_type) {
687 	case INTENTRY_TYPE_INT:
688 		switch (busses[intr->src_bus_id].bus_type) {
689 		case NOBUS:
690 			panic("interrupt from missing bus");
691 		case ISA:
692 		case EISA:
693 			if (busses[intr->src_bus_id].bus_type == ISA)
694 				ioapic_set_bus(ioapic, pin, APIC_BUS_ISA);
695 			else
696 				ioapic_set_bus(ioapic, pin, APIC_BUS_EISA);
697 			if (intr->src_bus_irq == pin)
698 				break;
699 			ioapic_remap_vector(ioapic, pin, intr->src_bus_irq);
700 			if (ioapic_get_vector(ioapic, intr->src_bus_irq) ==
701 			    intr->src_bus_irq)
702 				ioapic_disable_pin(ioapic, intr->src_bus_irq);
703 			break;
704 		case PCI:
705 			ioapic_set_bus(ioapic, pin, APIC_BUS_PCI);
706 			break;
707 		default:
708 			ioapic_set_bus(ioapic, pin, APIC_BUS_UNKNOWN);
709 			break;
710 		}
711 		break;
712 	case INTENTRY_TYPE_NMI:
713 		ioapic_set_nmi(ioapic, pin);
714 		break;
715 	case INTENTRY_TYPE_SMI:
716 		ioapic_set_smi(ioapic, pin);
717 		break;
718 	case INTENTRY_TYPE_EXTINT:
719 		ioapic_set_extint(ioapic, pin);
720 		break;
721 	default:
722 		panic("%s: invalid interrupt entry type %d\n", __func__,
723 		    intr->int_type);
724 	}
725 	if (intr->int_type == INTENTRY_TYPE_INT ||
726 	    (intr->int_flags & INTENTRY_FLAGS_TRIGGER) !=
727 	    INTENTRY_FLAGS_TRIGGER_CONFORM)
728 		ioapic_set_triggermode(ioapic, pin, intentry_trigger(intr));
729 	if (intr->int_type == INTENTRY_TYPE_INT ||
730 	    (intr->int_flags & INTENTRY_FLAGS_POLARITY) !=
731 	    INTENTRY_FLAGS_POLARITY_CONFORM)
732 		ioapic_set_polarity(ioapic, pin, intentry_polarity(intr));
733 }
734 
735 /*
736  * Parse an interrupt entry for a local APIC LVT pin.
737  */
738 static void
739 mptable_parse_local_int(int_entry_ptr intr)
740 {
741 	u_int apic_id, pin;
742 
743 	if (intr->dst_apic_id == 0xff)
744 		apic_id = APIC_ID_ALL;
745 	else
746 		apic_id = intr->dst_apic_id;
747 	if (intr->dst_apic_int == 0)
748 		pin = LVT_LINT0;
749 	else
750 		pin = LVT_LINT1;
751 	switch (intr->int_type) {
752 	case INTENTRY_TYPE_INT:
753 #if 1
754 		printf(
755 	"MPTable: Ignoring vectored local interrupt for LINTIN%d vector %d\n",
756 		    intr->dst_apic_int, intr->src_bus_irq);
757 		return;
758 #else
759 		lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_FIXED);
760 		break;
761 #endif
762 	case INTENTRY_TYPE_NMI:
763 		lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
764 		break;
765 	case INTENTRY_TYPE_SMI:
766 		lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_SMI);
767 		break;
768 	case INTENTRY_TYPE_EXTINT:
769 		lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_EXTINT);
770 		break;
771 	default:
772 		panic("%s: invalid interrupt entry type %d\n", __func__,
773 		    intr->int_type);
774 	}
775 	if ((intr->int_flags & INTENTRY_FLAGS_TRIGGER) !=
776 	    INTENTRY_FLAGS_TRIGGER_CONFORM)
777 		lapic_set_lvt_triggermode(apic_id, pin,
778 		    intentry_trigger(intr));
779 	if ((intr->int_flags & INTENTRY_FLAGS_POLARITY) !=
780 	    INTENTRY_FLAGS_POLARITY_CONFORM)
781 		lapic_set_lvt_polarity(apic_id, pin, intentry_polarity(intr));
782 }
783 
784 /*
785  * Parse interrupt entries.
786  */
787 static void
788 mptable_parse_ints_handler(u_char *entry, void *arg __unused)
789 {
790 	int_entry_ptr intr;
791 
792 	intr = (int_entry_ptr)entry;
793 	switch (*entry) {
794 	case MPCT_ENTRY_INT:
795 		mptable_parse_io_int(intr);
796 		break;
797 	case MPCT_ENTRY_LOCAL_INT:
798 		mptable_parse_local_int(intr);
799 		break;
800 	}
801 }
802 
803 /*
804  * Configure interrupt pins for a default configuration.  For details see
805  * Table 5-2 in Section 5 of the MP Table specification.
806  */
807 static void
808 mptable_parse_default_config_ints(void)
809 {
810 	struct INTENTRY entry;
811 	int pin;
812 
813 	/*
814 	 * All default configs route IRQs from bus 0 to the first 16 pins
815 	 * of the first I/O APIC with an APIC ID of 2.
816 	 */
817 	entry.type = MPCT_ENTRY_INT;
818 	entry.int_flags = INTENTRY_FLAGS_POLARITY_CONFORM |
819 	    INTENTRY_FLAGS_TRIGGER_CONFORM;
820 	entry.src_bus_id = 0;
821 	entry.dst_apic_id = 2;
822 
823 	/* Run through all 16 pins. */
824 	for (pin = 0; pin < 16; pin++) {
825 		entry.dst_apic_int = pin;
826 		switch (pin) {
827 		case 0:
828 			/* Pin 0 is an ExtINT pin. */
829 			entry.int_type = INTENTRY_TYPE_EXTINT;
830 			break;
831 		case 2:
832 			/* IRQ 0 is routed to pin 2. */
833 			entry.int_type = INTENTRY_TYPE_INT;
834 			entry.src_bus_irq = 0;
835 			break;
836 		default:
837 			/* All other pins are identity mapped. */
838 			entry.int_type = INTENTRY_TYPE_INT;
839 			entry.src_bus_irq = pin;
840 			break;
841 		}
842 		mptable_parse_io_int(&entry);
843 	}
844 
845 	/* Certain configs disable certain pins. */
846 	if (mpfps->config_type == 7)
847 		ioapic_disable_pin(ioapics[2], 0);
848 	if (mpfps->config_type == 2) {
849 		ioapic_disable_pin(ioapics[2], 2);
850 		ioapic_disable_pin(ioapics[2], 13);
851 	}
852 }
853 
854 /*
855  * Configure the interrupt pins
856  */
857 static void
858 mptable_parse_ints(void)
859 {
860 
861 	/* Is this a pre-defined config? */
862 	if (mpfps->config_type != 0) {
863 		/* Configure LINT pins. */
864 		lapic_set_lvt_mode(APIC_ID_ALL, LVT_LINT0, APIC_LVT_DM_EXTINT);
865 		lapic_set_lvt_mode(APIC_ID_ALL, LVT_LINT1, APIC_LVT_DM_NMI);
866 
867 		/* Configure I/O APIC pins. */
868 		mptable_parse_default_config_ints();
869 	} else
870 		mptable_walk_table(mptable_parse_ints_handler, NULL);
871 }
872 
873 #ifdef MPTABLE_FORCE_HTT
874 /*
875  * Perform a hyperthreading "fix-up" to enumerate any logical CPU's
876  * that aren't already listed in the table.
877  *
878  * XXX: We assume that all of the physical CPUs in the
879  * system have the same number of logical CPUs.
880  *
881  * XXX: We assume that APIC ID's are allocated such that
882  * the APIC ID's for a physical processor are aligned
883  * with the number of logical CPU's in the processor.
884  */
885 static void
886 mptable_hyperthread_fixup(u_int id_mask)
887 {
888 	u_int i, id, logical_cpus;
889 
890 	/* Nothing to do if there is no HTT support. */
891 	if ((cpu_feature & CPUID_HTT) == 0)
892 		return;
893 	logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
894 	if (logical_cpus <= 1)
895 		return;
896 
897 	/*
898 	 * For each APIC ID of a CPU that is set in the mask,
899 	 * scan the other candidate APIC ID's for this
900 	 * physical processor.  If any of those ID's are
901 	 * already in the table, then kill the fixup.
902 	 */
903 	for (id = 0; id <= MAX_LAPIC_ID; id++) {
904 		if ((id_mask & 1 << id) == 0)
905 			continue;
906 		/* First, make sure we are on a logical_cpus boundary. */
907 		if (id % logical_cpus != 0)
908 			return;
909 		for (i = id + 1; i < id + logical_cpus; i++)
910 			if ((id_mask & 1 << i) != 0)
911 				return;
912 	}
913 
914 	/*
915 	 * Ok, the ID's checked out, so perform the fixup by
916 	 * adding the logical CPUs.
917 	 */
918 	while ((id = ffs(id_mask)) != 0) {
919 		id--;
920 		for (i = id + 1; i < id + logical_cpus; i++) {
921 			if (bootverbose)
922 				printf(
923 			"MPTable: Adding logical CPU %d from main CPU %d\n",
924 				    i, id);
925 			lapic_create(i, 0);
926 		}
927 		id_mask &= ~(1 << id);
928 	}
929 }
930 #endif /* MPTABLE_FORCE_HTT */
931 
932 /*
933  * Support code for routing PCI interrupts using the MP Table.
934  */
935 static void
936 mptable_pci_setup(void)
937 {
938 	int i;
939 
940 	/*
941 	 * Find the first pci bus and call it 0.  Panic if pci0 is not
942 	 * bus zero and there are multiple PCI busses.
943 	 */
944 	for (i = 0; i <= mptable_maxbusid; i++)
945 		if (busses[i].bus_type == PCI) {
946 			if (pci0 == -1)
947 				pci0 = i;
948 			else if (pci0 != 0)
949 				panic(
950 		"MPTable contains multiple PCI busses but no PCI bus 0");
951 		}
952 }
953 
954 static void
955 mptable_pci_probe_table_handler(u_char *entry, void *arg)
956 {
957 	struct pci_probe_table_args *args;
958 	int_entry_ptr intr;
959 
960 	if (*entry != MPCT_ENTRY_INT)
961 		return;
962 	intr = (int_entry_ptr)entry;
963 	args = (struct pci_probe_table_args *)arg;
964 	KASSERT(args->bus <= mptable_maxbusid,
965 	    ("bus %d is too big", args->bus));
966 	KASSERT(busses[args->bus].bus_type == PCI, ("probing for non-PCI bus"));
967 	if (intr->src_bus_id == args->bus)
968 		args->found = 1;
969 }
970 
971 int
972 mptable_pci_probe_table(int bus)
973 {
974 	struct pci_probe_table_args args;
975 
976 	if (bus < 0)
977 		return (EINVAL);
978 	if (mpct == NULL || pci0 == -1 || pci0 + bus > mptable_maxbusid)
979 		return (ENXIO);
980 	if (busses[pci0 + bus].bus_type != PCI)
981 		return (ENXIO);
982 	args.bus = pci0 + bus;
983 	args.found = 0;
984 	mptable_walk_table(mptable_pci_probe_table_handler, &args);
985 	if (args.found == 0)
986 		return (ENXIO);
987 	return (0);
988 }
989 
990 static void
991 mptable_pci_route_interrupt_handler(u_char *entry, void *arg)
992 {
993 	struct pci_route_interrupt_args *args;
994 	int_entry_ptr intr;
995 	int vector;
996 
997 	if (*entry != MPCT_ENTRY_INT)
998 		return;
999 	intr = (int_entry_ptr)entry;
1000 	args = (struct pci_route_interrupt_args *)arg;
1001 	if (intr->src_bus_id != args->bus || intr->src_bus_irq != args->irq)
1002 		return;
1003 
1004 	/* Make sure the APIC maps to a known APIC. */
1005 	KASSERT(ioapics[intr->dst_apic_id] != NULL,
1006 	    ("No I/O APIC %d to route interrupt to", intr->dst_apic_id));
1007 
1008 	/*
1009 	 * Look up the vector for this APIC / pin combination.  If we
1010 	 * have previously matched an entry for this PCI IRQ but it
1011 	 * has the same vector as this entry, just return.  Otherwise,
1012 	 * we use the vector for this APIC / pin combination.
1013 	 */
1014 	vector = ioapic_get_vector(ioapics[intr->dst_apic_id],
1015 	    intr->dst_apic_int);
1016 	if (args->vector == vector)
1017 		return;
1018 	KASSERT(args->vector == -1,
1019 	    ("Multiple IRQs for PCI interrupt %d.%d.INT%c: %d and %d\n",
1020 	    args->bus, args->irq >> 2, 'A' + (args->irq & 0x3), args->vector,
1021 	    vector));
1022 	args->vector = vector;
1023 }
1024 
1025 int
1026 mptable_pci_route_interrupt(device_t pcib, device_t dev, int pin)
1027 {
1028 	struct pci_route_interrupt_args args;
1029 	int slot;
1030 
1031 	/* Like ACPI, pin numbers are 0-3, not 1-4. */
1032 	pin--;
1033 	KASSERT(pci0 != -1, ("do not know how to route PCI interrupts"));
1034 	args.bus = pci_get_bus(dev) + pci0;
1035 	slot = pci_get_slot(dev);
1036 
1037 	/*
1038 	 * PCI interrupt entries in the MP Table encode both the slot and
1039 	 * pin into the IRQ with the pin being the two least significant
1040 	 * bits, the slot being the next five bits, and the most significant
1041 	 * bit being reserved.
1042 	 */
1043 	args.irq = slot << 2 | pin;
1044 	args.vector = -1;
1045 	mptable_walk_table(mptable_pci_route_interrupt_handler, &args);
1046 	if (args.vector < 0) {
1047 		device_printf(pcib, "unable to route slot %d INT%c\n", slot,
1048 		    'A' + pin);
1049 		return (PCI_INVALID_IRQ);
1050 	}
1051 	if (bootverbose)
1052 		device_printf(pcib, "slot %d INT%c routed to irq %d\n", slot,
1053 		    'A' + pin, args.vector);
1054 	return (args.vector);
1055 }
1056