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