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: releng/5.2/sys/i386/i386/mptable.c 123133 2003-12-03 20:33:18Z 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/malloc.h>
36
37 #include <vm/vm.h>
38 #include <vm/vm_param.h>
39 #include <vm/pmap.h>
40
41 #include <machine/apicreg.h>
42 #include <machine/frame.h>
43 #include <machine/intr_machdep.h>
44 #include <machine/apicvar.h>
45 #include <machine/md_var.h>
46 #include <machine/mptable.h>
47 #include <machine/specialreg.h>
48
49 #include <dev/pci/pcivar.h>
50
51 /* EISA Edge/Level trigger control registers */
52 #define ELCR0 0x4d0 /* eisa irq 0-7 */
53 #define ELCR1 0x4d1 /* eisa irq 8-15 */
54
55 /* string defined by the Intel MP Spec as identifying the MP table */
56 #define MP_SIG 0x5f504d5f /* _MP_ */
57
58 #define NAPICID 32 /* Max number of I/O APIC's */
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[NAPICID];
150 static bus_datum *busses;
151 static int mptable_nioapics, mptable_nbusses, mptable_maxbusid;
152 static int pci0 = -1;
153
154 MALLOC_DEFINE(M_MPTABLE, "MP Table", "MP Table Items");
155
156 static u_char conforming_polarity(u_char src_bus);
157 static u_char conforming_trigger(u_char src_bus, u_char src_bus_irq);
158 static u_char intentry_polarity(int_entry_ptr intr);
159 static u_char intentry_trigger(int_entry_ptr intr);
160 static int lookup_bus_type(char *name);
161 static void mptable_count_items(void);
162 static void mptable_count_items_handler(u_char *entry, void *arg);
163 #ifdef MPTABLE_FORCE_HTT
164 static void mptable_hyperthread_fixup(u_int id_mask);
165 #endif
166 static void mptable_parse_apics_and_busses(void);
167 static void mptable_parse_apics_and_busses_handler(u_char *entry,
168 void *arg);
169 static void mptable_parse_ints(void);
170 static void mptable_parse_ints_handler(u_char *entry, void *arg);
171 static void mptable_parse_io_int(int_entry_ptr intr);
172 static void mptable_parse_local_int(int_entry_ptr intr);
173 static void mptable_pci_probe_table_handler(u_char *entry, void *arg);
174 static void mptable_pci_route_interrupt_handler(u_char *entry, void *arg);
175 static void mptable_pci_setup(void);
176 static int mptable_probe(void);
177 static int mptable_probe_cpus(void);
178 static void mptable_probe_cpus_handler(u_char *entry, void *arg __unused);
179 static void mptable_register(void *dummy);
180 static int mptable_setup_local(void);
181 static int mptable_setup_io(void);
182 static void mptable_walk_table(mptable_entry_handler *handler, void *arg);
183 static int search_for_sig(u_int32_t target, int count);
184
185 static struct apic_enumerator mptable_enumerator = {
186 "MPTable",
187 mptable_probe,
188 mptable_probe_cpus,
189 mptable_setup_local,
190 mptable_setup_io
191 };
192
193 /*
194 * look for the MP spec signature
195 */
196
197 static int
198 search_for_sig(u_int32_t target, int count)
199 {
200 int x;
201 u_int32_t *addr = (u_int32_t *) (KERNBASE + target);
202
203 for (x = 0; x < count; x += 4)
204 if (addr[x] == MP_SIG)
205 /* make array index a byte index */
206 return (target + (x * sizeof(u_int32_t)));
207 return (-1);
208 }
209
210 static int
211 lookup_bus_type(char *name)
212 {
213 int x;
214
215 for (x = 0; x < MAX_BUSTYPE; ++x)
216 if (strncmp(bus_type_table[x].name, name, 6) == 0)
217 return (bus_type_table[x].type);
218
219 return (UNKNOWN_BUSTYPE);
220 }
221
222 /*
223 * Look for an Intel MP spec table (ie, SMP capable hardware).
224 */
225 static int
226 mptable_probe(void)
227 {
228 int x;
229 u_long segment;
230 u_int32_t target;
231
232 /* see if EBDA exists */
233 if ((segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) != 0) {
234 /* search first 1K of EBDA */
235 target = (u_int32_t) (segment << 4);
236 if ((x = search_for_sig(target, 1024 / 4)) >= 0)
237 goto found;
238 } else {
239 /* last 1K of base memory, effective 'top of base' passed in */
240 target = (u_int32_t) ((basemem * 1024) - 0x400);
241 if ((x = search_for_sig(target, 1024 / 4)) >= 0)
242 goto found;
243 }
244
245 /* search the BIOS */
246 target = (u_int32_t) BIOS_BASE;
247 if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
248 goto found;
249
250 /* nothing found */
251 return (ENXIO);
252
253 found:
254 mpfps = (mpfps_t)(KERNBASE + x);
255
256 /* Map in the configuration table if it exists. */
257 if (mpfps->config_type != 0)
258 mpct = NULL;
259 else {
260 if ((uintptr_t)mpfps->pap >= 1024 * 1024) {
261 printf("%s: Unable to map MP Configuration Table\n",
262 __func__);
263 return (ENXIO);
264 }
265 mpct = (mpcth_t)(KERNBASE + (uintptr_t)mpfps->pap);
266 if (mpct->base_table_length + (uintptr_t)mpfps->pap >=
267 1024 * 1024) {
268 printf("%s: Unable to map end of MP Config Table\n",
269 __func__);
270 return (ENXIO);
271 }
272 if (mpct->signature[0] != 'P' || mpct->signature[1] != 'C' ||
273 mpct->signature[2] != 'M' || mpct->signature[3] != 'P') {
274 printf("%s: MP Config Table has bad signature: %c%c%c%c\n",
275 __func__, mpct->signature[0], mpct->signature[1],
276 mpct->signature[2], mpct->signature[3]);
277 return (ENXIO);
278 }
279 if (bootverbose)
280 printf(
281 "MP Configuration Table version 1.%d found at %p\n",
282 mpct->spec_rev, mpct);
283 }
284
285 return (-100);
286 }
287
288 /*
289 * Run through the MP table enumerating CPUs.
290 */
291 static int
292 mptable_probe_cpus(void)
293 {
294 u_int cpu_mask;
295
296 /* Is this a pre-defined config? */
297 if (mpfps->config_type != 0) {
298 lapic_create(0, 1);
299 lapic_create(1, 0);
300 } else {
301 cpu_mask = 0;
302 mptable_walk_table(mptable_probe_cpus_handler, &cpu_mask);
303 #ifdef MPTABLE_FORCE_HTT
304 mptable_hyperthread_fixup(cpu_mask);
305 #endif
306 }
307 return (0);
308 }
309
310 /*
311 * Initialize the local APIC on the BSP.
312 */
313 static int
314 mptable_setup_local(void)
315 {
316
317 /* Is this a pre-defined config? */
318 printf("MPTable: <");
319 if (mpfps->config_type != 0) {
320 lapic_init(DEFAULT_APIC_BASE);
321 printf("Preset Config %d", mpfps->config_type);
322 } else {
323 lapic_init((uintptr_t)mpct->apic_address);
324 printf("%.*s %.*s", (int)sizeof(mpct->oem_id), mpct->oem_id,
325 (int)sizeof(mpct->product_id), mpct->product_id);
326 }
327 printf(">\n");
328 return (0);
329 }
330
331 /*
332 * Run through the MP table enumerating I/O APICs.
333 */
334 static int
335 mptable_setup_io(void)
336 {
337 int i;
338 u_char byte;
339
340 /* First, we count individual items and allocate arrays. */
341 mptable_count_items();
342 busses = malloc((mptable_maxbusid + 1) * sizeof(bus_datum), M_MPTABLE,
343 M_WAITOK);
344 for (i = 0; i <= mptable_maxbusid; i++)
345 busses[i].bus_type = NOBUS;
346
347 /* Second, we run through adding I/O APIC's and busses. */
348 mptable_parse_apics_and_busses();
349
350 /* Third, we run through the table tweaking interrupt sources. */
351 mptable_parse_ints();
352
353 /* Fourth, we register all the I/O APIC's. */
354 for (i = 0; i < NAPICID; i++)
355 if (ioapics[i] != NULL)
356 ioapic_register(ioapics[i]);
357
358 /* Fifth, we setup data structures to handle PCI interrupt routing. */
359 mptable_pci_setup();
360
361 /* Finally, we throw the switch to enable the I/O APIC's. */
362 if (mpfps->mpfb2 & MPFB2_IMCR_PRESENT) {
363 outb(0x22, 0x70); /* select IMCR */
364 byte = inb(0x23); /* current contents */
365 byte |= 0x01; /* mask external INTR */
366 outb(0x23, byte); /* disconnect 8259s/NMI */
367 }
368
369 return (0);
370 }
371
372 static void
373 mptable_register(void *dummy __unused)
374 {
375
376 apic_register_enumerator(&mptable_enumerator);
377 }
378 SYSINIT(mptable_register, SI_SUB_CPU - 1, SI_ORDER_FIRST, mptable_register,
379 NULL)
380
381 /*
382 * Call the handler routine for each entry in the MP config table.
383 */
384 static void
385 mptable_walk_table(mptable_entry_handler *handler, void *arg)
386 {
387 u_int i;
388 u_char *entry;
389
390 entry = (u_char *)(mpct + 1);
391 for (i = 0; i < mpct->entry_count; i++) {
392 switch (*entry) {
393 case MPCT_ENTRY_PROCESSOR:
394 case MPCT_ENTRY_IOAPIC:
395 case MPCT_ENTRY_BUS:
396 case MPCT_ENTRY_INT:
397 case MPCT_ENTRY_LOCAL_INT:
398 break;
399 default:
400 panic("%s: Unknown MP Config Entry %d\n", __func__,
401 (int)*entry);
402 }
403 handler(entry, arg);
404 entry += basetable_entry_types[*entry].length;
405 }
406 }
407
408 static void
409 mptable_probe_cpus_handler(u_char *entry, void *arg)
410 {
411 proc_entry_ptr proc;
412 u_int *cpu_mask;
413
414 switch (*entry) {
415 case MPCT_ENTRY_PROCESSOR:
416 proc = (proc_entry_ptr)entry;
417 if (proc->cpu_flags & PROCENTRY_FLAG_EN) {
418 lapic_create(proc->apic_id, proc->cpu_flags &
419 PROCENTRY_FLAG_BP);
420 cpu_mask = (u_int *)arg;
421 *cpu_mask |= (1 << proc->apic_id);
422 }
423 break;
424 }
425 }
426
427 static void
428 mptable_count_items_handler(u_char *entry, void *arg __unused)
429 {
430 io_apic_entry_ptr apic;
431 bus_entry_ptr bus;
432
433 switch (*entry) {
434 case MPCT_ENTRY_BUS:
435 bus = (bus_entry_ptr)entry;
436 mptable_nbusses++;
437 if (bus->bus_id > mptable_maxbusid)
438 mptable_maxbusid = bus->bus_id;
439 break;
440 case MPCT_ENTRY_IOAPIC:
441 apic = (io_apic_entry_ptr)entry;
442 if (apic->apic_flags & IOAPICENTRY_FLAG_EN)
443 mptable_nioapics++;
444 break;
445 }
446 }
447
448 /*
449 * Count items in the table.
450 */
451 static void
452 mptable_count_items(void)
453 {
454
455 /* Is this a pre-defined config? */
456 if (mpfps->config_type != 0) {
457 mptable_nioapics = 1;
458 switch (mpfps->config_type) {
459 case 1:
460 case 2:
461 case 3:
462 case 4:
463 mptable_nbusses = 1;
464 break;
465 case 5:
466 case 6:
467 case 7:
468 mptable_nbusses = 2;
469 break;
470 default:
471 panic("Unknown pre-defined MP Table config type %d",
472 mpfps->config_type);
473 }
474 mptable_maxbusid = mptable_nbusses - 1;
475 } else
476 mptable_walk_table(mptable_count_items_handler, NULL);
477 }
478
479 /*
480 * Add a bus or I/O APIC from an entry in the table.
481 */
482 static void
483 mptable_parse_apics_and_busses_handler(u_char *entry, void *arg __unused)
484 {
485 io_apic_entry_ptr apic;
486 bus_entry_ptr bus;
487 enum busTypes bus_type;
488 int i;
489
490
491 switch (*entry) {
492 case MPCT_ENTRY_BUS:
493 bus = (bus_entry_ptr)entry;
494 bus_type = lookup_bus_type(bus->bus_type);
495 if (bus_type == UNKNOWN_BUSTYPE) {
496 printf("MPTable: Unknown bus %d type \"", bus->bus_id);
497 for (i = 0; i < 6; i++)
498 printf("%c", bus->bus_type[i]);
499 printf("\"\n");
500 }
501 busses[bus->bus_id].bus_id = bus->bus_id;
502 busses[bus->bus_id].bus_type = bus_type;
503 break;
504 case MPCT_ENTRY_IOAPIC:
505 apic = (io_apic_entry_ptr)entry;
506 if (!(apic->apic_flags & IOAPICENTRY_FLAG_EN))
507 break;
508 if (apic->apic_id >= NAPICID)
509 panic("%s: I/O APIC ID %d too high", __func__,
510 apic->apic_id);
511 if (ioapics[apic->apic_id] != NULL)
512 panic("%s: Double APIC ID %d", __func__,
513 apic->apic_id);
514 ioapics[apic->apic_id] = ioapic_create(
515 (uintptr_t)apic->apic_address, apic->apic_id, -1);
516 break;
517 default:
518 break;
519 }
520 }
521
522 /*
523 * Enumerate I/O APIC's and busses.
524 */
525 static void
526 mptable_parse_apics_and_busses(void)
527 {
528
529 /* Is this a pre-defined config? */
530 if (mpfps->config_type != 0) {
531 ioapics[0] = ioapic_create(DEFAULT_IO_APIC_BASE, 2, 0);
532 busses[0].bus_id = 0;
533 busses[0].bus_type = default_data[mpfps->config_type][2];
534 if (mptable_nbusses > 1) {
535 busses[1].bus_id = 1;
536 busses[1].bus_type =
537 default_data[mpfps->config_type][4];
538 }
539 } else
540 mptable_walk_table(mptable_parse_apics_and_busses_handler,
541 NULL);
542 }
543
544 /*
545 * Determine conforming polarity for a given bus type.
546 */
547 static u_char
548 conforming_polarity(u_char src_bus)
549 {
550
551 KASSERT(src_bus <= mptable_maxbusid, ("bus id %d too large", src_bus));
552 switch (busses[src_bus].bus_type) {
553 case ISA:
554 case EISA:
555 /* Active Hi */
556 return (1);
557 case PCI:
558 /* Active Lo */
559 return (0);
560 default:
561 panic("%s: unknown bus type %d", __func__,
562 busses[src_bus].bus_type);
563 }
564 }
565
566 /*
567 * Determine conforming trigger for a given bus type.
568 */
569 static u_char
570 conforming_trigger(u_char src_bus, u_char src_bus_irq)
571 {
572 static int eisa_int_control = -1;
573
574 KASSERT(src_bus <= mptable_maxbusid, ("bus id %d too large", src_bus));
575 switch (busses[src_bus].bus_type) {
576 case ISA:
577 /* Edge Triggered */
578 return (1);
579 case PCI:
580 /* Level Triggered */
581 return (0);
582 case EISA:
583 KASSERT(src_bus_irq < 16, ("Invalid EISA IRQ %d", src_bus_irq));
584 if (eisa_int_control == -1)
585 eisa_int_control = inb(ELCR1) << 8 | inb(ELCR0);
586 if (eisa_int_control & (1 << src_bus_irq))
587 /* Level Triggered */
588 return (0);
589 else
590 /* Edge Triggered */
591 return (1);
592 default:
593 panic("%s: unknown bus type %d", __func__,
594 busses[src_bus].bus_type);
595 }
596 }
597
598 static u_char
599 intentry_polarity(int_entry_ptr intr)
600 {
601
602 switch (intr->int_flags & INTENTRY_FLAGS_POLARITY) {
603 case INTENTRY_FLAGS_POLARITY_CONFORM:
604 return (conforming_polarity(intr->src_bus_id));
605 case INTENTRY_FLAGS_POLARITY_ACTIVEHI:
606 return (1);
607 case INTENTRY_FLAGS_POLARITY_ACTIVELO:
608 return (0);
609 default:
610 panic("Bogus interrupt flags");
611 }
612 }
613
614 static u_char
615 intentry_trigger(int_entry_ptr intr)
616 {
617
618 switch (intr->int_flags & INTENTRY_FLAGS_TRIGGER) {
619 case INTENTRY_FLAGS_TRIGGER_CONFORM:
620 return (conforming_trigger(intr->src_bus_id,
621 intr->src_bus_irq));
622 case INTENTRY_FLAGS_TRIGGER_EDGE:
623 return (1);
624 case INTENTRY_FLAGS_TRIGGER_LEVEL:
625 return (0);
626 default:
627 panic("Bogus interrupt flags");
628 }
629 }
630
631 /*
632 * Parse an interrupt entry for an I/O interrupt routed to a pin on an I/O APIC.
633 */
634 static void
635 mptable_parse_io_int(int_entry_ptr intr)
636 {
637 void *ioapic;
638 u_int pin;
639
640 if (intr->dst_apic_id == 0xff) {
641 printf("MPTable: Ignoring global interrupt entry for pin %d\n",
642 intr->dst_apic_int);
643 return;
644 }
645 if (intr->dst_apic_id >= NAPICID) {
646 printf("MPTable: Ignoring interrupt entry for ioapic%d\n",
647 intr->dst_apic_id);
648 return;
649 }
650 ioapic = ioapics[intr->dst_apic_id];
651 if (ioapic == NULL) {
652 printf(
653 "MPTable: Ignoring interrupt entry for missing ioapic%d\n",
654 intr->dst_apic_id);
655 return;
656 }
657 pin = intr->dst_apic_int;
658 switch (intr->int_type) {
659 case INTENTRY_TYPE_INT:
660 if (busses[intr->src_bus_id].bus_type == NOBUS)
661 panic("interrupt from missing bus");
662 if (busses[intr->src_bus_id].bus_type == ISA &&
663 intr->src_bus_irq != pin) {
664 ioapic_remap_vector(ioapic, pin, intr->src_bus_irq);
665 if (ioapic_get_vector(ioapic, intr->src_bus_irq) ==
666 intr->src_bus_irq)
667 ioapic_disable_pin(ioapic, intr->src_bus_irq);
668 }
669 break;
670 case INTENTRY_TYPE_NMI:
671 ioapic_set_nmi(ioapic, pin);
672 break;
673 case INTENTRY_TYPE_SMI:
674 ioapic_set_smi(ioapic, pin);
675 break;
676 case INTENTRY_TYPE_EXTINT:
677 ioapic_set_extint(ioapic, pin);
678 break;
679 default:
680 panic("%s: invalid interrupt entry type %d\n", __func__,
681 intr->int_type);
682 }
683 if (intr->int_type == INTENTRY_TYPE_INT ||
684 (intr->int_flags & INTENTRY_FLAGS_TRIGGER) !=
685 INTENTRY_FLAGS_TRIGGER_CONFORM)
686 ioapic_set_triggermode(ioapic, pin, intentry_trigger(intr));
687 if (intr->int_type == INTENTRY_TYPE_INT ||
688 (intr->int_flags & INTENTRY_FLAGS_POLARITY) !=
689 INTENTRY_FLAGS_POLARITY_CONFORM)
690 ioapic_set_polarity(ioapic, pin, intentry_polarity(intr));
691 }
692
693 /*
694 * Parse an interrupt entry for a local APIC LVT pin.
695 */
696 static void
697 mptable_parse_local_int(int_entry_ptr intr)
698 {
699 u_int apic_id, pin;
700
701 if (intr->dst_apic_id == 0xff)
702 apic_id = APIC_ID_ALL;
703 else
704 apic_id = intr->dst_apic_id;
705 if (intr->dst_apic_int == 0)
706 pin = LVT_LINT0;
707 else
708 pin = LVT_LINT1;
709 switch (intr->int_type) {
710 case INTENTRY_TYPE_INT:
711 #if 1
712 printf(
713 "MPTable: Ignoring vectored local interrupt for LINTIN%d vector %d\n",
714 intr->dst_apic_int, intr->src_bus_irq);
715 return;
716 #else
717 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_FIXED);
718 break;
719 #endif
720 case INTENTRY_TYPE_NMI:
721 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_NMI);
722 break;
723 case INTENTRY_TYPE_SMI:
724 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_SMI);
725 break;
726 case INTENTRY_TYPE_EXTINT:
727 lapic_set_lvt_mode(apic_id, pin, APIC_LVT_DM_EXTINT);
728 break;
729 default:
730 panic("%s: invalid interrupt entry type %d\n", __func__,
731 intr->int_type);
732 }
733 if ((intr->int_flags & INTENTRY_FLAGS_TRIGGER) !=
734 INTENTRY_FLAGS_TRIGGER_CONFORM)
735 lapic_set_lvt_triggermode(apic_id, pin,
736 intentry_trigger(intr));
737 if ((intr->int_flags & INTENTRY_FLAGS_POLARITY) !=
738 INTENTRY_FLAGS_POLARITY_CONFORM)
739 lapic_set_lvt_polarity(apic_id, pin, intentry_polarity(intr));
740 }
741
742 /*
743 * Parse interrupt entries.
744 */
745 static void
746 mptable_parse_ints_handler(u_char *entry, void *arg __unused)
747 {
748 int_entry_ptr intr;
749
750 intr = (int_entry_ptr)entry;
751 switch (*entry) {
752 case MPCT_ENTRY_INT:
753 mptable_parse_io_int(intr);
754 break;
755 case MPCT_ENTRY_LOCAL_INT:
756 mptable_parse_local_int(intr);
757 break;
758 }
759 }
760
761 /*
762 * Configure the interrupt pins
763 */
764 static void
765 mptable_parse_ints(void)
766 {
767
768 /* Is this a pre-defined config? */
769 if (mpfps->config_type != 0) {
770 /* Configure LINT pins. */
771 lapic_set_lvt_mode(APIC_ID_ALL, LVT_LINT0, APIC_LVT_DM_EXTINT);
772 lapic_set_lvt_mode(APIC_ID_ALL, LVT_LINT1, APIC_LVT_DM_NMI);
773
774 /* Configure I/O APIC pins. */
775 if (mpfps->config_type != 7)
776 ioapic_set_extint(ioapics[0], 0);
777 else
778 ioapic_disable_pin(ioapics[0], 0);
779 if (mpfps->config_type != 2)
780 ioapic_remap_vector(ioapics[0], 2, 0);
781 else
782 ioapic_disable_pin(ioapics[0], 2);
783 if (mpfps->config_type == 2)
784 ioapic_disable_pin(ioapics[0], 13);
785 } else
786 mptable_walk_table(mptable_parse_ints_handler, NULL);
787 }
788
789 #ifdef MPTABLE_FORCE_HTT
790 /*
791 * Perform a hyperthreading "fix-up" to enumerate any logical CPU's
792 * that aren't already listed in the table.
793 *
794 * XXX: We assume that all of the physical CPUs in the
795 * system have the same number of logical CPUs.
796 *
797 * XXX: We assume that APIC ID's are allocated such that
798 * the APIC ID's for a physical processor are aligned
799 * with the number of logical CPU's in the processor.
800 */
801 static void
802 mptable_hyperthread_fixup(u_int id_mask)
803 {
804 u_int i, id, logical_cpus;
805
806 /* Nothing to do if there is no HTT support. */
807 if ((cpu_feature & CPUID_HTT) == 0)
808 return;
809 logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
810 if (logical_cpus <= 1)
811 return;
812
813 /*
814 * For each APIC ID of a CPU that is set in the mask,
815 * scan the other candidate APIC ID's for this
816 * physical processor. If any of those ID's are
817 * already in the table, then kill the fixup.
818 */
819 for (id = 0; id <= MAXCPU; id++) {
820 if ((id_mask & 1 << id) == 0)
821 continue;
822 /* First, make sure we are on a logical_cpus boundary. */
823 if (id % logical_cpus != 0)
824 return;
825 for (i = id + 1; i < id + logical_cpus; i++)
826 if ((id_mask & 1 << i) != 0)
827 return;
828 }
829
830 /*
831 * Ok, the ID's checked out, so perform the fixup by
832 * adding the logical CPUs.
833 */
834 while ((id = ffs(id_mask)) != 0) {
835 id--;
836 for (i = id + 1; i < id + logical_cpus; i++) {
837 if (bootverbose)
838 printf(
839 "MPTable: Adding logical CPU %d from main CPU %d\n",
840 i, id);
841 lapic_create(i, 0);
842 }
843 id_mask &= ~(1 << id);
844 }
845 }
846 #endif /* MPTABLE_FORCE_HTT */
847
848 /*
849 * Support code for routing PCI interrupts using the MP Table.
850 */
851 static void
852 mptable_pci_setup(void)
853 {
854 int i;
855
856 /*
857 * Find the first pci bus and call it 0. Panic if pci0 is not
858 * bus zero and there are multiple PCI busses.
859 */
860 for (i = 0; i <= mptable_maxbusid; i++)
861 if (busses[i].bus_type == PCI) {
862 if (pci0 == -1)
863 pci0 = i;
864 else if (pci0 != 0)
865 panic(
866 "MPTable contains multiple PCI busses but no PCI bus 0");
867 }
868 }
869
870 static void
871 mptable_pci_probe_table_handler(u_char *entry, void *arg)
872 {
873 struct pci_probe_table_args *args;
874 int_entry_ptr intr;
875
876 if (*entry != MPCT_ENTRY_INT)
877 return;
878 intr = (int_entry_ptr)entry;
879 args = (struct pci_probe_table_args *)arg;
880 KASSERT(args->bus <= mptable_maxbusid,
881 ("bus %d is too big", args->bus));
882 KASSERT(busses[args->bus].bus_type == PCI, ("probing for non-PCI bus"));
883 if (intr->src_bus_id == args->bus)
884 args->found = 1;
885 }
886
887 int
888 mptable_pci_probe_table(int bus)
889 {
890 struct pci_probe_table_args args;
891
892 if (bus < 0)
893 return (EINVAL);
894 if (pci0 == -1 || pci0 + bus > mptable_maxbusid)
895 return (ENXIO);
896 if (busses[pci0 + bus].bus_type != PCI)
897 return (ENXIO);
898 args.bus = pci0 + bus;
899 args.found = 0;
900 mptable_walk_table(mptable_pci_probe_table_handler, &args);
901 if (args.found == 0)
902 return (ENXIO);
903 return (0);
904 }
905
906 static void
907 mptable_pci_route_interrupt_handler(u_char *entry, void *arg)
908 {
909 struct pci_route_interrupt_args *args;
910 int_entry_ptr intr;
911 int vector;
912
913 if (*entry != MPCT_ENTRY_INT)
914 return;
915 intr = (int_entry_ptr)entry;
916 args = (struct pci_route_interrupt_args *)arg;
917 if (intr->src_bus_id != args->bus || intr->src_bus_irq != args->irq)
918 return;
919
920 /* Make sure the APIC maps to a known APIC. */
921 KASSERT(ioapics[intr->dst_apic_id] != NULL,
922 ("No I/O APIC %d to route interrupt to", intr->dst_apic_id));
923
924 /*
925 * Look up the vector for this APIC / pin combination. If we
926 * have previously matched an entry for this PCI IRQ but it
927 * has the same vector as this entry, just return. Otherwise,
928 * we use the vector for this APIC / pin combination.
929 */
930 vector = ioapic_get_vector(ioapics[intr->dst_apic_id],
931 intr->dst_apic_int);
932 if (args->vector == vector)
933 return;
934 KASSERT(args->vector == -1,
935 ("Multiple entries for PCI IRQ %d", args->vector));
936 args->vector = vector;
937 }
938
939 int
940 mptable_pci_route_interrupt(device_t pcib, device_t dev, int pin)
941 {
942 struct pci_route_interrupt_args args;
943 int slot;
944
945 /* Like ACPI, pin numbers are 0-3, not 1-4. */
946 pin--;
947 KASSERT(pci0 != -1, ("do not know how to route PCI interrupts"));
948 args.bus = pci_get_bus(dev) + pci0;
949 slot = pci_get_slot(dev);
950
951 /*
952 * PCI interrupt entries in the MP Table encode both the slot and
953 * pin into the IRQ with the pin being the two least significant
954 * bits, the slot being the next five bits, and the most significant
955 * bit being reserved.
956 */
957 args.irq = slot << 2 | pin;
958 args.vector = -1;
959 mptable_walk_table(mptable_pci_route_interrupt_handler, &args);
960 if (args.vector < 0) {
961 device_printf(pcib, "unable to route slot %d INT%c\n", slot,
962 'A' + pin);
963 return (PCI_INVALID_IRQ);
964 }
965 device_printf(pcib, "slot %d INT%c routed to irq %d\n", slot, 'A' + pin,
966 args.vector);
967 return (args.vector);
968 }
Cache object: ef9b71cc321bddeea2e5a1aa432e6e05
|