From: Sepherosa Ziehau Date: Fri, 20 Jul 2012 02:59:08 +0000 (+0800) Subject: lapic: Allow lapic enumeration to fail X-Git-Tag: v3.2.0~559 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/f8ae04751efd0a7229e6043e0a3a78cc59a6aeb4 lapic: Allow lapic enumeration to fail 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 --- diff --git a/sys/platform/pc32/acpica5/acpi_madt.c b/sys/platform/pc32/acpica5/acpi_madt.c index 904614ec47..b7c3097ad4 100644 --- a/sys/platform/pc32/acpica5/acpi_madt.c +++ b/sys/platform/pc32/acpica5/acpi_madt.c @@ -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 = { diff --git a/sys/platform/pc32/apic/lapic.c b/sys/platform/pc32/apic/lapic.c index b9dd213d9f..174a8301e2 100644 --- a/sys/platform/pc32/apic/lapic.c +++ b/sys/platform/pc32/apic/lapic.c @@ -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); diff --git a/sys/platform/pc32/apic/lapic.h b/sys/platform/pc32/apic/lapic.h index 3d59556c22..cae676e0e4 100644 --- a/sys/platform/pc32/apic/lapic.h +++ b/sys/platform/pc32/apic/lapic.h @@ -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 diff --git a/sys/platform/pc32/i386/mptable.c b/sys/platform/pc32/i386/mptable.c index b017dede03..5076266789 100644 --- a/sys/platform/pc32/i386/mptable.c +++ b/sys/platform/pc32/i386/mptable.c @@ -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 { diff --git a/sys/platform/pc64/acpica5/acpi_madt.c b/sys/platform/pc64/acpica5/acpi_madt.c index e2c3d291d7..f1a71729a5 100644 --- a/sys/platform/pc64/acpica5/acpi_madt.c +++ b/sys/platform/pc64/acpica5/acpi_madt.c @@ -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 = { diff --git a/sys/platform/pc64/apic/lapic.c b/sys/platform/pc64/apic/lapic.c index 670025beab..af62d93a0b 100644 --- a/sys/platform/pc64/apic/lapic.c +++ b/sys/platform/pc64/apic/lapic.c @@ -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); diff --git a/sys/platform/pc64/apic/lapic.h b/sys/platform/pc64/apic/lapic.h index 23cf52cb91..69e67b06b0 100644 --- a/sys/platform/pc64/apic/lapic.h +++ b/sys/platform/pc64/apic/lapic.h @@ -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 diff --git a/sys/platform/pc64/x86_64/mptable.c b/sys/platform/pc64/x86_64/mptable.c index c11ef7e6ec..cddb58450a 100644 --- a/sys/platform/pc64/x86_64/mptable.c +++ b/sys/platform/pc64/x86_64/mptable.c @@ -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 {