acpi: get boot_cpu_id as early for k8_scan_nodes
authorYinghai Lu <Yinghai.Lu@Sun.COM>
Tue, 19 Feb 2008 11:21:06 +0000 (03:21 -0800)
committerIngo Molnar <mingo@elte.hu>
Sat, 26 Apr 2008 21:41:04 +0000 (23:41 +0200)
[mingo@elte.hu: split from "x86_64: get boot_cpu_id as early for k8_scan_nodes]

Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
arch/x86/kernel/acpi/boot.c
arch/x86/mm/k8topology_64.c
include/linux/acpi.h

index 977ed5c..c49ebcc 100644 (file)
@@ -771,6 +771,32 @@ static void __init acpi_register_lapic_address(unsigned long address)
                boot_cpu_physical_apicid  = GET_APIC_ID(read_apic_id());
 }
 
+static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
+{
+       int count;
+
+       if (!cpu_has_apic)
+               return -ENODEV;
+
+       /*
+        * Note that the LAPIC address is obtained from the MADT (32-bit value)
+        * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
+        */
+
+       count =
+           acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
+                                 acpi_parse_lapic_addr_ovr, 0);
+       if (count < 0) {
+               printk(KERN_ERR PREFIX
+                      "Error parsing LAPIC address override entry\n");
+               return count;
+       }
+
+       acpi_register_lapic_address(acpi_lapic_addr);
+
+       return count;
+}
+
 static int __init acpi_parse_madt_lapic_entries(void)
 {
        int count;
@@ -901,6 +927,33 @@ static inline int acpi_parse_madt_ioapic_entries(void)
 }
 #endif /* !CONFIG_X86_IO_APIC */
 
+static void __init early_acpi_process_madt(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+       int error;
+
+       if (!acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt)) {
+
+               /*
+                * Parse MADT LAPIC entries
+                */
+               error = early_acpi_parse_madt_lapic_addr_ovr();
+               if (!error) {
+                       acpi_lapic = 1;
+                       smp_found_config = 1;
+               }
+               if (error == -EINVAL) {
+                       /*
+                        * Dell Precision Workstation 410, 610 come here.
+                        */
+                       printk(KERN_ERR PREFIX
+                              "Invalid BIOS MADT, disabling ACPI\n");
+                       disable_acpi();
+               }
+       }
+#endif
+}
+
 static void __init acpi_process_madt(void)
 {
 #ifdef CONFIG_X86_LOCAL_APIC
@@ -1233,6 +1286,23 @@ int __init acpi_boot_table_init(void)
        return 0;
 }
 
+int __init early_acpi_boot_init(void)
+{
+       /*
+        * If acpi_disabled, bail out
+        * One exception: acpi=ht continues far enough to enumerate LAPICs
+        */
+       if (acpi_disabled && !acpi_ht)
+               return 1;
+
+       /*
+        * Process the Multiple APIC Description Table (MADT), if present
+        */
+       early_acpi_process_madt();
+
+       return 0;
+}
+
 int __init acpi_boot_init(void)
 {
        /*
index 86808e6..1f476e4 100644 (file)
 #include <linux/nodemask.h>
 #include <asm/io.h>
 #include <linux/pci_ids.h>
+#include <linux/acpi.h>
 #include <asm/types.h>
 #include <asm/mmzone.h>
 #include <asm/proto.h>
 #include <asm/e820.h>
 #include <asm/pci-direct.h>
 #include <asm/numa.h>
+#include <asm/mpspec.h>
+#include <asm/apic.h>
 
 static __init int find_northbridge(void)
 {
@@ -44,6 +47,30 @@ static __init int find_northbridge(void)
        return -1;
 }
 
+static __init void early_get_boot_cpu_id(void)
+{
+       /*
+        * need to get boot_cpu_id so can use that to create apicid_to_node
+        * in k8_scan_nodes()
+        */
+       /*
+        * Find possible boot-time SMP configuration:
+        */
+       early_find_smp_config();
+#ifdef CONFIG_ACPI
+       /*
+        * Read APIC information from ACPI tables.
+        */
+       early_acpi_boot_init();
+#endif
+       /*
+        * get boot-time SMP configuration:
+        */
+       if (smp_found_config)
+               early_get_smp_config();
+       early_init_lapic_mapping();
+}
+
 int __init k8_scan_nodes(unsigned long start, unsigned long end)
 {
        unsigned long prevbase;
@@ -56,6 +83,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
        unsigned cores;
        unsigned bits;
        int j;
+       unsigned apicid_base;
 
        if (!early_pci_allowed())
                return -1;
@@ -174,11 +202,19 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
        /* use the coreid bits from early_identify_cpu */
        bits = boot_cpu_data.x86_coreid_bits;
        cores = (1<<bits);
+       apicid_base = 0;
+       /* need to get boot_cpu_id early for system with apicid lifting */
+       early_get_boot_cpu_id();
+       if (boot_cpu_physical_apicid > 0) {
+               printk(KERN_INFO "BSP APIC ID: %02x\n",
+                                boot_cpu_physical_apicid);
+               apicid_base = boot_cpu_physical_apicid;
+       }
 
        for (i = 0; i < 8; i++) {
                if (nodes[i].start != nodes[i].end) {
                        nodeid = nodeids[i];
-                       for (j = 0; j < cores; j++)
+                       for (j = apicid_base; j < cores + apicid_base; j++)
                                apicid_to_node[(nodeid << bits) + j] = i;
                        setup_node_bootmem(i, nodes[i].start, nodes[i].end);
                }
index 2c7e003..41f7ce7 100644 (file)
@@ -79,6 +79,7 @@ typedef int (*acpi_table_handler) (struct acpi_table_header *table);
 typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);
 
 char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
+int early_acpi_boot_init(void);
 int acpi_boot_init (void);
 int acpi_boot_table_init (void);
 int acpi_numa_init (void);
@@ -235,6 +236,10 @@ int acpi_check_mem_region(resource_size_t start, resource_size_t n,
 
 #else  /* CONFIG_ACPI */
 
+static inline int early_acpi_boot_init(void)
+{
+       return 0;
+}
 static inline int acpi_boot_init(void)
 {
        return 0;