diff options
author | Yinghai Lu <yinghai@kernel.org> | 2009-05-02 13:40:57 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-05-12 06:22:06 -0400 |
commit | 4797f6b021a3fa399942245d07a1feb30df81bb8 (patch) | |
tree | aea4f0aec80786f8e5b4d55c9140add997a9a348 /arch/x86/kernel/apic | |
parent | 6cda3eb62ef42aa5acd649bf99c8db544e0f4051 (diff) |
x86: read apic ID in the !acpi_lapic case
Ed found that on 32-bit, boot_cpu_physical_apicid is not read right,
when the mptable is broken.
Interestingly, actually three paths use/set it:
1. acpi: at that time that is already read from reg
2. mptable: only read from mptable
3. no madt, and no mptable, that use default apic id 0 for 64-bit, -1 for 32-bit
so we could read the apic id for the 2/3 path. We trust the hardware
register more than we trust a BIOS data structure (the mptable).
We can also avoid the double set_fixmap() when acpi_lapic
is used, and also need to move cpu_has_apic earlier and
call apic_disable().
Also when need to update the apic id, we'd better read and
set the apic version as well - so that quirks are applied precisely.
v2: make path 3 with 64bit, use -1 as apic id, so could read it later.
v3: fix whitespace problem pointed out by Ed Swierk
v5: fix boot crash
[ Impact: get correct apic id for bsp other than acpi path ]
Reported-by: Ed Swierk <eswierk@aristanetworks.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
LKML-Reference: <49FC85A9.2070702@kernel.org>
[ v4: sanity-check in the ACPI case too ]
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/apic')
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 46 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 5 |
2 files changed, 27 insertions, 24 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 07cffc1214cb..b0fd26442c41 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -242,17 +242,24 @@ static int modern_apic(void) | |||
242 | * bare function to substitute write operation | 242 | * bare function to substitute write operation |
243 | * and it's _that_ fast :) | 243 | * and it's _that_ fast :) |
244 | */ | 244 | */ |
245 | void native_apic_write_dummy(u32 reg, u32 v) | 245 | static void native_apic_write_dummy(u32 reg, u32 v) |
246 | { | 246 | { |
247 | WARN_ON_ONCE((cpu_has_apic || !disable_apic)); | 247 | WARN_ON_ONCE((cpu_has_apic || !disable_apic)); |
248 | } | 248 | } |
249 | 249 | ||
250 | static u32 native_apic_read_dummy(u32 reg) | ||
251 | { | ||
252 | WARN_ON_ONCE((cpu_has_apic || !disable_apic)); | ||
253 | return 0; | ||
254 | } | ||
255 | |||
250 | /* | 256 | /* |
251 | * right after this call apic->write doesn't do anything | 257 | * right after this call apic->write/read doesn't do anything |
252 | * note that there is no restore operation it works one way | 258 | * note that there is no restore operation it works one way |
253 | */ | 259 | */ |
254 | void apic_disable(void) | 260 | void apic_disable(void) |
255 | { | 261 | { |
262 | apic->read = native_apic_read_dummy; | ||
256 | apic->write = native_apic_write_dummy; | 263 | apic->write = native_apic_write_dummy; |
257 | } | 264 | } |
258 | 265 | ||
@@ -1576,32 +1583,23 @@ void __init init_apic_mappings(void) | |||
1576 | return; | 1583 | return; |
1577 | } | 1584 | } |
1578 | 1585 | ||
1579 | /* | 1586 | /* If no local APIC can be found return early */ |
1580 | * If no local APIC can be found then set up a fake all | ||
1581 | * zeroes page to simulate the local APIC and another | ||
1582 | * one for the IO-APIC. | ||
1583 | */ | ||
1584 | if (!smp_found_config && detect_init_APIC()) { | 1587 | if (!smp_found_config && detect_init_APIC()) { |
1585 | apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); | 1588 | /* lets NOP'ify apic operations */ |
1586 | apic_phys = __pa(apic_phys); | 1589 | pr_info("APIC: disable apic facility\n"); |
1587 | } else | 1590 | apic_disable(); |
1591 | } else { | ||
1588 | apic_phys = mp_lapic_addr; | 1592 | apic_phys = mp_lapic_addr; |
1589 | 1593 | ||
1590 | /* | 1594 | /* |
1591 | * acpi lapic path already maps that address in | 1595 | * acpi lapic path already maps that address in |
1592 | * acpi_register_lapic_address() | 1596 | * acpi_register_lapic_address() |
1593 | */ | 1597 | */ |
1594 | if (!acpi_lapic) | 1598 | if (!acpi_lapic) |
1595 | set_fixmap_nocache(FIX_APIC_BASE, apic_phys); | 1599 | set_fixmap_nocache(FIX_APIC_BASE, apic_phys); |
1596 | |||
1597 | apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n", | ||
1598 | APIC_BASE, apic_phys); | ||
1599 | 1600 | ||
1600 | /* lets check if we may NOP'ify apic operations */ | 1601 | apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n", |
1601 | if (!cpu_has_apic) { | 1602 | APIC_BASE, apic_phys); |
1602 | pr_info("APIC: disable apic facility\n"); | ||
1603 | apic_disable(); | ||
1604 | return; | ||
1605 | } | 1603 | } |
1606 | 1604 | ||
1607 | /* | 1605 | /* |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 1f3d3669dae8..74d2b480a20b 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -1878,6 +1878,11 @@ __apicdebuginit(void) print_PIC(void) | |||
1878 | __apicdebuginit(int) print_all_ICs(void) | 1878 | __apicdebuginit(int) print_all_ICs(void) |
1879 | { | 1879 | { |
1880 | print_PIC(); | 1880 | print_PIC(); |
1881 | |||
1882 | /* don't print out if apic is not there */ | ||
1883 | if (!cpu_has_apic || disable_apic) | ||
1884 | return 0; | ||
1885 | |||
1881 | print_all_local_APICs(); | 1886 | print_all_local_APICs(); |
1882 | print_IO_APIC(); | 1887 | print_IO_APIC(); |
1883 | 1888 | ||