From 512fb675374a84c17c1f5bfb3b2d4c68807f0fed Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Thu, 17 Mar 2011 15:48:53 +0800 Subject: [PATCH] ioapic: Save interrupt source override information --- sys/platform/pc32/apic/mpapic.c | 12 +++++++ sys/platform/pc32/i386/mp_machdep.c | 46 ++++++++++++++++++++++----- sys/platform/pc32/i386/mp_madt.c | 4 ++- sys/platform/pc32/include/smp.h | 1 + sys/platform/pc64/apic/mpapic.c | 12 +++++++ sys/platform/pc64/include/smp.h | 1 + sys/platform/pc64/x86_64/mp_machdep.c | 46 ++++++++++++++++++++++----- sys/platform/pc64/x86_64/mp_madt.c | 4 ++- 8 files changed, 108 insertions(+), 18 deletions(-) diff --git a/sys/platform/pc32/apic/mpapic.c b/sys/platform/pc32/apic/mpapic.c index a042c3984b..c81b36fdae 100644 --- a/sys/platform/pc32/apic/mpapic.c +++ b/sys/platform/pc32/apic/mpapic.c @@ -1184,3 +1184,15 @@ ioapic_add(void *addr, int gsi_base, int npin) if (info == NULL) TAILQ_INSERT_HEAD(&ioapic_conf.ioc_list, ninfo, io_link); } + +void +ioapic_intsrc(int irq, int gsi) +{ + KKASSERT(irq < 16); + if (ioapic_conf.ioc_intsrc[irq] != -1 && + ioapic_conf.ioc_intsrc[irq] != gsi) { + kprintf("IOAPIC: warning intsrc irq %d, gsi %d -> gsi %d\n", + irq, ioapic_conf.ioc_intsrc[irq], gsi); + } + ioapic_conf.ioc_intsrc[irq] = gsi; +} diff --git a/sys/platform/pc32/i386/mp_machdep.c b/sys/platform/pc32/i386/mp_machdep.c index cac270936d..bd9811a613 100644 --- a/sys/platform/pc32/i386/mp_machdep.c +++ b/sys/platform/pc32/i386/mp_machdep.c @@ -3570,6 +3570,7 @@ static int mptable_ioapic_int_callback(void *xarg, const void *pos, int type) { struct mptable_ioapic_int_cbarg *arg = xarg; + const struct mptable_ioapic *ioapic; const struct mptable_bus *bus; const struct INTENTRY *ent; @@ -3590,11 +3591,40 @@ mptable_ioapic_int_callback(void *xarg, const void *pos, int type) if (bus == NULL) return 0; - /* XXX rough estimation */ - if (ent->src_bus_irq != ent->dst_apic_int) { - if (bootverbose) { - kprintf("MPTABLE: INTSRC irq %d -> GSI %d\n", - ent->src_bus_irq, ent->dst_apic_int); + TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) { + if (ioapic->mio_apic_id == ent->dst_apic_id) + break; + } + if (ioapic == NULL) { + kprintf("MPTABLE: warning ISA int dst apic id %d " + "does not exist\n", ent->dst_apic_id); + return 0; + } + + if (!ioapic_use_old) { + int gsi; + + if (ent->dst_apic_int >= ioapic->mio_npin) { + panic("mptable_ioapic_enumerate: invalid I/O APIC " + "pin %d, should be < %d", + ent->dst_apic_int, ioapic->mio_npin); + } + gsi = ioapic->mio_gsi_base + ent->dst_apic_int; + + if (ent->src_bus_irq != gsi) { + if (bootverbose) { + kprintf("MPTABLE: INTSRC irq %d -> GSI %d\n", + ent->src_bus_irq, gsi); + } + ioapic_intsrc(ent->src_bus_irq, gsi); + } + } else { + /* XXX rough estimation */ + if (ent->src_bus_irq != ent->dst_apic_int) { + if (bootverbose) { + kprintf("MPTABLE: INTSRC irq %d -> GSI %d\n", + ent->src_bus_irq, ent->dst_apic_int); + } } } return 0; @@ -3650,7 +3680,7 @@ mptable_ioapic_enumerate(struct ioapic_enumerator *e) if (mptable_use_default) { if (bootverbose) kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 (default)\n"); - /* TODO default intsrc */ + ioapic_intsrc(0, 2); return; } @@ -3666,7 +3696,7 @@ mptable_ioapic_enumerate(struct ioapic_enumerator *e) if (TAILQ_EMPTY(&bus_info.mbi_list)) { if (bootverbose) kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 (no bus)\n"); - /* TODO default intsrc */ + ioapic_intsrc(0, 2); } else { struct mptable_ioapic_int_cbarg arg; @@ -3683,7 +3713,7 @@ mptable_ioapic_enumerate(struct ioapic_enumerator *e) kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 " "(no int)\n"); } - /* TODO default intsrc */ + ioapic_intsrc(0, 2); } } diff --git a/sys/platform/pc32/i386/mp_madt.c b/sys/platform/pc32/i386/mp_madt.c index 7154ab01f0..163f8a8827 100644 --- a/sys/platform/pc32/i386/mp_madt.c +++ b/sys/platform/pc32/i386/mp_madt.c @@ -840,11 +840,13 @@ madt_ioapic_enum_callback(void *xarg, const struct acpi_madt_ent *ent) const struct acpi_madt_intsrc *intsrc_ent; intsrc_ent = (const struct acpi_madt_intsrc *)ent; - if (intsrc_ent->mint_src == intsrc_ent->mint_gsi) + if (intsrc_ent->mint_src == intsrc_ent->mint_gsi || + intsrc_ent->mint_bus != MADT_INT_BUS_ISA) return 0; MADT_VPRINTF("INTSRC irq %d -> gsi %u\n", intsrc_ent->mint_src, intsrc_ent->mint_gsi); + ioapic_intsrc(intsrc_ent->mint_src, intsrc_ent->mint_gsi); } else if (ent->me_type == MADT_ENT_IOAPIC) { const struct acpi_madt_ioapic *ioapic_ent; diff --git a/sys/platform/pc32/include/smp.h b/sys/platform/pc32/include/smp.h index 4da1f13c39..bf6503aa81 100644 --- a/sys/platform/pc32/include/smp.h +++ b/sys/platform/pc32/include/smp.h @@ -160,6 +160,7 @@ void lapic_enumerator_register(struct lapic_enumerator *); void ioapic_config(void); void ioapic_enumerator_register(struct ioapic_enumerator *); void ioapic_add(void *, int, int); +void ioapic_intsrc(int, int); extern int apic_io_enable; extern int ioapic_use_old; diff --git a/sys/platform/pc64/apic/mpapic.c b/sys/platform/pc64/apic/mpapic.c index 1e4d374d44..50ef94bc77 100644 --- a/sys/platform/pc64/apic/mpapic.c +++ b/sys/platform/pc64/apic/mpapic.c @@ -1246,3 +1246,15 @@ ioapic_add(void *addr, int gsi_base, int npin) if (info == NULL) TAILQ_INSERT_HEAD(&ioapic_conf.ioc_list, ninfo, io_link); } + +void +ioapic_intsrc(int irq, int gsi) +{ + KKASSERT(irq < 16); + if (ioapic_conf.ioc_intsrc[irq] != -1 && + ioapic_conf.ioc_intsrc[irq] != gsi) { + kprintf("IOAPIC: warning intsrc irq %d, gsi %d -> gsi %d\n", + irq, ioapic_conf.ioc_intsrc[irq], gsi); + } + ioapic_conf.ioc_intsrc[irq] = gsi; +} diff --git a/sys/platform/pc64/include/smp.h b/sys/platform/pc64/include/smp.h index c2136b5b45..5a4d3b2128 100644 --- a/sys/platform/pc64/include/smp.h +++ b/sys/platform/pc64/include/smp.h @@ -171,6 +171,7 @@ void lapic_enumerator_register(struct lapic_enumerator *); void ioapic_config(void); void ioapic_enumerator_register(struct ioapic_enumerator *); void ioapic_add(void *, int, int); +void ioapic_intsrc(int, int); #if defined(READY) void clr_io_apic_mask24 (int, u_int32_t); diff --git a/sys/platform/pc64/x86_64/mp_machdep.c b/sys/platform/pc64/x86_64/mp_machdep.c index 3f469de7c7..e41ef75c28 100644 --- a/sys/platform/pc64/x86_64/mp_machdep.c +++ b/sys/platform/pc64/x86_64/mp_machdep.c @@ -3565,6 +3565,7 @@ static int mptable_ioapic_int_callback(void *xarg, const void *pos, int type) { struct mptable_ioapic_int_cbarg *arg = xarg; + const struct mptable_ioapic *ioapic; const struct mptable_bus *bus; const struct INTENTRY *ent; @@ -3585,11 +3586,40 @@ mptable_ioapic_int_callback(void *xarg, const void *pos, int type) if (bus == NULL) return 0; - /* XXX rough estimation */ - if (ent->src_bus_irq != ent->dst_apic_int) { - if (bootverbose) { - kprintf("MPTABLE: INTSRC irq %d -> GSI %d\n", - ent->src_bus_irq, ent->dst_apic_int); + TAILQ_FOREACH(ioapic, &mptable_ioapic_list, mio_link) { + if (ioapic->mio_apic_id == ent->dst_apic_id) + break; + } + if (ioapic == NULL) { + kprintf("MPTABLE: warning ISA int dst apic id %d " + "does not exist\n", ent->dst_apic_id); + return 0; + } + + if (!ioapic_use_old) { + int gsi; + + if (ent->dst_apic_int >= ioapic->mio_npin) { + panic("mptable_ioapic_enumerate: invalid I/O APIC " + "pin %d, should be < %d", + ent->dst_apic_int, ioapic->mio_npin); + } + gsi = ioapic->mio_gsi_base + ent->dst_apic_int; + + if (ent->src_bus_irq != gsi) { + if (bootverbose) { + kprintf("MPTABLE: INTSRC irq %d -> GSI %d\n", + ent->src_bus_irq, gsi); + } + ioapic_intsrc(ent->src_bus_irq, gsi); + } + } else { + /* XXX rough estimation */ + if (ent->src_bus_irq != ent->dst_apic_int) { + if (bootverbose) { + kprintf("MPTABLE: INTSRC irq %d -> GSI %d\n", + ent->src_bus_irq, ent->dst_apic_int); + } } } return 0; @@ -3645,7 +3675,7 @@ mptable_ioapic_enumerate(struct ioapic_enumerator *e) if (mptable_use_default) { if (bootverbose) kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 (default)\n"); - /* TODO default intsrc */ + ioapic_intsrc(0, 2); return; } @@ -3661,7 +3691,7 @@ mptable_ioapic_enumerate(struct ioapic_enumerator *e) if (TAILQ_EMPTY(&bus_info.mbi_list)) { if (bootverbose) kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 (no bus)\n"); - /* TODO default intsrc */ + ioapic_intsrc(0, 2); } else { struct mptable_ioapic_int_cbarg arg; @@ -3678,7 +3708,7 @@ mptable_ioapic_enumerate(struct ioapic_enumerator *e) kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 " "(no int)\n"); } - /* TODO default intsrc */ + ioapic_intsrc(0, 2); } } diff --git a/sys/platform/pc64/x86_64/mp_madt.c b/sys/platform/pc64/x86_64/mp_madt.c index 2c8b8aa17f..c784a45698 100644 --- a/sys/platform/pc64/x86_64/mp_madt.c +++ b/sys/platform/pc64/x86_64/mp_madt.c @@ -839,11 +839,13 @@ madt_ioapic_enum_callback(void *xarg, const struct acpi_madt_ent *ent) const struct acpi_madt_intsrc *intsrc_ent; intsrc_ent = (const struct acpi_madt_intsrc *)ent; - if (intsrc_ent->mint_src == intsrc_ent->mint_gsi) + if (intsrc_ent->mint_src == intsrc_ent->mint_gsi || + intsrc_ent->mint_bus != MADT_INT_BUS_ISA) return 0; MADT_VPRINTF("INTSRC irq %d -> gsi %u\n", intsrc_ent->mint_src, intsrc_ent->mint_gsi); + ioapic_intsrc(intsrc_ent->mint_src, intsrc_ent->mint_gsi); } else if (ent->me_type == MADT_ENT_IOAPIC) { const struct acpi_madt_ioapic *ioapic_ent; -- 2.41.0