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>
50 #include <machine/smp.h>
51 #include <machine_base/isa/isa_intr.h>
52 #include <machine_base/apic/apicreg.h>
53 #include <machine_base/apic/apicvar.h>
54 #include <machine/atomic.h>
55 #include <machine/cpufunc.h>
56 #include <machine/cputypes.h>
57 #include <machine_base/apic/lapic.h>
58 #include <machine_base/apic/ioapic.h>
59 #include <machine/psl.h>
60 #include <machine/segments.h>
61 #include <machine/tss.h>
62 #include <machine/specialreg.h>
63 #include <machine/globaldata.h>
64 #include <machine/pmap_inval.h>
65 #include <machine/mptable.h>
67 #include <machine/md_var.h> /* setidt() */
68 #include <machine_base/icu/icu.h> /* IPIs */
69 #include <machine_base/apic/ioapic_abi.h>
70 #include <machine/intr_machdep.h> /* IPIs */
72 extern u_int base_memory
;
73 extern u_long ebda_addr
;
74 extern int imcr_present
;
77 static int force_enable
= 0;
78 TUNABLE_INT("hw.lapic_force_enable", &force_enable
);
80 #define BIOS_BASE (0xf0000)
81 #define BIOS_BASE2 (0xe0000)
82 #define BIOS_SIZE (0x10000)
83 #define BIOS_COUNT (BIOS_SIZE/4)
85 #define PROCENTRY_FLAG_EN 0x01
86 #define PROCENTRY_FLAG_BP 0x02
87 #define IOAPICENTRY_FLAG_EN 0x01
90 /* MP Floating Pointer Structure */
91 typedef struct MPFPS
{
104 /* MP Configuration Table Header */
105 typedef struct MPCTH
{
107 u_short base_table_length
;
111 u_char product_id
[12];
112 u_int32_t oem_table_pointer
;
113 u_short oem_table_size
;
115 u_int32_t apic_address
;
116 u_short extended_table_length
;
117 u_char extended_table_checksum
;
122 typedef struct PROCENTRY
{
127 u_int32_t cpu_signature
;
128 u_int32_t feature_flags
;
133 typedef struct BUSENTRY
{
139 typedef struct IOAPICENTRY
{
144 u_int32_t apic_address
;
145 } *io_apic_entry_ptr
;
147 typedef struct INTENTRY
{
157 /* descriptions of MP basetable entries */
158 typedef struct BASETABLE_ENTRY
{
167 vm_size_t mp_cth_mapsz
;
170 #define MPTABLE_POS_USE_DEFAULT(mpt) \
171 ((mpt)->mp_fps->mpfb1 != 0 || (mpt)->mp_cth == NULL)
175 int mb_type
; /* MPTABLE_BUS_ */
176 TAILQ_ENTRY(mptable_bus
) mb_link
;
179 #define MPTABLE_BUS_ISA 0
180 #define MPTABLE_BUS_PCI 1
182 struct mptable_bus_info
{
183 TAILQ_HEAD(, mptable_bus
) mbi_list
;
186 struct mptable_pci_int
{
193 TAILQ_ENTRY(mptable_pci_int
) mpci_link
;
196 struct mptable_ioapic
{
202 TAILQ_ENTRY(mptable_ioapic
) mio_link
;
205 typedef int (*mptable_iter_func
)(void *, const void *, int);
207 static int mptable_iterate_entries(const mpcth_t
,
208 mptable_iter_func
, void *);
209 static int mptable_search(void);
210 static long mptable_search_sig(u_int32_t target
, int count
);
211 static int mptable_hyperthread_fixup(cpumask_t
, int);
212 static int mptable_map(struct mptable_pos
*);
213 static void mptable_unmap(struct mptable_pos
*);
214 static void mptable_bus_info_alloc(const mpcth_t
,
215 struct mptable_bus_info
*);
216 static void mptable_bus_info_free(struct mptable_bus_info
*);
218 static int mptable_lapic_probe(struct lapic_enumerator
*);
219 static int mptable_lapic_enumerate(struct lapic_enumerator
*);
220 static void mptable_lapic_default(void);
222 static int mptable_ioapic_probe(struct ioapic_enumerator
*);
223 static void mptable_ioapic_enumerate(struct ioapic_enumerator
*);
225 static basetable_entry basetable_entry_types
[] =
227 {0, 20, "Processor"},
234 static vm_paddr_t mptable_fps_phyaddr
;
235 static int mptable_use_default
;
236 static TAILQ_HEAD(mptable_pci_int_list
, mptable_pci_int
) mptable_pci_int_list
=
237 TAILQ_HEAD_INITIALIZER(mptable_pci_int_list
);
238 static TAILQ_HEAD(mptable_ioapic_list
, mptable_ioapic
) mptable_ioapic_list
=
239 TAILQ_HEAD_INITIALIZER(mptable_ioapic_list
);
244 struct mptable_pos mpt
;
247 KKASSERT(mptable_fps_phyaddr
== 0);
249 mptable_fps_phyaddr
= mptable_search();
250 if (mptable_fps_phyaddr
== 0)
253 error
= mptable_map(&mpt
);
255 mptable_fps_phyaddr
= 0;
259 if (MPTABLE_POS_USE_DEFAULT(&mpt
)) {
260 kprintf("MPTABLE: use default configuration\n");
261 mptable_use_default
= 1;
263 if (mpt
.mp_fps
->mpfb2
& 0x80)
268 SYSINIT(mptable_probe
, SI_BOOT2_PRESMP
, SI_ORDER_FIRST
, mptable_probe
, 0);
271 * Look for an Intel MP spec table (ie, SMP capable hardware).
279 /* see if EBDA exists */
280 if (ebda_addr
!= 0) {
281 /* search first 1K of EBDA */
282 target
= (u_int32_t
)ebda_addr
;
283 if ((x
= mptable_search_sig(target
, 1024 / 4)) > 0)
286 /* last 1K of base memory, effective 'top of base' passed in */
287 target
= (u_int32_t
)(base_memory
- 0x400);
288 if ((x
= mptable_search_sig(target
, 1024 / 4)) > 0)
292 /* search the BIOS */
293 target
= (u_int32_t
)BIOS_BASE
;
294 if ((x
= mptable_search_sig(target
, BIOS_COUNT
)) > 0)
297 /* search the extended BIOS */
298 target
= (u_int32_t
)BIOS_BASE2
;
299 if ((x
= mptable_search_sig(target
, BIOS_COUNT
)) > 0)
307 mptable_iterate_entries(const mpcth_t cth
, mptable_iter_func func
, void *arg
)
309 int count
, total_size
;
310 const void *position
;
312 KKASSERT(cth
->base_table_length
>= sizeof(struct MPCTH
));
313 total_size
= cth
->base_table_length
- sizeof(struct MPCTH
);
314 position
= (const uint8_t *)cth
+ sizeof(struct MPCTH
);
315 count
= cth
->entry_count
;
320 KKASSERT(total_size
>= 0);
321 if (total_size
== 0) {
322 kprintf("invalid base MP table, "
323 "entry count and length mismatch\n");
327 type
= *(const uint8_t *)position
;
329 case 0: /* processor_entry */
330 case 1: /* bus_entry */
331 case 2: /* io_apic_entry */
332 case 3: /* int_entry */
333 case 4: /* int_entry */
336 kprintf("unknown base MP table entry type %d\n", type
);
340 if (total_size
< basetable_entry_types
[type
].length
) {
341 kprintf("invalid base MP table length, "
342 "does not contain all entries\n");
345 total_size
-= basetable_entry_types
[type
].length
;
347 error
= func(arg
, position
, type
);
351 position
= (const uint8_t *)position
+
352 basetable_entry_types
[type
].length
;
358 * look for the MP spec signature
361 /* string defined by the Intel MP Spec as identifying the MP table */
362 #define MP_SIG 0x5f504d5f /* _MP_ */
363 #define NEXT(X) ((X) += 4)
365 mptable_search_sig(u_int32_t target
, int count
)
371 KKASSERT(target
!= 0);
373 map_size
= count
* sizeof(u_int32_t
);
374 addr
= pmap_mapdev((vm_paddr_t
)target
, map_size
);
377 for (x
= 0; x
< count
; NEXT(x
)) {
378 if (addr
[x
] == MP_SIG
) {
379 /* make array index a byte index */
380 ret
= target
+ (x
* sizeof(u_int32_t
));
385 pmap_unmapdev((vm_offset_t
)addr
, map_size
);
389 static int processor_entry (const struct PROCENTRY
*entry
, int cpu
);
392 * Check if we should perform a hyperthreading "fix-up" to
393 * enumerate any logical CPU's that aren't already listed
396 * XXX: We assume that all of the physical CPUs in the
397 * system have the same number of logical CPUs.
399 * XXX: We assume that APIC ID's are allocated such that
400 * the APIC ID's for a physical processor are aligned
401 * with the number of logical CPU's in the processor.
404 mptable_hyperthread_fixup(cpumask_t id_mask
, int cpu_count
)
406 int i
, id
, lcpus_max
, logical_cpus
;
408 if ((cpu_feature
& CPUID_HTT
) == 0)
411 lcpus_max
= (cpu_procinfo
& CPUID_HTT_CORES
) >> 16;
415 if (cpu_vendor_id
== CPU_VENDOR_INTEL
) {
417 * INSTRUCTION SET REFERENCE, A-M (#253666)
418 * Page 3-181, Table 3-20
419 * "The nearest power-of-2 integer that is not smaller
420 * than EBX[23:16] is the number of unique initial APIC
421 * IDs reserved for addressing different logical
422 * processors in a physical package."
425 if ((1 << i
) >= lcpus_max
) {
432 KKASSERT(cpu_count
!= 0);
433 if (cpu_count
== lcpus_max
) {
434 /* We have nothing to fix */
436 } else if (cpu_count
== 1) {
437 /* XXX this may be incorrect */
438 logical_cpus
= lcpus_max
;
443 * Calculate the distances between two nearest
444 * APIC IDs. If all such distances are same,
445 * then it is the number of missing cpus that
446 * we are going to fill later.
448 dist
= cur
= prev
= -1;
449 for (id
= 0; id
< MAXCPU
; ++id
) {
450 if (CPUMASK_TESTBIT(id_mask
, id
) == 0)
455 int new_dist
= cur
- prev
;
461 * Make sure that all distances
462 * between two nearest APIC IDs
465 if (dist
!= new_dist
)
473 /* Must be power of 2 */
474 if (dist
& (dist
- 1))
477 /* Can't exceed CPU package capacity */
478 if (dist
> lcpus_max
)
479 logical_cpus
= lcpus_max
;
485 * For each APIC ID of a CPU that is set in the mask,
486 * scan the other candidate APIC ID's for this
487 * physical processor. If any of those ID's are
488 * already in the table, then kill the fixup.
490 for (id
= 0; id
< MAXCPU
; id
++) {
491 if (CPUMASK_TESTBIT(id_mask
, id
) == 0)
493 /* First, make sure we are on a logical_cpus boundary. */
494 if (id
% logical_cpus
!= 0)
496 for (i
= id
+ 1; i
< id
+ logical_cpus
; i
++)
497 if (CPUMASK_TESTBIT(id_mask
, i
) != 0)
504 mptable_map(struct mptable_pos
*mpt
)
508 vm_size_t cth_mapsz
= 0;
510 KKASSERT(mptable_fps_phyaddr
!= 0);
512 bzero(mpt
, sizeof(*mpt
));
514 fps
= pmap_mapdev(mptable_fps_phyaddr
, sizeof(*fps
));
517 * Map configuration table header to get
518 * the base table size
520 cth
= pmap_mapdev(fps
->pap
, sizeof(*cth
));
521 cth_mapsz
= cth
->base_table_length
;
522 pmap_unmapdev((vm_offset_t
)cth
, sizeof(*cth
));
524 if (cth_mapsz
< sizeof(*cth
)) {
525 kprintf("invalid base MP table length %d\n",
527 pmap_unmapdev((vm_offset_t
)fps
, sizeof(*fps
));
534 cth
= pmap_mapdev(fps
->pap
, cth_mapsz
);
539 mpt
->mp_cth_mapsz
= cth_mapsz
;
545 mptable_unmap(struct mptable_pos
*mpt
)
547 if (mpt
->mp_cth
!= NULL
) {
548 pmap_unmapdev((vm_offset_t
)mpt
->mp_cth
, mpt
->mp_cth_mapsz
);
550 mpt
->mp_cth_mapsz
= 0;
552 if (mpt
->mp_fps
!= NULL
) {
553 pmap_unmapdev((vm_offset_t
)mpt
->mp_fps
, sizeof(*mpt
->mp_fps
));
559 processor_entry(const struct PROCENTRY
*entry
, int cpu
)
563 /* check for usability */
564 if (!(entry
->cpu_flags
& PROCENTRY_FLAG_EN
))
567 /* check for BSP flag */
568 if (entry
->cpu_flags
& PROCENTRY_FLAG_BP
) {
569 lapic_set_cpuid(0, entry
->apic_id
);
570 return 0; /* its already been counted */
573 /* add another AP to list, if less than max number of CPUs */
574 else if (cpu
< MAXCPU
) {
575 lapic_set_cpuid(cpu
, entry
->apic_id
);
583 mptable_bus_info_callback(void *xarg
, const void *pos
, int type
)
585 struct mptable_bus_info
*bus_info
= xarg
;
586 const struct BUSENTRY
*ent
;
587 struct mptable_bus
*bus
;
593 TAILQ_FOREACH(bus
, &bus_info
->mbi_list
, mb_link
) {
594 if (bus
->mb_id
== ent
->bus_id
) {
595 kprintf("mptable_bus_info_alloc: duplicated bus id "
596 "(%d)\n", bus
->mb_id
);
602 if (strncmp(ent
->bus_type
, "PCI", 3) == 0) {
603 bus
= kmalloc(sizeof(*bus
), M_TEMP
, M_WAITOK
| M_ZERO
);
604 bus
->mb_type
= MPTABLE_BUS_PCI
;
605 } else if (strncmp(ent
->bus_type
, "ISA", 3) == 0) {
606 bus
= kmalloc(sizeof(*bus
), M_TEMP
, M_WAITOK
| M_ZERO
);
607 bus
->mb_type
= MPTABLE_BUS_ISA
;
611 bus
->mb_id
= ent
->bus_id
;
612 TAILQ_INSERT_TAIL(&bus_info
->mbi_list
, bus
, mb_link
);
618 mptable_bus_info_alloc(const mpcth_t cth
, struct mptable_bus_info
*bus_info
)
622 bzero(bus_info
, sizeof(*bus_info
));
623 TAILQ_INIT(&bus_info
->mbi_list
);
625 error
= mptable_iterate_entries(cth
, mptable_bus_info_callback
, bus_info
);
627 mptable_bus_info_free(bus_info
);
631 mptable_bus_info_free(struct mptable_bus_info
*bus_info
)
633 struct mptable_bus
*bus
;
635 while ((bus
= TAILQ_FIRST(&bus_info
->mbi_list
)) != NULL
) {
636 TAILQ_REMOVE(&bus_info
->mbi_list
, bus
, mb_link
);
641 struct mptable_lapic_cbarg1
{
644 u_int ht_apicid_mask
;
648 mptable_lapic_pass1_callback(void *xarg
, const void *pos
, int type
)
650 const struct PROCENTRY
*ent
;
651 struct mptable_lapic_cbarg1
*arg
= xarg
;
657 if ((ent
->cpu_flags
& PROCENTRY_FLAG_EN
) == 0)
661 if (ent
->apic_id
< 64) {
662 arg
->ht_apicid_mask
|= 1UL << ent
->apic_id
;
663 } else if (arg
->ht_fixup
) {
664 kprintf("MPTABLE: lapic id > 64, disable HTT fixup\n");
670 struct mptable_lapic_cbarg2
{
677 mptable_lapic_pass2_callback(void *xarg
, const void *pos
, int type
)
679 const struct PROCENTRY
*ent
;
680 struct mptable_lapic_cbarg2
*arg
= xarg
;
686 if (ent
->cpu_flags
& PROCENTRY_FLAG_BP
) {
687 KKASSERT(!arg
->found_bsp
);
691 if (processor_entry(ent
, arg
->cpu
))
694 if (arg
->logical_cpus
) {
695 struct PROCENTRY proc
;
699 * Create fake mptable processor entries
700 * and feed them to processor_entry() to
701 * enumerate the logical CPUs.
703 bzero(&proc
, sizeof(proc
));
705 proc
.cpu_flags
= (force_enable
) ? PROCENTRY_FLAG_EN
: ent
->cpu_flags
;
706 proc
.apic_id
= ent
->apic_id
;
708 for (i
= 1; i
< arg
->logical_cpus
; i
++) {
710 processor_entry(&proc
, arg
->cpu
);
718 mptable_lapic_default(void)
720 int ap_apicid
, bsp_apicid
;
722 naps
= 1; /* exclude BSP */
724 /* Map local apic before the id field is accessed */
725 lapic_map(DEFAULT_APIC_BASE
);
727 bsp_apicid
= LAPIC_READID
;
728 ap_apicid
= (bsp_apicid
== 0) ? 1 : 0;
731 lapic_set_cpuid(0, bsp_apicid
);
732 /* one and only AP */
733 lapic_set_cpuid(1, ap_apicid
);
739 * APIC ID <-> CPU ID mappings
742 mptable_lapic_enumerate(struct lapic_enumerator
*e
)
744 struct mptable_pos mpt
;
745 struct mptable_lapic_cbarg1 arg1
;
746 struct mptable_lapic_cbarg2 arg2
;
748 int error
, logical_cpus
= 0;
749 vm_paddr_t lapic_addr
;
751 if (mptable_use_default
) {
752 mptable_lapic_default();
756 error
= mptable_map(&mpt
);
758 panic("mptable_lapic_enumerate mptable_map failed");
759 KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt
));
763 /* Save local apic address */
764 lapic_addr
= cth
->apic_address
;
765 KKASSERT(lapic_addr
!= 0);
768 * Find out how many CPUs do we have
770 bzero(&arg1
, sizeof(arg1
));
771 arg1
.ht_fixup
= 1; /* Apply ht fixup by default */
773 error
= mptable_iterate_entries(cth
,
774 mptable_lapic_pass1_callback
, &arg1
);
776 panic("mptable_iterate_entries(lapic_pass1) failed");
777 KKASSERT(arg1
.cpu_count
!= 0);
779 /* See if we need to fixup HT logical CPUs. */
781 * XXX fixup for cpus >= 32 ? XXX
786 CPUMASK_ASSZERO(mask
);
787 mask
.ary
[0] = arg1
.ht_apicid_mask
;
788 logical_cpus
= mptable_hyperthread_fixup(mask
, arg1
.cpu_count
);
789 if (logical_cpus
!= 0)
790 arg1
.cpu_count
*= logical_cpus
;
792 naps
= arg1
.cpu_count
- 1; /* subtract the BSP */
795 * Link logical CPU id to local apic id
797 bzero(&arg2
, sizeof(arg2
));
799 arg2
.logical_cpus
= logical_cpus
;
801 error
= mptable_iterate_entries(cth
,
802 mptable_lapic_pass2_callback
, &arg2
);
804 panic("mptable_iterate_entries(lapic_pass2) failed");
805 KKASSERT(arg2
.found_bsp
);
808 lapic_map(lapic_addr
);
815 struct mptable_lapic_probe_cbarg
{
821 mptable_lapic_probe_callback(void *xarg
, const void *pos
, int type
)
823 const struct PROCENTRY
*ent
;
824 struct mptable_lapic_probe_cbarg
*arg
= xarg
;
830 if ((ent
->cpu_flags
& PROCENTRY_FLAG_EN
) == 0)
834 if (ent
->apic_id
== APICID_MAX
) {
835 kprintf("MPTABLE: invalid LAPIC apic id %d\n",
840 if (ent
->cpu_flags
& PROCENTRY_FLAG_BP
) {
841 if (arg
->found_bsp
) {
842 kprintf("more than one BSP in base MP table\n");
851 mptable_lapic_probe(struct lapic_enumerator
*e
)
853 struct mptable_pos mpt
;
854 struct mptable_lapic_probe_cbarg arg
;
858 if (mptable_fps_phyaddr
== 0)
861 if (mptable_use_default
)
864 error
= mptable_map(&mpt
);
867 KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt
));
872 if (cth
->apic_address
== 0)
875 bzero(&arg
, sizeof(arg
));
876 error
= mptable_iterate_entries(cth
,
877 mptable_lapic_probe_callback
, &arg
);
879 if (arg
.cpu_count
== 0) {
880 kprintf("MP table contains no processor entries\n");
882 } else if (!arg
.found_bsp
) {
883 kprintf("MP table does not contains BSP entry\n");
892 static struct lapic_enumerator mptable_lapic_enumerator
= {
893 .lapic_prio
= LAPIC_ENUM_PRIO_MPTABLE
,
894 .lapic_probe
= mptable_lapic_probe
,
895 .lapic_enumerate
= mptable_lapic_enumerate
899 mptable_lapic_enum_register(void)
901 lapic_enumerator_register(&mptable_lapic_enumerator
);
903 SYSINIT(mptable_lapic
, SI_BOOT2_PRESMP
, SI_ORDER_ANY
,
904 mptable_lapic_enum_register
, 0);
907 mptable_ioapic_list_callback(void *xarg
, const void *pos
, int type
)
909 const struct IOAPICENTRY
*ent
;
910 struct mptable_ioapic
*nioapic
, *ioapic
;
916 if ((ent
->apic_flags
& IOAPICENTRY_FLAG_EN
) == 0)
919 if (ent
->apic_address
== 0) {
920 kprintf("mptable_ioapic_create_list: zero IOAPIC addr\n");
923 if (ent
->apic_id
== APICID_MAX
) {
924 kprintf("mptable_ioapic_create_list: "
925 "invalid IOAPIC apic id %d\n", ent
->apic_id
);
929 TAILQ_FOREACH(ioapic
, &mptable_ioapic_list
, mio_link
) {
930 if (ioapic
->mio_apic_id
== ent
->apic_id
) {
931 kprintf("mptable_ioapic_create_list: duplicated "
932 "apic id %d\n", ioapic
->mio_apic_id
);
935 if (ioapic
->mio_addr
== ent
->apic_address
) {
936 kprintf("mptable_ioapic_create_list: overlapped "
937 "IOAPIC addr 0x%08x", ioapic
->mio_addr
);
942 nioapic
= kmalloc(sizeof(*nioapic
), M_DEVBUF
, M_WAITOK
| M_ZERO
);
943 nioapic
->mio_apic_id
= ent
->apic_id
;
944 nioapic
->mio_addr
= ent
->apic_address
;
947 * Create IOAPIC list in ascending order of APIC ID
949 TAILQ_FOREACH_REVERSE(ioapic
, &mptable_ioapic_list
,
950 mptable_ioapic_list
, mio_link
) {
951 if (nioapic
->mio_apic_id
> ioapic
->mio_apic_id
) {
952 TAILQ_INSERT_AFTER(&mptable_ioapic_list
,
953 ioapic
, nioapic
, mio_link
);
958 TAILQ_INSERT_HEAD(&mptable_ioapic_list
, nioapic
, mio_link
);
964 mptable_ioapic_create_list(void)
966 struct mptable_ioapic
*ioapic
;
967 struct mptable_pos mpt
;
970 if (mptable_fps_phyaddr
== 0)
973 if (mptable_use_default
) {
974 ioapic
= kmalloc(sizeof(*ioapic
), M_DEVBUF
, M_WAITOK
| M_ZERO
);
976 ioapic
->mio_apic_id
= 0; /* NOTE: any value is ok here */
977 ioapic
->mio_addr
= 0xfec00000; /* XXX magic number */
979 TAILQ_INSERT_HEAD(&mptable_ioapic_list
, ioapic
, mio_link
);
983 error
= mptable_map(&mpt
);
985 panic("mptable_ioapic_create_list: mptable_map failed");
986 KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt
));
988 error
= mptable_iterate_entries(mpt
.mp_cth
,
989 mptable_ioapic_list_callback
, NULL
);
991 while ((ioapic
= TAILQ_FIRST(&mptable_ioapic_list
)) != NULL
) {
992 TAILQ_REMOVE(&mptable_ioapic_list
, ioapic
, mio_link
);
993 kfree(ioapic
, M_DEVBUF
);
999 * Assign index number for each IOAPIC
1002 TAILQ_FOREACH(ioapic
, &mptable_ioapic_list
, mio_link
) {
1003 ioapic
->mio_idx
= idx
;
1007 mptable_unmap(&mpt
);
1009 SYSINIT(mptable_ioapic_list
, SI_BOOT2_PRESMP
, SI_ORDER_SECOND
,
1010 mptable_ioapic_create_list
, 0);
1013 mptable_pci_int_callback(void *xarg
, const void *pos
, int type
)
1015 const struct mptable_bus_info
*bus_info
= xarg
;
1016 const struct mptable_ioapic
*ioapic
;
1017 const struct mptable_bus
*bus
;
1018 struct mptable_pci_int
*pci_int
;
1019 const struct INTENTRY
*ent
;
1020 int pci_pin
, pci_dev
;
1026 if (ent
->int_type
!= 0)
1029 TAILQ_FOREACH(bus
, &bus_info
->mbi_list
, mb_link
) {
1030 if (bus
->mb_type
== MPTABLE_BUS_PCI
&&
1031 bus
->mb_id
== ent
->src_bus_id
)
1037 TAILQ_FOREACH(ioapic
, &mptable_ioapic_list
, mio_link
) {
1038 if (ioapic
->mio_apic_id
== ent
->dst_apic_id
)
1041 if (ioapic
== NULL
) {
1043 static char intdis_warned
[64];
1044 int apic_id
= ent
->dst_apic_id
;
1047 if (apic_id
< 0 || apic_id
>= sizeof(intdis_warned
)) {
1049 } else if (intdis_warned
[apic_id
] == 0) {
1050 intdis_warned
[apic_id
] = 1;
1054 kprintf("MPTABLE: warning PCI int dst apic id "
1055 "%d does not exist\n", apic_id
);
1061 pci_pin
= ent
->src_bus_irq
& 0x3;
1062 pci_dev
= (ent
->src_bus_irq
>> 2) & 0x1f;
1064 TAILQ_FOREACH(pci_int
, &mptable_pci_int_list
, mpci_link
) {
1065 if (pci_int
->mpci_bus
== ent
->src_bus_id
&&
1066 pci_int
->mpci_dev
== pci_dev
&&
1067 pci_int
->mpci_pin
== pci_pin
) {
1068 if (pci_int
->mpci_ioapic_idx
== ioapic
->mio_idx
&&
1069 pci_int
->mpci_ioapic_pin
== ent
->dst_apic_int
) {
1070 kprintf("MPTABLE: warning duplicated "
1071 "PCI int entry for "
1072 "bus %d, dev %d, pin %d\n",
1078 kprintf("mptable_pci_int_register: "
1079 "conflict PCI int entry for "
1080 "bus %d, dev %d, pin %d, "
1081 "IOAPIC %d.%d -> %d.%d\n",
1085 pci_int
->mpci_ioapic_idx
,
1086 pci_int
->mpci_ioapic_pin
,
1094 pci_int
= kmalloc(sizeof(*pci_int
), M_DEVBUF
, M_WAITOK
| M_ZERO
);
1096 pci_int
->mpci_bus
= ent
->src_bus_id
;
1097 pci_int
->mpci_dev
= pci_dev
;
1098 pci_int
->mpci_pin
= pci_pin
;
1099 pci_int
->mpci_ioapic_idx
= ioapic
->mio_idx
;
1100 pci_int
->mpci_ioapic_pin
= ent
->dst_apic_int
;
1102 TAILQ_INSERT_TAIL(&mptable_pci_int_list
, pci_int
, mpci_link
);
1108 mptable_pci_int_register(void)
1110 struct mptable_bus_info bus_info
;
1111 const struct mptable_bus
*bus
;
1112 struct mptable_pci_int
*pci_int
;
1113 struct mptable_pos mpt
;
1114 int error
, force_pci0
, npcibus
;
1117 if (mptable_fps_phyaddr
== 0)
1120 if (mptable_use_default
)
1123 if (TAILQ_EMPTY(&mptable_ioapic_list
))
1126 error
= mptable_map(&mpt
);
1128 panic("mptable_pci_int_register: mptable_map failed");
1129 KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt
));
1133 mptable_bus_info_alloc(cth
, &bus_info
);
1134 if (TAILQ_EMPTY(&bus_info
.mbi_list
))
1139 TAILQ_FOREACH(bus
, &bus_info
.mbi_list
, mb_link
) {
1140 if (bus
->mb_type
== MPTABLE_BUS_PCI
)
1144 mptable_bus_info_free(&bus_info
);
1146 } else if (npcibus
== 1) {
1150 error
= mptable_iterate_entries(cth
,
1151 mptable_pci_int_callback
, &bus_info
);
1153 mptable_bus_info_free(&bus_info
);
1156 while ((pci_int
= TAILQ_FIRST(&mptable_pci_int_list
)) != NULL
) {
1157 TAILQ_REMOVE(&mptable_pci_int_list
, pci_int
, mpci_link
);
1158 kfree(pci_int
, M_DEVBUF
);
1164 TAILQ_FOREACH(pci_int
, &mptable_pci_int_list
, mpci_link
)
1165 pci_int
->mpci_bus
= 0;
1168 mptable_unmap(&mpt
);
1170 SYSINIT(mptable_pci
, SI_BOOT2_PRESMP
, SI_ORDER_ANY
,
1171 mptable_pci_int_register
, 0);
1173 struct mptable_ioapic_probe_cbarg
{
1174 const struct mptable_bus_info
*bus_info
;
1178 mptable_ioapic_probe_callback(void *xarg
, const void *pos
, int type
)
1180 struct mptable_ioapic_probe_cbarg
*arg
= xarg
;
1181 const struct mptable_ioapic
*ioapic
;
1182 const struct mptable_bus
*bus
;
1183 const struct INTENTRY
*ent
;
1189 if (ent
->int_type
!= 0)
1192 TAILQ_FOREACH(bus
, &arg
->bus_info
->mbi_list
, mb_link
) {
1193 if (bus
->mb_type
== MPTABLE_BUS_ISA
&&
1194 bus
->mb_id
== ent
->src_bus_id
)
1200 TAILQ_FOREACH(ioapic
, &mptable_ioapic_list
, mio_link
) {
1201 if (ioapic
->mio_apic_id
== ent
->dst_apic_id
)
1204 if (ioapic
== NULL
) {
1205 kprintf("MPTABLE: warning ISA int dst apic id %d "
1206 "does not exist\n", ent
->dst_apic_id
);
1210 /* XXX magic number */
1211 if (ent
->src_bus_irq
>= ISA_IRQ_CNT
) {
1212 kprintf("mptable_ioapic_probe: invalid ISA irq (%d)\n",
1220 mptable_ioapic_probe(struct ioapic_enumerator
*e
)
1222 struct mptable_ioapic_probe_cbarg arg
;
1223 struct mptable_bus_info bus_info
;
1224 struct mptable_pos mpt
;
1228 if (mptable_fps_phyaddr
== 0)
1231 if (mptable_use_default
)
1234 if (TAILQ_EMPTY(&mptable_ioapic_list
))
1237 error
= mptable_map(&mpt
);
1239 panic("mptable_ioapic_probe: mptable_map failed");
1240 KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt
));
1244 mptable_bus_info_alloc(cth
, &bus_info
);
1246 bzero(&arg
, sizeof(arg
));
1247 arg
.bus_info
= &bus_info
;
1249 error
= mptable_iterate_entries(cth
,
1250 mptable_ioapic_probe_callback
, &arg
);
1252 mptable_bus_info_free(&bus_info
);
1253 mptable_unmap(&mpt
);
1258 struct mptable_ioapic_int_cbarg
{
1259 const struct mptable_bus_info
*bus_info
;
1264 mptable_ioapic_int_callback(void *xarg
, const void *pos
, int type
)
1266 struct mptable_ioapic_int_cbarg
*arg
= xarg
;
1267 const struct mptable_ioapic
*ioapic
;
1268 const struct mptable_bus
*bus
;
1269 const struct INTENTRY
*ent
;
1278 if (ent
->int_type
!= 0)
1281 TAILQ_FOREACH(bus
, &arg
->bus_info
->mbi_list
, mb_link
) {
1282 if (bus
->mb_type
== MPTABLE_BUS_ISA
&&
1283 bus
->mb_id
== ent
->src_bus_id
)
1289 TAILQ_FOREACH(ioapic
, &mptable_ioapic_list
, mio_link
) {
1290 if (ioapic
->mio_apic_id
== ent
->dst_apic_id
)
1293 if (ioapic
== NULL
) {
1294 kprintf("MPTABLE: warning ISA int dst apic id %d "
1295 "does not exist\n", ent
->dst_apic_id
);
1299 if (ent
->dst_apic_int
>= ioapic
->mio_npin
) {
1300 panic("mptable_ioapic_enumerate: invalid I/O APIC "
1301 "pin %d, should be < %d",
1302 ent
->dst_apic_int
, ioapic
->mio_npin
);
1304 gsi
= ioapic
->mio_gsi_base
+ ent
->dst_apic_int
;
1306 if (ent
->src_bus_irq
!= gsi
) {
1308 kprintf("MPTABLE: INTSRC irq %d -> GSI %d\n",
1309 ent
->src_bus_irq
, gsi
);
1311 ioapic_intsrc(ent
->src_bus_irq
, gsi
,
1312 INTR_TRIGGER_EDGE
, INTR_POLARITY_HIGH
);
1318 mptable_ioapic_enumerate(struct ioapic_enumerator
*e
)
1320 struct mptable_bus_info bus_info
;
1321 struct mptable_ioapic
*ioapic
;
1322 struct mptable_pos mpt
;
1326 KKASSERT(mptable_fps_phyaddr
!= 0);
1327 KKASSERT(!TAILQ_EMPTY(&mptable_ioapic_list
));
1329 TAILQ_FOREACH(ioapic
, &mptable_ioapic_list
, mio_link
) {
1330 const struct mptable_ioapic
*prev_ioapic
;
1334 addr
= ioapic_map(ioapic
->mio_addr
);
1336 ver
= ioapic_read(addr
, IOAPIC_VER
);
1337 ioapic
->mio_npin
= ((ver
& IOART_VER_MAXREDIR
)
1338 >> MAXREDIRSHIFT
) + 1;
1340 prev_ioapic
= TAILQ_PREV(ioapic
,
1341 mptable_ioapic_list
, mio_link
);
1342 if (prev_ioapic
== NULL
) {
1343 ioapic
->mio_gsi_base
= 0;
1345 ioapic
->mio_gsi_base
=
1346 prev_ioapic
->mio_gsi_base
+
1347 prev_ioapic
->mio_npin
;
1349 ioapic_add(addr
, ioapic
->mio_gsi_base
, ioapic
->mio_npin
);
1352 kprintf("MPTABLE: IOAPIC addr 0x%08x, "
1353 "apic id %d, idx %d, gsi base %d, npin %d\n",
1355 ioapic
->mio_apic_id
,
1357 ioapic
->mio_gsi_base
,
1362 if (mptable_use_default
) {
1364 kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 (default)\n");
1365 ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE
, INTR_POLARITY_HIGH
);
1369 error
= mptable_map(&mpt
);
1371 panic("mptable_ioapic_probe: mptable_map failed");
1372 KKASSERT(!MPTABLE_POS_USE_DEFAULT(&mpt
));
1376 mptable_bus_info_alloc(cth
, &bus_info
);
1378 if (TAILQ_EMPTY(&bus_info
.mbi_list
)) {
1380 kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 (no bus)\n");
1381 ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE
, INTR_POLARITY_HIGH
);
1383 struct mptable_ioapic_int_cbarg arg
;
1385 bzero(&arg
, sizeof(arg
));
1386 arg
.bus_info
= &bus_info
;
1388 error
= mptable_iterate_entries(cth
,
1389 mptable_ioapic_int_callback
, &arg
);
1391 panic("mptable_ioapic_int failed");
1393 if (arg
.ioapic_nint
== 0) {
1395 kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 "
1398 ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE
,
1399 INTR_POLARITY_HIGH
);
1403 mptable_bus_info_free(&bus_info
);
1405 mptable_unmap(&mpt
);
1408 static struct ioapic_enumerator mptable_ioapic_enumerator
= {
1409 .ioapic_prio
= IOAPIC_ENUM_PRIO_MPTABLE
,
1410 .ioapic_probe
= mptable_ioapic_probe
,
1411 .ioapic_enumerate
= mptable_ioapic_enumerate
1415 mptable_ioapic_enum_register(void)
1417 ioapic_enumerator_register(&mptable_ioapic_enumerator
);
1419 SYSINIT(mptable_ioapic
, SI_BOOT2_PRESMP
, SI_ORDER_ANY
,
1420 mptable_ioapic_enum_register
, 0);
1423 mptable_pci_int_dump(void)
1425 const struct mptable_pci_int
*pci_int
;
1430 TAILQ_FOREACH(pci_int
, &mptable_pci_int_list
, mpci_link
) {
1431 kprintf("MPTABLE: %d:%d INT%c -> IOAPIC %d.%d\n",
1434 pci_int
->mpci_pin
+ 'A',
1435 pci_int
->mpci_ioapic_idx
,
1436 pci_int
->mpci_ioapic_pin
);
1441 mptable_pci_int_route(int bus
, int dev
, int pin
, int intline
)
1443 const struct mptable_pci_int
*pci_int
;
1447 --pin
; /* zero based */
1449 TAILQ_FOREACH(pci_int
, &mptable_pci_int_list
, mpci_link
) {
1450 if (pci_int
->mpci_bus
== bus
&&
1451 pci_int
->mpci_dev
== dev
&&
1452 pci_int
->mpci_pin
== pin
)
1455 if (pci_int
!= NULL
) {
1458 gsi
= ioapic_gsi(pci_int
->mpci_ioapic_idx
,
1459 pci_int
->mpci_ioapic_pin
);
1461 irq
= machintr_legacy_intr_find_bygsi(gsi
,
1462 INTR_TRIGGER_LEVEL
, INTR_POLARITY_LOW
);
1466 if (irq
< 0 && intline
>= 0) {
1467 kprintf("MPTABLE: fixed interrupt routing "
1468 "for %d:%d INT%c\n", bus
, dev
, pin
+ 'A');
1469 irq
= machintr_legacy_intr_find(intline
,
1470 INTR_TRIGGER_LEVEL
, INTR_POLARITY_LOW
);
1473 if (irq
>= 0 && bootverbose
) {
1474 kprintf("MPTABLE: %d:%d INT%c routed to irq %d\n",
1475 bus
, dev
, pin
+ 'A', irq
);