diff options
Diffstat (limited to 'arch/x86/kernel/mpparse_64.c')
-rw-r--r-- | arch/x86/kernel/mpparse_64.c | 89 |
1 files changed, 66 insertions, 23 deletions
diff --git a/arch/x86/kernel/mpparse_64.c b/arch/x86/kernel/mpparse_64.c index 2a1f7881c75b..529b1c22077e 100644 --- a/arch/x86/kernel/mpparse_64.c +++ b/arch/x86/kernel/mpparse_64.c @@ -224,8 +224,7 @@ static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m) /* * Read/parse the MPC */ - -static int __init smp_read_mpc(struct mp_config_table *mpc) +static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early) { char str[16]; int count=sizeof(*mpc); @@ -266,6 +265,9 @@ static int __init smp_read_mpc(struct mp_config_table *mpc) if (!acpi_lapic) mp_lapic_addr = mpc->mpc_lapic; + if (early) + return 1; + /* * Now process the configuration blocks. */ @@ -477,27 +479,38 @@ static struct intel_mp_floating *mpf_found; /* * Scan the memory blocks for an SMP configuration block. */ -void __init get_smp_config (void) +static void __init __get_smp_config(unsigned early) { struct intel_mp_floating *mpf = mpf_found; + if (acpi_lapic && early) + return; /* - * ACPI supports both logical (e.g. Hyper-Threading) and physical - * processors, where MPS only supports physical. - */ - if (acpi_lapic && acpi_ioapic) { - printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n"); - return; - } - else if (acpi_lapic) - printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n"); + * ACPI supports both logical (e.g. Hyper-Threading) and physical + * processors, where MPS only supports physical. + */ + if (acpi_lapic && acpi_ioapic) { + printk(KERN_INFO "Using ACPI (MADT) for SMP configuration " + "information\n"); + return; + } else if (acpi_lapic) + printk(KERN_INFO "Using ACPI for processor (LAPIC) " + "configuration information\n"); - printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification); + printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n", + mpf->mpf_specification); /* * Now see if we need to read further. */ if (mpf->mpf_feature1 != 0) { + if (early) { + /* + * local APIC has default address + */ + mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; + return; + } printk(KERN_INFO "Default MP configuration #%d\n", mpf->mpf_feature1); construct_default_ISA_mptable(mpf->mpf_feature1); @@ -508,12 +521,15 @@ void __init get_smp_config (void) * Read the physical hardware table. Anything here will * override the defaults. */ - if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr))) { + if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr), early)) { smp_found_config = 0; printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"); printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n"); return; } + + if (early) + return; /* * If there are no explicit MP IRQ entries, then we are * broken. We set up most of the low 16 IO-APIC pins to @@ -535,13 +551,25 @@ void __init get_smp_config (void) } else BUG(); - printk(KERN_INFO "Processors: %d\n", num_processors); + if (!early) + printk(KERN_INFO "Processors: %d\n", num_processors); /* * Only use the first configuration found. */ } -static int __init smp_scan_config (unsigned long base, unsigned long length) +void __init early_get_smp_config(void) +{ + __get_smp_config(1); +} + +void __init get_smp_config(void) +{ + __get_smp_config(0); +} + +static int __init smp_scan_config(unsigned long base, unsigned long length, + unsigned reserve) { extern void __bad_mpf_size(void); unsigned int *bp = phys_to_virt(base); @@ -560,10 +588,15 @@ static int __init smp_scan_config (unsigned long base, unsigned long length) || (mpf->mpf_specification == 4)) ) { smp_found_config = 1; + mpf_found = mpf; + + if (!reserve) + return 1; + reserve_bootmem_generic(virt_to_phys(mpf), PAGE_SIZE); if (mpf->mpf_physptr) - reserve_bootmem_generic(mpf->mpf_physptr, PAGE_SIZE); - mpf_found = mpf; + reserve_bootmem_generic(mpf->mpf_physptr, + PAGE_SIZE); return 1; } bp += 4; @@ -572,7 +605,7 @@ static int __init smp_scan_config (unsigned long base, unsigned long length) return 0; } -void __init find_smp_config(void) +static void __init __find_smp_config(unsigned reserve) { unsigned int address; @@ -584,9 +617,9 @@ void __init find_smp_config(void) * 2) Scan the top 1K of base RAM * 3) Scan the 64K of bios */ - if (smp_scan_config(0x0,0x400) || - smp_scan_config(639*0x400,0x400) || - smp_scan_config(0xF0000,0x10000)) + if (smp_scan_config(0x0, 0x400, reserve) || + smp_scan_config(639*0x400, 0x400, reserve) || + smp_scan_config(0xF0000, 0x10000, reserve)) return; /* * If it is an SMP machine we should know now. @@ -603,13 +636,23 @@ void __init find_smp_config(void) address = *(unsigned short *)phys_to_virt(0x40E); address <<= 4; - if (smp_scan_config(address, 0x1000)) + if (smp_scan_config(address, 0x1000, reserve)) return; /* If we have come this far, we did not find an MP table */ printk(KERN_INFO "No mptable found.\n"); } +void __init early_find_smp_config(void) +{ + __find_smp_config(0); +} + +void __init find_smp_config(void) +{ + __find_smp_config(1); +} + /* -------------------------------------------------------------------------- ACPI-based MP Configuration -------------------------------------------------------------------------- */ |