lapic: Allow lapic enumeration to fail
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 20 Jul 2012 02:59:08 +0000 (10:59 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 20 Jul 2012 02:59:08 +0000 (10:59 +0800)
It is mainly used to workaround for some old brain dead BIOS, which
will set BSP's LAPIC apic id to 255, but all MADT LAPIC entries are
valid

Reported-by: klanger on #dragonflybsd
sys/platform/pc32/acpica5/acpi_madt.c
sys/platform/pc32/apic/lapic.c
sys/platform/pc32/apic/lapic.h
sys/platform/pc32/i386/mptable.c
sys/platform/pc64/acpica5/acpi_madt.c
sys/platform/pc64/apic/lapic.c
sys/platform/pc64/apic/lapic.h
sys/platform/pc64/x86_64/mptable.c

index 904614e..b7c3097 100644 (file)
@@ -132,7 +132,7 @@ static int                  madt_iterate_entries(struct acpi_madt *,
 static vm_paddr_t              madt_lapic_pass1(void);
 static int                     madt_lapic_pass2(int);
 
-static void                    madt_lapic_enumerate(struct lapic_enumerator *);
+static int                     madt_lapic_enumerate(struct lapic_enumerator *);
 static int                     madt_lapic_probe(struct lapic_enumerator *);
 
 static void                    madt_ioapic_enumerate(
@@ -449,7 +449,7 @@ madt_lapic_probe(struct lapic_enumerator *e)
        return error;
 }
 
-static void
+static int
 madt_lapic_enumerate(struct lapic_enumerator *e)
 {
        vm_paddr_t lapic_addr;
@@ -464,8 +464,21 @@ madt_lapic_enumerate(struct lapic_enumerator *e)
        lapic_map(lapic_addr);
 
        bsp_apic_id = APIC_ID(lapic->id);
+       if (bsp_apic_id == APICID_MAX) {
+               /*
+                * XXX
+                * Some old brain dead BIOS will set BSP's LAPIC apic id
+                * to 255, though all LAPIC entries in MADT are valid.
+                */
+               kprintf("%s invalid BSP LAPIC apic id %d\n", __func__,
+                   bsp_apic_id);
+               return EINVAL;
+       }
+
        if (madt_lapic_pass2(bsp_apic_id))
                panic("madt_lapic_enumerate: madt_lapic_pass2 failed");
+
+       return 0;
 }
 
 static struct lapic_enumerator madt_lapic_enumerator = {
index b9dd213..174a830 100644 (file)
@@ -708,7 +708,11 @@ lapic_config(void)
                return ENXIO;
        }
 
-       e->lapic_enumerate(e);
+       error = e->lapic_enumerate(e);
+       if (error) {
+               kprintf("LAPIC: enumeration failed\n");
+               return ENXIO;
+       }
 
        ap_max = MAXCPU - 1;
        TUNABLE_INT_FETCH("hw.ap_max", &ap_max);
index 3d59556..cae676e 100644 (file)
@@ -45,7 +45,7 @@ struct lapic_enumerator {
        int     lapic_prio;
        TAILQ_ENTRY(lapic_enumerator) lapic_link;
        int     (*lapic_probe)(struct lapic_enumerator *);
-       void    (*lapic_enumerate)(struct lapic_enumerator *);
+       int     (*lapic_enumerate)(struct lapic_enumerator *);
 };
 
 #define LAPIC_ENUM_PRIO_MPTABLE                20
index b017ded..5076266 100644 (file)
@@ -215,7 +215,7 @@ static void mptable_bus_info_alloc(const mpcth_t,
 static void    mptable_bus_info_free(struct mptable_bus_info *);
 
 static int     mptable_lapic_probe(struct lapic_enumerator *);
-static void    mptable_lapic_enumerate(struct lapic_enumerator *);
+static int     mptable_lapic_enumerate(struct lapic_enumerator *);
 static void    mptable_lapic_default(void);
 
 static int     mptable_ioapic_probe(struct ioapic_enumerator *);
@@ -737,7 +737,7 @@ mptable_lapic_default(void)
  *     naps
  *     APIC ID <-> CPU ID mappings
  */
-static void
+static int
 mptable_lapic_enumerate(struct lapic_enumerator *e)
 {
        struct mptable_pos mpt;
@@ -749,7 +749,7 @@ mptable_lapic_enumerate(struct lapic_enumerator *e)
 
        if (mptable_use_default) {
                mptable_lapic_default();
-               return;
+               return 0;
        }
 
        error = mptable_map(&mpt);
@@ -801,6 +801,8 @@ mptable_lapic_enumerate(struct lapic_enumerator *e)
        lapic_map(lapic_addr);
 
        mptable_unmap(&mpt);
+
+       return 0;
 }
 
 struct mptable_lapic_probe_cbarg {
index e2c3d29..f1a7172 100644 (file)
@@ -132,7 +132,7 @@ static int                  madt_iterate_entries(struct acpi_madt *,
 static vm_paddr_t              madt_lapic_pass1(void);
 static int                     madt_lapic_pass2(int);
 
-static void                    madt_lapic_enumerate(struct lapic_enumerator *);
+static int                     madt_lapic_enumerate(struct lapic_enumerator *);
 static int                     madt_lapic_probe(struct lapic_enumerator *);
 
 static void                    madt_ioapic_enumerate(
@@ -449,7 +449,7 @@ madt_lapic_probe(struct lapic_enumerator *e)
        return error;
 }
 
-static void
+static int
 madt_lapic_enumerate(struct lapic_enumerator *e)
 {
        vm_paddr_t lapic_addr;
@@ -464,8 +464,21 @@ madt_lapic_enumerate(struct lapic_enumerator *e)
        lapic_map(lapic_addr);
 
        bsp_apic_id = APIC_ID(lapic->id);
+       if (bsp_apic_id == APICID_MAX) {
+               /*
+                * XXX
+                * Some old brain dead BIOS will set BSP's LAPIC apic id
+                * to 255, though all LAPIC entries in MADT are valid.
+                */
+               kprintf("%s invalid BSP LAPIC apic id %d\n", __func__,
+                   bsp_apic_id);
+               return EINVAL;
+       }
+
        if (madt_lapic_pass2(bsp_apic_id))
                panic("madt_lapic_enumerate: madt_lapic_pass2 failed");
+
+       return 0;
 }
 
 static struct lapic_enumerator madt_lapic_enumerator = {
index 670025b..af62d93 100644 (file)
@@ -769,7 +769,11 @@ lapic_config(void)
                return ENXIO;
        }
 
-       e->lapic_enumerate(e);
+       error = e->lapic_enumerate(e);
+       if (error) {
+               kprintf("LAPIC: enumeration failed\n");
+               return ENXIO;
+       }
 
        ap_max = MAXCPU - 1;
        TUNABLE_INT_FETCH("hw.ap_max", &ap_max);
index 23cf52c..69e67b0 100644 (file)
@@ -46,7 +46,7 @@ struct lapic_enumerator {
        int     lapic_prio;
        TAILQ_ENTRY(lapic_enumerator) lapic_link;
        int     (*lapic_probe)(struct lapic_enumerator *);
-       void    (*lapic_enumerate)(struct lapic_enumerator *);
+       int     (*lapic_enumerate)(struct lapic_enumerator *);
 };
 
 #define LAPIC_ENUM_PRIO_MPTABLE                20
index c11ef7e..cddb584 100644 (file)
@@ -216,7 +216,7 @@ static void mptable_bus_info_alloc(const mpcth_t,
 static void    mptable_bus_info_free(struct mptable_bus_info *);
 
 static int     mptable_lapic_probe(struct lapic_enumerator *);
-static void    mptable_lapic_enumerate(struct lapic_enumerator *);
+static int     mptable_lapic_enumerate(struct lapic_enumerator *);
 static void    mptable_lapic_default(void);
 
 static int     mptable_ioapic_probe(struct ioapic_enumerator *);
@@ -738,7 +738,7 @@ mptable_lapic_default(void)
  *     naps
  *     APIC ID <-> CPU ID mappings
  */
-static void
+static int
 mptable_lapic_enumerate(struct lapic_enumerator *e)
 {
        struct mptable_pos mpt;
@@ -750,7 +750,7 @@ mptable_lapic_enumerate(struct lapic_enumerator *e)
 
        if (mptable_use_default) {
                mptable_lapic_default();
-               return;
+               return 0;
        }
  
        error = mptable_map(&mpt);
@@ -802,6 +802,8 @@ mptable_lapic_enumerate(struct lapic_enumerator *e)
        lapic_map(lapic_addr);
 
        mptable_unmap(&mpt);
+
+       return 0;
 }
 
 struct mptable_lapic_probe_cbarg {