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