2 * Copyright (c) 1996, by Steve Passe
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
25 * $FreeBSD: src/sys/i386/i386/mp_machdep.c,v 1.115.2.15 2003/03/14 21:22:35 jhb Exp $
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>
39 #include <sys/mplock2.h>
42 #include <vm/vm_param.h>
44 #include <vm/vm_kern.h>
45 #include <vm/vm_extern.h>
47 #include <vm/vm_map.h>
53 #include <machine/smp.h>
54 #include <machine_base/isa/isa_intr.h>
55 #include <machine_base/apic/apicreg.h>
56 #include <machine_base/apic/apicvar.h>
57 #include <machine/atomic.h>
58 #include <machine/cpufunc.h>
59 #include <machine/cputypes.h>
60 #include <machine_base/apic/lapic.h>
61 #include <machine_base/apic/ioapic.h>
62 #include <machine/psl.h>
63 #include <machine/segments.h>
64 #include <machine/tss.h>
65 #include <machine/specialreg.h>
66 #include <machine/globaldata.h>
67 #include <machine/pmap_inval.h>
68 #include <machine/mptable.h>
70 #include <machine/md_var.h> /* setidt() */
71 #include <machine_base/icu/icu.h> /* IPIs */
72 #include <machine_base/apic/ioapic_abi.h>
73 #include <machine/intr_machdep.h> /* IPIs */
75 extern u_int base_memory
;
76 extern u_long ebda_addr
;
77 extern int imcr_present
;
80 static int force_enable
= 0;
81 TUNABLE_INT("hw.lapic_force_enable", &force_enable
);
83 #define BIOS_BASE (0xf0000)
84 #define BIOS_BASE2 (0xe0000)
85 #define BIOS_SIZE (0x10000)
86 #define BIOS_COUNT (BIOS_SIZE/4)
88 #define PROCENTRY_FLAG_EN 0x01
89 #define PROCENTRY_FLAG_BP 0x02
90 #define IOAPICENTRY_FLAG_EN 0x01
93 /* MP Floating Pointer Structure */
94 typedef struct MPFPS
{
107 /* MP Configuration Table Header */
108 typedef struct MPCTH
{
110 u_short base_table_length
;
114 u_char product_id
[12];
115 u_int32_t oem_table_pointer
;
116 u_short oem_table_size
;
118 u_int32_t apic_address
;
119 u_short extended_table_length
;
120 u_char extended_table_checksum
;
125 typedef struct PROCENTRY
{
130 u_int32_t cpu_signature
;
131 u_int32_t feature_flags
;
136 typedef struct BUSENTRY
{
142 typedef struct IOAPICENTRY
{
147 u_int32_t apic_address
;
148 } *io_apic_entry_ptr
;
150 typedef struct INTENTRY
{
160 /* descriptions of MP basetable entries */
161 typedef struct BASETABLE_ENTRY
{
170 vm_size_t mp_cth_mapsz
;
173 #define MPTABLE_POS_USE_DEFAULT(mpt) \
174 ((mpt)->mp_fps->mpfb1 != 0 || (mpt)->mp_cth == NULL)
178 int mb_type
; /* MPTABLE_BUS_ */
179 TAILQ_ENTRY(mptable_bus
) mb_link
;
182 #define MPTABLE_BUS_ISA 0
183 #define MPTABLE_BUS_PCI 1
185 struct mptable_bus_info
{
186 TAILQ_HEAD(, mptable_bus
) mbi_list
;
189 struct mptable_pci_int
{
196 TAILQ_ENTRY(mptable_pci_int
) mpci_link
;
199 struct mptable_ioapic
{
205 TAILQ_ENTRY(mptable_ioapic
) mio_link
;
208 typedef int (*mptable_iter_func
)(void *, const void *, int);
210 static int mptable_iterate_entries(const mpcth_t
,
211 mptable_iter_func
, void *);
212 static int mptable_search(void);
213 static long mptable_search_sig(u_int32_t target
, int count
);
214 static int mptable_hyperthread_fixup(cpumask_t
, int);
215 static int mptable_map(struct mptable_pos
*);
216 static void mptable_unmap(struct mptable_pos
*);
217 static void mptable_bus_info_alloc(const mpcth_t
,
218 struct mptable_bus_info
*);
219 static void mptable_bus_info_free(struct mptable_bus_info
*);
221 static int mptable_lapic_probe(struct lapic_enumerator
*);
222 static int mptable_lapic_enumerate(struct lapic_enumerator
*);
223 static void mptable_lapic_default(void);
225 static int mptable_ioapic_probe(struct ioapic_enumerator
*);
226 static void mptable_ioapic_enumerate(struct ioapic_enumerator
*);
228 static basetable_entry basetable_entry_types
[] =
230 {0, 20, "Processor"},
237 static vm_paddr_t mptable_fps_phyaddr
;
238 static int mptable_use_default
;
239 static TAILQ_HEAD(mptable_pci_int_list
, mptable_pci_int
) mptable_pci_int_list
=
240 TAILQ_HEAD_INITIALIZER(mptable_pci_int_list
);
241 static TAILQ_HEAD(mptable_ioapic_list
, mptable_ioapic
) mptable_ioapic_list
=
242 TAILQ_HEAD_INITIALIZER(mptable_ioapic_list
);
247 struct mptable_pos mpt
;
250 KKASSERT(mptable_fps_phyaddr
== 0);
252 mptable_fps_phyaddr
= mptable_search();
253 if (mptable_fps_phyaddr
== 0)
256 error
= mptable_map(&mpt
);
258 mptable_fps_phyaddr
= 0;
262 if (MPTABLE_POS_USE_DEFAULT(&mpt
)) {
263 kprintf("MPTABLE: use default configuration\n");
264 mptable_use_default
= 1;
266 if (mpt
.mp_fps
->mpfb2
& 0x80)
271 SYSINIT(mptable_probe
, SI_BOOT2_PRESMP
, SI_ORDER_FIRST
, mptable_probe
, 0);
274 * Look for an Intel MP spec table (ie, SMP capable hardware).
282 /* see if EBDA exists */
283 if (ebda_addr
!= 0) {
284 /* search first 1K of EBDA */
285 target
= (u_int32_t
)ebda_addr
;
286 if ((x
= mptable_search_sig(target
, 1024 / 4)) > 0)
289 /* last 1K of base memory, effective 'top of base' passed in */
290 target
= (u_int32_t
)(base_memory
- 0x400);
291 if ((x
= mptable_search_sig(target
, 1024 / 4)) > 0)
295 /* search the BIOS */
296 target
= (u_int32_t
)BIOS_BASE
;
297 if ((x
= mptable_search_sig(target
, BIOS_COUNT
)) > 0)
300 /* search the extended BIOS */
301 target
= (u_int32_t
)BIOS_BASE2
;
302 if ((x
= mptable_search_sig(target
, BIOS_COUNT
)) > 0)
310 mptable_iterate_entries(const mpcth_t cth
, mptable_iter_func func
, void *arg
)
312 int count
, total_size
;
313 const void *position
;
315 KKASSERT(cth
->base_table_length
>= sizeof(struct MPCTH
));
316 total_size
= cth
->base_table_length
- sizeof(struct MPCTH
);
317 position
= (const uint8_t *)cth
+ sizeof(struct MPCTH
);
318 count
= cth
->entry_count
;
323 KKASSERT(total_size
>= 0);
324 if (total_size
== 0) {
325 kprintf("invalid base MP table, "
326 "entry count and length mismatch\n");
330 type
= *(const uint8_t *)position
;
332 case 0: /* processor_entry */
333 case 1: /* bus_entry */
334 case 2: /* io_apic_entry */
335 case 3: /* int_entry */
336 case 4: /* int_entry */
339 kprintf("unknown base MP table entry type %d\n", type
);
343 if (total_size
< basetable_entry_types
[type
].length
) {
344 kprintf("invalid base MP table length, "
345 "does not contain all entries\n");
348 total_size
-= basetable_entry_types
[type
].length
;
350 error
= func(arg
, position
, type
);
354 position
= (const uint8_t *)position
+
355 basetable_entry_types
[type
].length
;
361 * look for the MP spec signature
364 /* string defined by the Intel MP Spec as identifying the MP table */
365 #define MP_SIG 0x5f504d5f /* _MP_ */
366 #define NEXT(X) ((X) += 4)
368 mptable_search_sig(u_int32_t target
, int count
)
374 KKASSERT(target
!= 0);
376 map_size
= count
* sizeof(u_int32_t
);
377 addr
= pmap_mapdev((vm_paddr_t
)target
, map_size
);
380 for (x
= 0; x
< count
; NEXT(x
)) {
381 if (addr
[x
] == MP_SIG
) {
382 /* make array index a byte index */
383 ret
= target
+ (x
* sizeof(u_int32_t
));
388 pmap_unmapdev((vm_offset_t
)addr
, map_size
);
392 static int processor_entry (const struct PROCENTRY
*entry
, int cpu
);
395 * Check if we should perform a hyperthreading "fix-up" to
396 * enumerate any logical CPU's that aren't already listed
399 * XXX: We assume that all of the physical CPUs in the
400 * system have the same number of logical CPUs.
402 * XXX: We assume that APIC ID's are allocated such that
403 * the APIC ID's for a physical processor are aligned
404 * with the number of logical CPU's in the processor.
407 mptable_hyperthread_fixup(cpumask_t id_mask
, int cpu_count
)
409 int i
, id
, lcpus_max
, logical_cpus
;
411 if ((cpu_feature
& CPUID_HTT
) == 0)
414 lcpus_max
= (cpu_procinfo
& CPUID_HTT_CORES
) >> 16;
418 if (cpu_vendor_id
== CPU_VENDOR_INTEL
) {
420 * INSTRUCTION SET REFERENCE, A-M (#253666)
421 * Page 3-181, Table 3-20
422 * "The nearest power-of-2 integer that is not smaller
423 * than EBX[23:16] is the number of unique initial APIC
424 * IDs reserved for addressing different logical
425 * processors in a physical package."
428 if ((1 << i
) >= lcpus_max
) {
435 KKASSERT(cpu_count
!= 0);
436 if (cpu_count
== lcpus_max
) {
437 /* We have nothing to fix */
439 } else if (cpu_count
== 1) {
440 /* XXX this may be incorrect */
441 logical_cpus
= lcpus_max
;
446 * Calculate the distances between two nearest
447 * APIC IDs. If all such distances are same,
448 * then it is the number of missing cpus that
449 * we are going to fill later.
451 dist
= cur
= prev
= -1;
452 for (id
= 0; id
< MAXCPU
; ++id
) {
453 if (CPUMASK_TESTBIT(id_mask
, id
) == 0)
458 int new_dist
= cur
- prev
;
464 * Make sure that all distances
465 * between two nearest APIC IDs
468 if (dist
!= new_dist
)
476 /* Must be power of 2 */
477 if (dist
& (dist
- 1))
480 /* Can't exceed CPU package capacity */
481 if (dist
> lcpus_max
)
482 logical_cpus
= lcpus_max
;
488 * For each APIC ID of a CPU that is set in the mask,
489 * scan the other candidate APIC ID's for this
490 * physical processor. If any of those ID's are
491 * already in the table, then kill the fixup.
493 for (id
= 0; id
< MAXCPU
; id
++) {
494 if (CPUMASK_TESTBIT(id_mask
, id
) == 0)
496 /* First, make sure we are on a logical_cpus boundary. */
497 if (id
% logical_cpus
!= 0)
499 for (i
= id
+ 1; i
< id
+ logical_cpus
; i
++)
500 if (CPUMASK_TESTBIT(id_mask
, i
) != 0)
507 mptable_map(struct mptable_pos
*mpt
)
511 vm_size_t cth_mapsz
= 0;
513 KKASSERT(mptable_fps_phyaddr
!= 0);
515 bzero(mpt
, sizeof(*mpt
));
517 fps
= pmap_mapdev(mptable_fps_phyaddr
, sizeof(*fps
));
520 * Map configuration table header to get
521 * the base table size
523 cth
= pmap_mapdev(fps
->pap
, sizeof(*cth
));
524 cth_mapsz
= cth
->base_table_length
;
525 pmap_unmapdev((vm_offset_t
)cth
, sizeof(*cth
));
527 if (cth_mapsz
< sizeof(*cth
)) {
528 kprintf("invalid base MP table length %d\n",
530 pmap_unmapdev((vm_offset_t
)fps
, sizeof(*fps
));
537 cth
= pmap_mapdev(fps
->pap
, cth_mapsz
);
542 mpt
->mp_cth_mapsz
= cth_mapsz
;
548 mptable_unmap(struct mptable_pos
*mpt
)
550 if (mpt
->mp_cth
!= NULL
) {
551 pmap_unmapdev((vm_offset_t
)mpt
->mp_cth
, mpt
->mp_cth_mapsz
);
553 mpt
->mp_cth_mapsz
= 0;
555 if (mpt
->mp_fps
!= NULL
) {
556 pmap_unmapdev((vm_offset_t
)mpt
->mp_fps
, sizeof(*mpt
->mp_fps
));
562 processor_entry(const struct PROCENTRY
*entry
, int cpu
)
566 /* check for usability */
567 if (!(entry
->cpu_flags
& PROCENTRY_FLAG_EN
))
570 /* check for BSP flag */
571 if (entry
->cpu_flags
& PROCENTRY_FLAG_BP
) {
572 lapic_set_cpuid(0, entry
->apic_id
);
573 return 0; /* its already been counted */
576 /* add another AP to list, if less than max number of CPUs */
577 else if (cpu
< MAXCPU
) {
578 lapic_set_cpuid(cpu
, entry
->apic_id
);
586 mptable_bus_info_callback(void *xarg
, const void *pos
, int type
)
588 struct mptable_bus_info
*bus_info
= xarg
;
589 const struct BUSENTRY
*ent
;
590 struct mptable_bus
*bus
;
596 TAILQ_FOREACH(bus
, &bus_info
->mbi_list
, mb_link
) {
597 if (bus
->mb_id
== ent
->bus_id
) {
598 kprintf("mptable_bus_info_alloc: duplicated bus id "
599 "(%d)\n", bus
->mb_id
);
605 if (strncmp(ent
->bus_type
, "PCI", 3) == 0) {
606 bus
= kmalloc(sizeof(*bus
), M_TEMP
, M_WAITOK
| M_ZERO
);
607 bus
->mb_type
= MPTABLE_BUS_PCI
;
608 } else if (strncmp(ent
->bus_type
, "ISA", 3) == 0) {
609 bus
= kmalloc(sizeof(*bus
), M_TEMP
, M_WAITOK
| M_ZERO
);
610 bus
->mb_type
= MPTABLE_BUS_ISA
;
614 bus
->mb_id
= ent
->bus_id
;
615 TAILQ_INSERT_TAIL(&bus_info
->mbi_list
, bus
, mb_link
);
621 mptable_bus_info_alloc(const mpcth_t cth
, struct mptable_bus_info
*bus_info
)
625 bzero(bus_info
, sizeof(*bus_info
));
626 TAILQ_INIT(&bus_info
->mbi_list
);
628 error
= mptable_iterate_entries(cth
, mptable_bus_info_callback
, bus_info
);
630 mptable_bus_info_free(bus_info
);
634 mptable_bus_info_free(struct mptable_bus_info
*bus_info
)
636 struct mptable_bus
*bus
;
638 while ((bus
= TAILQ_FIRST(&bus_info
->mbi_list
)) != NULL
) {
639 TAILQ_REMOVE(&bus_info
->mbi_list
, bus
, mb_link
);
644 struct mptable_lapic_cbarg1
{
647 u_int ht_apicid_mask
;
651 mptable_lapic_pass1_callback(void *xarg
, const void *pos
, int type
)
653 const struct PROCENTRY
*ent
;
654 struct mptable_lapic_cbarg1
*arg
= xarg
;
660 if ((ent
->cpu_flags
& PROCENTRY_FLAG_EN
) == 0)
664 if (ent
->apic_id
< 64) {
665 arg
->ht_apicid_mask
|= 1UL << ent
->apic_id
;
666 } else if (arg
->ht_fixup
) {
667 kprintf("MPTABLE: lapic id > 64, disable HTT fixup\n");
673 struct mptable_lapic_cbarg2
{
680 mptable_lapic_pass2_callback(void *xarg
, const void *pos
, int type
)
682 const struct PROCENTRY
*ent
;
683 struct mptable_lapic_cbarg2
*arg
= xarg
;
689 if (ent
->cpu_flags
& PROCENTRY_FLAG_BP
) {
690 KKASSERT(!arg
->found_bsp
);
694 if (processor_entry(ent
, arg
->cpu
))
697 if (arg
->logical_cpus
) {
698 struct PROCENTRY proc
;
702 * Create fake mptable processor entries
703 * and feed them to processor_entry() to
704 * enumerate the logical CPUs.
706 bzero(&proc
, sizeof(proc
));
708 proc
.cpu_flags
= (force_enable
) ? PROCENTRY_FLAG_EN
: ent
->cpu_flags
;
709 proc
.apic_id
= ent
->apic_id
;
711 for (i
= 1; i
< arg
->logical_cpus
; i
++) {
713 processor_entry(&proc
, arg
->cpu
);
721 mptable_lapic_default(void)
723 int ap_apicid
, bsp_apicid
;
725 naps
= 1; /* exclude BSP */
727 /* Map local apic before the id field is accessed */
728 lapic_map(DEFAULT_APIC_BASE
);
730 bsp_apicid
= APIC_ID(lapic
->id
);
731 ap_apicid
= (bsp_apicid
== 0) ? 1 : 0;
734 lapic_set_cpuid(0, bsp_apicid
);
735 /* one and only AP */
736 lapic_set_cpuid(1, ap_apicid
);
742 * APIC ID <-> CPU ID mappings
745 mptable_lapic_enumerate(struct lapic_enumerator
*e
)
747 struct mptable_pos mpt
;
748 struct mptable_lapic_cbarg1 arg1
;
749 struct mptable_lapic_cbarg2 arg2
;
751 int error
, logical_cpus
= 0;
752 vm_paddr_t lapic_addr
;
754 if (mptable_use_default
) {
755 mptable_lapic_default();
759 error
= mptable_map(&mpt
);
761 panic("mptable_lapic_enumerate mptable_map failed");
762 KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt
));
766 /* Save local apic address */
767 lapic_addr
= cth
->apic_address
;
768 KKASSERT(lapic_addr
!= 0);
771 * Find out how many CPUs do we have
773 bzero(&arg1
, sizeof(arg1
));
774 arg1
.ht_fixup
= 1; /* Apply ht fixup by default */
776 error
= mptable_iterate_entries(cth
,
777 mptable_lapic_pass1_callback
, &arg1
);
779 panic("mptable_iterate_entries(lapic_pass1) failed");
780 KKASSERT(arg1
.cpu_count
!= 0);
782 /* See if we need to fixup HT logical CPUs. */
784 * XXX fixup for cpus >= 32 ? XXX
789 CPUMASK_ASSZERO(mask
);
790 mask
.ary
[0] = arg1
.ht_apicid_mask
;
791 logical_cpus
= mptable_hyperthread_fixup(mask
, arg1
.cpu_count
);
792 if (logical_cpus
!= 0)
793 arg1
.cpu_count
*= logical_cpus
;
795 naps
= arg1
.cpu_count
- 1; /* subtract the BSP */
798 * Link logical CPU id to local apic id
800 bzero(&arg2
, sizeof(arg2
));
802 arg2
.logical_cpus
= logical_cpus
;
804 error
= mptable_iterate_entries(cth
,
805 mptable_lapic_pass2_callback
, &arg2
);
807 panic("mptable_iterate_entries(lapic_pass2) failed");
808 KKASSERT(arg2
.found_bsp
);
811 lapic_map(lapic_addr
);
818 struct mptable_lapic_probe_cbarg
{
824 mptable_lapic_probe_callback(void *xarg
, const void *pos
, int type
)
826 const struct PROCENTRY
*ent
;
827 struct mptable_lapic_probe_cbarg
*arg
= xarg
;
833 if ((ent
->cpu_flags
& PROCENTRY_FLAG_EN
) == 0)
837 if (ent
->apic_id
== APICID_MAX
) {
838 kprintf("MPTABLE: invalid LAPIC apic id %d\n",
843 if (ent
->cpu_flags
& PROCENTRY_FLAG_BP
) {
844 if (arg
->found_bsp
) {
845 kprintf("more than one BSP in base MP table\n");
854 mptable_lapic_probe(struct lapic_enumerator
*e
)
856 struct mptable_pos mpt
;
857 struct mptable_lapic_probe_cbarg arg
;
861 if (mptable_fps_phyaddr
== 0)
864 if (mptable_use_default
)
867 error
= mptable_map(&mpt
);
870 KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt
));
875 if (cth
->apic_address
== 0)
878 bzero(&arg
, sizeof(arg
));
879 error
= mptable_iterate_entries(cth
,
880 mptable_lapic_probe_callback
, &arg
);
882 if (arg
.cpu_count
== 0) {
883 kprintf("MP table contains no processor entries\n");
885 } else if (!arg
.found_bsp
) {
886 kprintf("MP table does not contains BSP entry\n");
895 static struct lapic_enumerator mptable_lapic_enumerator
= {
896 .lapic_prio
= LAPIC_ENUM_PRIO_MPTABLE
,
897 .lapic_probe
= mptable_lapic_probe
,
898 .lapic_enumerate
= mptable_lapic_enumerate
902 mptable_lapic_enum_register(void)
904 lapic_enumerator_register(&mptable_lapic_enumerator
);
906 SYSINIT(mptable_lapic
, SI_BOOT2_PRESMP
, SI_ORDER_ANY
,
907 mptable_lapic_enum_register
, 0);
910 mptable_ioapic_list_callback(void *xarg
, const void *pos
, int type
)
912 const struct IOAPICENTRY
*ent
;
913 struct mptable_ioapic
*nioapic
, *ioapic
;
919 if ((ent
->apic_flags
& IOAPICENTRY_FLAG_EN
) == 0)
922 if (ent
->apic_address
== 0) {
923 kprintf("mptable_ioapic_create_list: zero IOAPIC addr\n");
926 if (ent
->apic_id
== APICID_MAX
) {
927 kprintf("mptable_ioapic_create_list: "
928 "invalid IOAPIC apic id %d\n", ent
->apic_id
);
932 TAILQ_FOREACH(ioapic
, &mptable_ioapic_list
, mio_link
) {
933 if (ioapic
->mio_apic_id
== ent
->apic_id
) {
934 kprintf("mptable_ioapic_create_list: duplicated "
935 "apic id %d\n", ioapic
->mio_apic_id
);
938 if (ioapic
->mio_addr
== ent
->apic_address
) {
939 kprintf("mptable_ioapic_create_list: overlapped "
940 "IOAPIC addr 0x%08x", ioapic
->mio_addr
);
945 nioapic
= kmalloc(sizeof(*nioapic
), M_DEVBUF
, M_WAITOK
| M_ZERO
);
946 nioapic
->mio_apic_id
= ent
->apic_id
;
947 nioapic
->mio_addr
= ent
->apic_address
;
950 * Create IOAPIC list in ascending order of APIC ID
952 TAILQ_FOREACH_REVERSE(ioapic
, &mptable_ioapic_list
,
953 mptable_ioapic_list
, mio_link
) {
954 if (nioapic
->mio_apic_id
> ioapic
->mio_apic_id
) {
955 TAILQ_INSERT_AFTER(&mptable_ioapic_list
,
956 ioapic
, nioapic
, mio_link
);
961 TAILQ_INSERT_HEAD(&mptable_ioapic_list
, nioapic
, mio_link
);
967 mptable_ioapic_create_list(void)
969 struct mptable_ioapic
*ioapic
;
970 struct mptable_pos mpt
;
973 if (mptable_fps_phyaddr
== 0)
976 if (mptable_use_default
) {
977 ioapic
= kmalloc(sizeof(*ioapic
), M_DEVBUF
, M_WAITOK
| M_ZERO
);
979 ioapic
->mio_apic_id
= 0; /* NOTE: any value is ok here */
980 ioapic
->mio_addr
= 0xfec00000; /* XXX magic number */
982 TAILQ_INSERT_HEAD(&mptable_ioapic_list
, ioapic
, mio_link
);
986 error
= mptable_map(&mpt
);
988 panic("mptable_ioapic_create_list: mptable_map failed");
989 KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt
));
991 error
= mptable_iterate_entries(mpt
.mp_cth
,
992 mptable_ioapic_list_callback
, NULL
);
994 while ((ioapic
= TAILQ_FIRST(&mptable_ioapic_list
)) != NULL
) {
995 TAILQ_REMOVE(&mptable_ioapic_list
, ioapic
, mio_link
);
996 kfree(ioapic
, M_DEVBUF
);
1002 * Assign index number for each IOAPIC
1005 TAILQ_FOREACH(ioapic
, &mptable_ioapic_list
, mio_link
) {
1006 ioapic
->mio_idx
= idx
;
1010 mptable_unmap(&mpt
);
1012 SYSINIT(mptable_ioapic_list
, SI_BOOT2_PRESMP
, SI_ORDER_SECOND
,
1013 mptable_ioapic_create_list
, 0);
1016 mptable_pci_int_callback(void *xarg
, const void *pos
, int type
)
1018 const struct mptable_bus_info
*bus_info
= xarg
;
1019 const struct mptable_ioapic
*ioapic
;
1020 const struct mptable_bus
*bus
;
1021 struct mptable_pci_int
*pci_int
;
1022 const struct INTENTRY
*ent
;
1023 int pci_pin
, pci_dev
;
1029 if (ent
->int_type
!= 0)
1032 TAILQ_FOREACH(bus
, &bus_info
->mbi_list
, mb_link
) {
1033 if (bus
->mb_type
== MPTABLE_BUS_PCI
&&
1034 bus
->mb_id
== ent
->src_bus_id
)
1040 TAILQ_FOREACH(ioapic
, &mptable_ioapic_list
, mio_link
) {
1041 if (ioapic
->mio_apic_id
== ent
->dst_apic_id
)
1044 if (ioapic
== NULL
) {
1046 static char intdis_warned
[64];
1047 int apic_id
= ent
->dst_apic_id
;
1050 if (apic_id
< 0 || apic_id
>= sizeof(intdis_warned
)) {
1052 } else if (intdis_warned
[apic_id
] == 0) {
1053 intdis_warned
[apic_id
] = 1;
1057 kprintf("MPTABLE: warning PCI int dst apic id "
1058 "%d does not exist\n", apic_id
);
1064 pci_pin
= ent
->src_bus_irq
& 0x3;
1065 pci_dev
= (ent
->src_bus_irq
>> 2) & 0x1f;
1067 TAILQ_FOREACH(pci_int
, &mptable_pci_int_list
, mpci_link
) {
1068 if (pci_int
->mpci_bus
== ent
->src_bus_id
&&
1069 pci_int
->mpci_dev
== pci_dev
&&
1070 pci_int
->mpci_pin
== pci_pin
) {
1071 if (pci_int
->mpci_ioapic_idx
== ioapic
->mio_idx
&&
1072 pci_int
->mpci_ioapic_pin
== ent
->dst_apic_int
) {
1073 kprintf("MPTABLE: warning duplicated "
1074 "PCI int entry for "
1075 "bus %d, dev %d, pin %d\n",
1081 kprintf("mptable_pci_int_register: "
1082 "conflict PCI int entry for "
1083 "bus %d, dev %d, pin %d, "
1084 "IOAPIC %d.%d -> %d.%d\n",
1088 pci_int
->mpci_ioapic_idx
,
1089 pci_int
->mpci_ioapic_pin
,
1097 pci_int
= kmalloc(sizeof(*pci_int
), M_DEVBUF
, M_WAITOK
| M_ZERO
);
1099 pci_int
->mpci_bus
= ent
->src_bus_id
;
1100 pci_int
->mpci_dev
= pci_dev
;
1101 pci_int
->mpci_pin
= pci_pin
;
1102 pci_int
->mpci_ioapic_idx
= ioapic
->mio_idx
;
1103 pci_int
->mpci_ioapic_pin
= ent
->dst_apic_int
;
1105 TAILQ_INSERT_TAIL(&mptable_pci_int_list
, pci_int
, mpci_link
);
1111 mptable_pci_int_register(void)
1113 struct mptable_bus_info bus_info
;
1114 const struct mptable_bus
*bus
;
1115 struct mptable_pci_int
*pci_int
;
1116 struct mptable_pos mpt
;
1117 int error
, force_pci0
, npcibus
;
1120 if (mptable_fps_phyaddr
== 0)
1123 if (mptable_use_default
)
1126 if (TAILQ_EMPTY(&mptable_ioapic_list
))
1129 error
= mptable_map(&mpt
);
1131 panic("mptable_pci_int_register: mptable_map failed");
1132 KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt
));
1136 mptable_bus_info_alloc(cth
, &bus_info
);
1137 if (TAILQ_EMPTY(&bus_info
.mbi_list
))
1142 TAILQ_FOREACH(bus
, &bus_info
.mbi_list
, mb_link
) {
1143 if (bus
->mb_type
== MPTABLE_BUS_PCI
)
1147 mptable_bus_info_free(&bus_info
);
1149 } else if (npcibus
== 1) {
1153 error
= mptable_iterate_entries(cth
,
1154 mptable_pci_int_callback
, &bus_info
);
1156 mptable_bus_info_free(&bus_info
);
1159 while ((pci_int
= TAILQ_FIRST(&mptable_pci_int_list
)) != NULL
) {
1160 TAILQ_REMOVE(&mptable_pci_int_list
, pci_int
, mpci_link
);
1161 kfree(pci_int
, M_DEVBUF
);
1167 TAILQ_FOREACH(pci_int
, &mptable_pci_int_list
, mpci_link
)
1168 pci_int
->mpci_bus
= 0;
1171 mptable_unmap(&mpt
);
1173 SYSINIT(mptable_pci
, SI_BOOT2_PRESMP
, SI_ORDER_ANY
,
1174 mptable_pci_int_register
, 0);
1176 struct mptable_ioapic_probe_cbarg
{
1177 const struct mptable_bus_info
*bus_info
;
1181 mptable_ioapic_probe_callback(void *xarg
, const void *pos
, int type
)
1183 struct mptable_ioapic_probe_cbarg
*arg
= xarg
;
1184 const struct mptable_ioapic
*ioapic
;
1185 const struct mptable_bus
*bus
;
1186 const struct INTENTRY
*ent
;
1192 if (ent
->int_type
!= 0)
1195 TAILQ_FOREACH(bus
, &arg
->bus_info
->mbi_list
, mb_link
) {
1196 if (bus
->mb_type
== MPTABLE_BUS_ISA
&&
1197 bus
->mb_id
== ent
->src_bus_id
)
1203 TAILQ_FOREACH(ioapic
, &mptable_ioapic_list
, mio_link
) {
1204 if (ioapic
->mio_apic_id
== ent
->dst_apic_id
)
1207 if (ioapic
== NULL
) {
1208 kprintf("MPTABLE: warning ISA int dst apic id %d "
1209 "does not exist\n", ent
->dst_apic_id
);
1213 /* XXX magic number */
1214 if (ent
->src_bus_irq
>= ISA_IRQ_CNT
) {
1215 kprintf("mptable_ioapic_probe: invalid ISA irq (%d)\n",
1223 mptable_ioapic_probe(struct ioapic_enumerator
*e
)
1225 struct mptable_ioapic_probe_cbarg arg
;
1226 struct mptable_bus_info bus_info
;
1227 struct mptable_pos mpt
;
1231 if (mptable_fps_phyaddr
== 0)
1234 if (mptable_use_default
)
1237 if (TAILQ_EMPTY(&mptable_ioapic_list
))
1240 error
= mptable_map(&mpt
);
1242 panic("mptable_ioapic_probe: mptable_map failed");
1243 KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt
));
1247 mptable_bus_info_alloc(cth
, &bus_info
);
1249 bzero(&arg
, sizeof(arg
));
1250 arg
.bus_info
= &bus_info
;
1252 error
= mptable_iterate_entries(cth
,
1253 mptable_ioapic_probe_callback
, &arg
);
1255 mptable_bus_info_free(&bus_info
);
1256 mptable_unmap(&mpt
);
1261 struct mptable_ioapic_int_cbarg
{
1262 const struct mptable_bus_info
*bus_info
;
1267 mptable_ioapic_int_callback(void *xarg
, const void *pos
, int type
)
1269 struct mptable_ioapic_int_cbarg
*arg
= xarg
;
1270 const struct mptable_ioapic
*ioapic
;
1271 const struct mptable_bus
*bus
;
1272 const struct INTENTRY
*ent
;
1281 if (ent
->int_type
!= 0)
1284 TAILQ_FOREACH(bus
, &arg
->bus_info
->mbi_list
, mb_link
) {
1285 if (bus
->mb_type
== MPTABLE_BUS_ISA
&&
1286 bus
->mb_id
== ent
->src_bus_id
)
1292 TAILQ_FOREACH(ioapic
, &mptable_ioapic_list
, mio_link
) {
1293 if (ioapic
->mio_apic_id
== ent
->dst_apic_id
)
1296 if (ioapic
== NULL
) {
1297 kprintf("MPTABLE: warning ISA int dst apic id %d "
1298 "does not exist\n", ent
->dst_apic_id
);
1302 if (ent
->dst_apic_int
>= ioapic
->mio_npin
) {
1303 panic("mptable_ioapic_enumerate: invalid I/O APIC "
1304 "pin %d, should be < %d",
1305 ent
->dst_apic_int
, ioapic
->mio_npin
);
1307 gsi
= ioapic
->mio_gsi_base
+ ent
->dst_apic_int
;
1309 if (ent
->src_bus_irq
!= gsi
) {
1311 kprintf("MPTABLE: INTSRC irq %d -> GSI %d\n",
1312 ent
->src_bus_irq
, gsi
);
1314 ioapic_intsrc(ent
->src_bus_irq
, gsi
,
1315 INTR_TRIGGER_EDGE
, INTR_POLARITY_HIGH
);
1321 mptable_ioapic_enumerate(struct ioapic_enumerator
*e
)
1323 struct mptable_bus_info bus_info
;
1324 struct mptable_ioapic
*ioapic
;
1325 struct mptable_pos mpt
;
1329 KKASSERT(mptable_fps_phyaddr
!= 0);
1330 KKASSERT(!TAILQ_EMPTY(&mptable_ioapic_list
));
1332 TAILQ_FOREACH(ioapic
, &mptable_ioapic_list
, mio_link
) {
1333 const struct mptable_ioapic
*prev_ioapic
;
1337 addr
= ioapic_map(ioapic
->mio_addr
);
1339 ver
= ioapic_read(addr
, IOAPIC_VER
);
1340 ioapic
->mio_npin
= ((ver
& IOART_VER_MAXREDIR
)
1341 >> MAXREDIRSHIFT
) + 1;
1343 prev_ioapic
= TAILQ_PREV(ioapic
,
1344 mptable_ioapic_list
, mio_link
);
1345 if (prev_ioapic
== NULL
) {
1346 ioapic
->mio_gsi_base
= 0;
1348 ioapic
->mio_gsi_base
=
1349 prev_ioapic
->mio_gsi_base
+
1350 prev_ioapic
->mio_npin
;
1352 ioapic_add(addr
, ioapic
->mio_gsi_base
, ioapic
->mio_npin
);
1355 kprintf("MPTABLE: IOAPIC addr 0x%08x, "
1356 "apic id %d, idx %d, gsi base %d, npin %d\n",
1358 ioapic
->mio_apic_id
,
1360 ioapic
->mio_gsi_base
,
1365 if (mptable_use_default
) {
1367 kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 (default)\n");
1368 ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE
, INTR_POLARITY_HIGH
);
1372 error
= mptable_map(&mpt
);
1374 panic("mptable_ioapic_probe: mptable_map failed");
1375 KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt
));
1379 mptable_bus_info_alloc(cth
, &bus_info
);
1381 if (TAILQ_EMPTY(&bus_info
.mbi_list
)) {
1383 kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 (no bus)\n");
1384 ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE
, INTR_POLARITY_HIGH
);
1386 struct mptable_ioapic_int_cbarg arg
;
1388 bzero(&arg
, sizeof(arg
));
1389 arg
.bus_info
= &bus_info
;
1391 error
= mptable_iterate_entries(cth
,
1392 mptable_ioapic_int_callback
, &arg
);
1394 panic("mptable_ioapic_int failed");
1396 if (arg
.ioapic_nint
== 0) {
1398 kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 "
1401 ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE
,
1402 INTR_POLARITY_HIGH
);
1406 mptable_bus_info_free(&bus_info
);
1408 mptable_unmap(&mpt
);
1411 static struct ioapic_enumerator mptable_ioapic_enumerator
= {
1412 .ioapic_prio
= IOAPIC_ENUM_PRIO_MPTABLE
,
1413 .ioapic_probe
= mptable_ioapic_probe
,
1414 .ioapic_enumerate
= mptable_ioapic_enumerate
1418 mptable_ioapic_enum_register(void)
1420 ioapic_enumerator_register(&mptable_ioapic_enumerator
);
1422 SYSINIT(mptable_ioapic
, SI_BOOT2_PRESMP
, SI_ORDER_ANY
,
1423 mptable_ioapic_enum_register
, 0);
1426 mptable_pci_int_dump(void)
1428 const struct mptable_pci_int
*pci_int
;
1433 TAILQ_FOREACH(pci_int
, &mptable_pci_int_list
, mpci_link
) {
1434 kprintf("MPTABLE: %d:%d INT%c -> IOAPIC %d.%d\n",
1437 pci_int
->mpci_pin
+ 'A',
1438 pci_int
->mpci_ioapic_idx
,
1439 pci_int
->mpci_ioapic_pin
);
1444 mptable_pci_int_route(int bus
, int dev
, int pin
, int intline
)
1446 const struct mptable_pci_int
*pci_int
;
1450 --pin
; /* zero based */
1452 TAILQ_FOREACH(pci_int
, &mptable_pci_int_list
, mpci_link
) {
1453 if (pci_int
->mpci_bus
== bus
&&
1454 pci_int
->mpci_dev
== dev
&&
1455 pci_int
->mpci_pin
== pin
)
1458 if (pci_int
!= NULL
) {
1461 gsi
= ioapic_gsi(pci_int
->mpci_ioapic_idx
,
1462 pci_int
->mpci_ioapic_pin
);
1464 irq
= machintr_legacy_intr_find_bygsi(gsi
,
1465 INTR_TRIGGER_LEVEL
, INTR_POLARITY_LOW
);
1469 if (irq
< 0 && intline
>= 0) {
1470 kprintf("MPTABLE: fixed interrupt routing "
1471 "for %d:%d INT%c\n", bus
, dev
, pin
+ 'A');
1472 irq
= machintr_legacy_intr_find(intline
,
1473 INTR_TRIGGER_LEVEL
, INTR_POLARITY_LOW
);
1476 if (irq
>= 0 && bootverbose
) {
1477 kprintf("MPTABLE: %d:%d INT%c routed to irq %d\n",
1478 bus
, dev
, pin
+ 'A', irq
);