From: Sepherosa Ziehau Date: Sun, 15 May 2011 07:21:11 +0000 (+0800) Subject: i386: Handle I/O APIC probing failure X-Git-Tag: v2.12.0~609 X-Git-Url: https://gitweb.dragonflybsd.org/~nant/dragonfly.git/commitdiff_plain/0bccf4f58edd59054bb036701eb5eabf8faf3a6e i386: Handle I/O APIC probing failure --- diff --git a/sys/platform/pc32/apic/ioapic.c b/sys/platform/pc32/apic/ioapic.c index ce0658d90b..e5ee1cc09c 100644 --- a/sys/platform/pc32/apic/ioapic.c +++ b/sys/platform/pc32/apic/ioapic.c @@ -86,13 +86,13 @@ static struct ioapic_conf ioapic_conf; static TAILQ_HEAD(, ioapic_enumerator) ioapic_enumerators = TAILQ_HEAD_INITIALIZER(ioapic_enumerators); -void +int ioapic_config(void) { struct ioapic_info *info; int start_apic_id = 0; struct ioapic_enumerator *e; - int error, i; + int error, i, probe; u_long ef = 0; TAILQ_INIT(&ioapic_conf.ioc_list); @@ -100,18 +100,21 @@ ioapic_config(void) for (i = 0; i < 16; ++i) ioapic_conf.ioc_intsrc[i].int_gsi = -1; + probe = 1; + TUNABLE_INT_FETCH("hw.ioapic_probe", &probe); + if (!probe) { + kprintf("IOAPIC: warning I/O APIC will not be probed\n"); + return ENXIO; + } + TAILQ_FOREACH(e, &ioapic_enumerators, ioapic_link) { error = e->ioapic_probe(e); if (!error) break; } if (e == NULL) { -#ifdef notyet - panic("can't config I/O APIC\n"); -#else - kprintf("no I/O APIC\n"); - return; -#endif + kprintf("IOAPIC: can't find I/O APIC\n"); + return ENXIO; } crit_enter(); @@ -208,6 +211,8 @@ ioapic_config(void) MachIntrABI.cleanup(); crit_exit(); + + return 0; } void diff --git a/sys/platform/pc32/apic/ioapic.h b/sys/platform/pc32/apic/ioapic.h index f99df805b3..7b537680fb 100644 --- a/sys/platform/pc32/apic/ioapic.h +++ b/sys/platform/pc32/apic/ioapic.h @@ -50,7 +50,7 @@ struct ioapic_enumerator { #define IOAPIC_ENUM_PRIO_MPTABLE 20 #define IOAPIC_ENUM_PRIO_MADT 40 -void ioapic_config(void); +int ioapic_config(void); void ioapic_enumerator_register(struct ioapic_enumerator *); void ioapic_add(void *, int, int); void ioapic_intsrc(int, int, enum intr_trigger, enum intr_polarity); diff --git a/sys/platform/pc32/apic/lapic.c b/sys/platform/pc32/apic/lapic.c index b40542fdd2..b61041f18d 100644 --- a/sys/platform/pc32/apic/lapic.c +++ b/sys/platform/pc32/apic/lapic.c @@ -697,3 +697,21 @@ lapic_set_cpuid(int cpu_id, int apic_id) CPUID_TO_APICID(cpu_id) = apic_id; APICID_TO_CPUID(apic_id) = cpu_id; } + +void +lapic_fixup_noioapic(void) +{ + u_int temp; + + /* Only allowed on BSP */ + KKASSERT(mycpuid == 0); + KKASSERT(!apic_io_enable); + + temp = lapic->lvt_lint0; + temp &= ~APIC_LVT_MASKED; + lapic->lvt_lint0 = temp; + + temp = lapic->lvt_lint1; + temp |= APIC_LVT_MASKED; + lapic->lvt_lint1 = temp; +} diff --git a/sys/platform/pc32/apic/lapic.h b/sys/platform/pc32/apic/lapic.h index 4b96bf02d4..abe5ba0c95 100644 --- a/sys/platform/pc32/apic/lapic.h +++ b/sys/platform/pc32/apic/lapic.h @@ -86,5 +86,6 @@ all_but_self_ipi(int vector) void lapic_map(vm_offset_t /* XXX should be vm_paddr_t */); int lapic_unused_apic_id(int); +void lapic_fixup_noioapic(void); #endif /* _ARCH_APIC_LAPIC_H_ */ diff --git a/sys/platform/pc32/i386/mp_machdep.c b/sys/platform/pc32/i386/mp_machdep.c index b775d7ef03..eba5087602 100644 --- a/sys/platform/pc32/i386/mp_machdep.c +++ b/sys/platform/pc32/i386/mp_machdep.c @@ -335,8 +335,14 @@ mp_enable(u_int boot_addr) /* start each Application Processor */ start_all_aps(boot_addr); - if (apic_io_enable) - ioapic_config(); + if (apic_io_enable) { + error = ioapic_config(); + if (error) { + apic_io_enable = 0; + icu_reinit_noioapic(); + lapic_fixup_noioapic(); + } + } } /*