aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/kernel/setup.c')
-rw-r--r--arch/x86_64/kernel/setup.c64
1 files changed, 46 insertions, 18 deletions
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 976ebcf96f3e..df55a63f8866 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -755,6 +755,24 @@ static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
755 } 755 }
756} 756}
757 757
758#ifdef CONFIG_NUMA
759static int nearby_node(int apicid)
760{
761 int i;
762 for (i = apicid - 1; i >= 0; i--) {
763 int node = apicid_to_node[i];
764 if (node != NUMA_NO_NODE && node_online(node))
765 return node;
766 }
767 for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
768 int node = apicid_to_node[i];
769 if (node != NUMA_NO_NODE && node_online(node))
770 return node;
771 }
772 return first_node(node_online_map); /* Shouldn't happen */
773}
774#endif
775
758/* 776/*
759 * On a AMD dual core setup the lower bits of the APIC id distingush the cores. 777 * On a AMD dual core setup the lower bits of the APIC id distingush the cores.
760 * Assumes number of cores is a power of two. 778 * Assumes number of cores is a power of two.
@@ -763,9 +781,11 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
763{ 781{
764#ifdef CONFIG_SMP 782#ifdef CONFIG_SMP
765 int cpu = smp_processor_id(); 783 int cpu = smp_processor_id();
766 int node = 0;
767 unsigned bits; 784 unsigned bits;
785#ifdef CONFIG_NUMA
786 int node = 0;
768 unsigned apicid = phys_proc_id[cpu]; 787 unsigned apicid = phys_proc_id[cpu];
788#endif
769 789
770 bits = 0; 790 bits = 0;
771 while ((1 << bits) < c->x86_num_cores) 791 while ((1 << bits) < c->x86_num_cores)
@@ -777,24 +797,32 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
777 phys_proc_id[cpu] >>= bits; 797 phys_proc_id[cpu] >>= bits;
778 798
779#ifdef CONFIG_NUMA 799#ifdef CONFIG_NUMA
780 /* When an ACPI SRAT table is available use the mappings from SRAT 800 node = phys_proc_id[cpu];
781 instead. */ 801 if (apicid_to_node[apicid] != NUMA_NO_NODE)
782 node = phys_proc_id[cpu]; 802 node = apicid_to_node[apicid];
783 if (acpi_numa > 0) { 803 if (!node_online(node)) {
784 if (apicid_to_node[apicid] != NUMA_NO_NODE) 804 /* Two possibilities here:
785 node = apicid_to_node[apicid]; 805 - The CPU is missing memory and no node was created.
786 else 806 In that case try picking one from a nearby CPU
787 printk(KERN_ERR 807 - The APIC IDs differ from the HyperTransport node IDs
788 "SRAT: Didn't specify node for CPU %d(%d)\n", 808 which the K8 northbridge parsing fills in.
789 cpu, apicid); 809 Assume they are all increased by a constant offset,
790 } 810 but in the same order as the HT nodeids.
791 if (!node_online(node)) 811 If that doesn't result in a usable node fall back to the
792 node = first_node(node_online_map); 812 path for the previous case. */
793 cpu_to_node[cpu] = node; 813 int ht_nodeid = apicid - (phys_proc_id[0] << bits);
814 if (ht_nodeid >= 0 &&
815 apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
816 node = apicid_to_node[ht_nodeid];
817 /* Pick a nearby node */
818 if (!node_online(node))
819 node = nearby_node(apicid);
820 }
821 cpu_to_node[cpu] = node;
822
823 printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
824 cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
794#endif 825#endif
795
796 printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
797 cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
798#endif 826#endif
799} 827}
800 828