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