i386: Handle I/O APIC probing failure
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Sun, 15 May 2011 07:21:11 +0000 (15:21 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Sun, 15 May 2011 07:21:11 +0000 (15:21 +0800)
sys/platform/pc32/apic/ioapic.c
sys/platform/pc32/apic/ioapic.h
sys/platform/pc32/apic/lapic.c
sys/platform/pc32/apic/lapic.h
sys/platform/pc32/i386/mp_machdep.c

index ce0658d..e5ee1cc 100644 (file)
@@ -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
index f99df80..7b53768 100644 (file)
@@ -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);
index b40542f..b61041f 100644 (file)
@@ -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;
+}
index 4b96bf0..abe5ba0 100644 (file)
@@ -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_ */
index b775d7e..eba5087 100644 (file)
@@ -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();
+               }
+       }
 }
 
 /*