Browse Source

acpi: get boot_cpu_id as early for k8_scan_nodes

[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>
Yinghai Lu 17 years ago
parent
commit
cbf9bd603a
3 changed files with 112 additions and 1 deletions
  1. 70 0
      arch/x86/kernel/acpi/boot.c
  2. 37 1
      arch/x86/mm/k8topology_64.c
  3. 5 0
      include/linux/acpi.h

+ 70 - 0
arch/x86/kernel/acpi/boot.c

@@ -771,6 +771,32 @@ static void __init acpi_register_lapic_address(unsigned long address)
 		boot_cpu_physical_apicid  = GET_APIC_ID(read_apic_id());
 		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)
 static int __init acpi_parse_madt_lapic_entries(void)
 {
 {
 	int count;
 	int count;
@@ -901,6 +927,33 @@ static inline int acpi_parse_madt_ioapic_entries(void)
 }
 }
 #endif	/* !CONFIG_X86_IO_APIC */
 #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)
 static void __init acpi_process_madt(void)
 {
 {
 #ifdef CONFIG_X86_LOCAL_APIC
 #ifdef CONFIG_X86_LOCAL_APIC
@@ -1233,6 +1286,23 @@ int __init acpi_boot_table_init(void)
 	return 0;
 	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)
 int __init acpi_boot_init(void)
 {
 {
 	/*
 	/*

+ 37 - 1
arch/x86/mm/k8topology_64.c

@@ -13,12 +13,15 @@
 #include <linux/nodemask.h>
 #include <linux/nodemask.h>
 #include <asm/io.h>
 #include <asm/io.h>
 #include <linux/pci_ids.h>
 #include <linux/pci_ids.h>
+#include <linux/acpi.h>
 #include <asm/types.h>
 #include <asm/types.h>
 #include <asm/mmzone.h>
 #include <asm/mmzone.h>
 #include <asm/proto.h>
 #include <asm/proto.h>
 #include <asm/e820.h>
 #include <asm/e820.h>
 #include <asm/pci-direct.h>
 #include <asm/pci-direct.h>
 #include <asm/numa.h>
 #include <asm/numa.h>
+#include <asm/mpspec.h>
+#include <asm/apic.h>
 
 
 static __init int find_northbridge(void)
 static __init int find_northbridge(void)
 {
 {
@@ -44,6 +47,30 @@ static __init int find_northbridge(void)
 	return -1;
 	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)
 int __init k8_scan_nodes(unsigned long start, unsigned long end)
 {
 {
 	unsigned long prevbase;
 	unsigned long prevbase;
@@ -56,6 +83,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
 	unsigned cores;
 	unsigned cores;
 	unsigned bits;
 	unsigned bits;
 	int j;
 	int j;
+	unsigned apicid_base;
 
 
 	if (!early_pci_allowed())
 	if (!early_pci_allowed())
 		return -1;
 		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 */
 	/* use the coreid bits from early_identify_cpu */
 	bits = boot_cpu_data.x86_coreid_bits;
 	bits = boot_cpu_data.x86_coreid_bits;
 	cores = (1<<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++) {
 	for (i = 0; i < 8; i++) {
 		if (nodes[i].start != nodes[i].end) {
 		if (nodes[i].start != nodes[i].end) {
 			nodeid = nodeids[i];
 			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;
 				apicid_to_node[(nodeid << bits) + j] = i;
 			setup_node_bootmem(i, nodes[i].start, nodes[i].end);
 			setup_node_bootmem(i, nodes[i].start, nodes[i].end);
 		}
 		}

+ 5 - 0
include/linux/acpi.h

@@ -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);
 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);
 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_init (void);
 int acpi_boot_table_init (void);
 int acpi_boot_table_init (void);
 int acpi_numa_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 */
 #else	/* CONFIG_ACPI */
 
 
+static inline int early_acpi_boot_init(void)
+{
+	return 0;
+}
 static inline int acpi_boot_init(void)
 static inline int acpi_boot_init(void)
 {
 {
 	return 0;
 	return 0;