diff options
Diffstat (limited to 'arch/x86_64/kernel/setup.c')
-rw-r--r-- | arch/x86_64/kernel/setup.c | 64 |
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 | ||
759 | static 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 | ||