summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/apic_64.c24
-rw-r--r--arch/x86/kernel/mpparse_64.c89
-rw-r--r--include/asm-x86/apic.h1
-rw-r--r--include/asm-x86/mpspec.h3
4 files changed, 94 insertions, 23 deletions
diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c
index f6eb01d8923a..8a475793f736 100644
--- a/arch/x86/kernel/apic_64.c
+++ b/arch/x86/kernel/apic_64.c
@@ -861,6 +861,30 @@ static int __init detect_init_APIC(void)
return 0;
}
+void __init early_init_lapic_mapping(void)
+{
+ unsigned long apic_phys;
+
+ /*
+ * If no local APIC can be found then go out
+ * : it means there is no mpatable and MADT
+ */
+ if (!smp_found_config)
+ return;
+
+ apic_phys = mp_lapic_addr;
+
+ set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
+ apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
+ APIC_BASE, apic_phys);
+
+ /*
+ * Fetch the APIC ID of the BSP in case we have a
+ * default configuration (or the MP table is broken).
+ */
+ boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
+}
+
/**
* init_apic_mappings - initialize APIC mappings
*/
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
-------------------------------------------------------------------------- */
diff --git a/include/asm-x86/apic.h b/include/asm-x86/apic.h
index f0321a427e16..db5f7501aed6 100644
--- a/include/asm-x86/apic.h
+++ b/include/asm-x86/apic.h
@@ -129,6 +129,7 @@ extern void enable_NMI_through_LVT0(void);
*/
#ifdef CONFIG_X86_64
extern void setup_apic_routing(void);
+extern void early_init_lapic_mapping(void);
#endif
extern u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask);
diff --git a/include/asm-x86/mpspec.h b/include/asm-x86/mpspec.h
index dbd63f8d4750..982550bef2cd 100644
--- a/include/asm-x86/mpspec.h
+++ b/include/asm-x86/mpspec.h
@@ -25,6 +25,9 @@ extern int pic_mode;
extern DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
+extern void early_find_smp_config(void);
+extern void early_get_smp_config(void);
+
#endif
extern int mp_bus_id_to_pci_bus[MAX_MP_BUSSES];