aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2005-04-16 18:25:16 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:25:16 -0400
commit635186447d0e6f3b35895fda993a266a1315d2a7 (patch)
tree7d92e2b57c66f076908a5739056d823a4bde0121 /arch/x86_64
parent3dd9d514846cdca1dcef2e4fce666d85e199e844 (diff)
[PATCH] x86_64: Final support for AMD dual core
Clean up the code greatly. Now uses the infrastructure from the Intel dual core patch Should fix a final bug noticed by Tyan of not detecting the nodes correctly in some corner cases. Patch for x86-64 and i386 Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/x86_64')
-rw-r--r--arch/x86_64/kernel/setup.c71
1 files changed, 38 insertions, 33 deletions
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index ef74564eedeb..666fe8bcca0e 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -715,14 +715,46 @@ static void __init display_cacheinfo(struct cpuinfo_x86 *c)
715 } 715 }
716} 716}
717 717
718#ifdef CONFIG_SMP
719/*
720 * On a AMD dual core setup the lower bits of the APIC id distingush the cores.
721 * Assumes number of cores is a power of two.
722 */
723static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
724{
725#ifdef CONFIG_SMP
726 int cpu = c->x86_apicid;
727 int node = 0;
728 if (c->x86_num_cores == 1)
729 return;
730 cpu_core_id[cpu] = cpu >> hweight32(c->x86_num_cores - 1);
731
732#ifdef CONFIG_NUMA
733 /* When an ACPI SRAT table is available use the mappings from SRAT
734 instead. */
735 if (acpi_numa <= 0) {
736 node = cpu_core_id[cpu];
737 if (!node_online(node))
738 node = first_node(node_online_map);
739 cpu_to_node[cpu] = node;
740 } else {
741 node = cpu_to_node[cpu];
742 }
743#endif
744 printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
745 cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
746#endif
747}
748#else
749static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
750{
751}
752#endif
718 753
719static int __init init_amd(struct cpuinfo_x86 *c) 754static int __init init_amd(struct cpuinfo_x86 *c)
720{ 755{
721 int r; 756 int r;
722 int level; 757 int level;
723#ifdef CONFIG_NUMA
724 int cpu;
725#endif
726 758
727 /* Bit 31 in normal CPUID used for nonstandard 3DNow ID; 759 /* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
728 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ 760 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
@@ -750,21 +782,7 @@ static int __init init_amd(struct cpuinfo_x86 *c)
750 if (c->x86_num_cores & (c->x86_num_cores - 1)) 782 if (c->x86_num_cores & (c->x86_num_cores - 1))
751 c->x86_num_cores = 1; 783 c->x86_num_cores = 1;
752 784
753#ifdef CONFIG_NUMA 785 amd_detect_cmp(c);
754 /* On a dual core setup the lower bits of apic id
755 distingush the cores. Fix up the CPU<->node mappings
756 here based on that.
757 Assumes number of cores is a power of two.
758 When using SRAT use mapping from SRAT. */
759 cpu = c->x86_apicid;
760 if (acpi_numa <= 0 && c->x86_num_cores > 1) {
761 cpu_to_node[cpu] = cpu >> hweight32(c->x86_num_cores - 1);
762 if (!node_online(cpu_to_node[cpu]))
763 cpu_to_node[cpu] = first_node(node_online_map);
764 }
765 printk(KERN_INFO "CPU %d(%d) -> Node %d\n",
766 cpu, c->x86_num_cores, cpu_to_node[cpu]);
767#endif
768 } 786 }
769 787
770 return r; 788 return r;
@@ -777,7 +795,7 @@ static void __init detect_ht(struct cpuinfo_x86 *c)
777 int index_msb, tmp; 795 int index_msb, tmp;
778 int cpu = smp_processor_id(); 796 int cpu = smp_processor_id();
779 797
780 if (!cpu_has(c, X86_FEATURE_HT)) 798 if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
781 return; 799 return;
782 800
783 cpuid(1, &eax, &ebx, &ecx, &edx); 801 cpuid(1, &eax, &ebx, &ecx, &edx);
@@ -819,6 +837,7 @@ static void __init detect_ht(struct cpuinfo_x86 *c)
819 if (smp_num_siblings & (smp_num_siblings - 1)) 837 if (smp_num_siblings & (smp_num_siblings - 1))
820 index_msb++; 838 index_msb++;
821 839
840 /* RED-PEN surely this must run in the non HT case too! -AK */
822 cpu_core_id[cpu] = phys_pkg_id(index_msb); 841 cpu_core_id[cpu] = phys_pkg_id(index_msb);
823 842
824 if (c->x86_num_cores > 1) 843 if (c->x86_num_cores > 1)
@@ -828,19 +847,6 @@ static void __init detect_ht(struct cpuinfo_x86 *c)
828#endif 847#endif
829} 848}
830 849
831static void __init sched_cmp_hack(struct cpuinfo_x86 *c)
832{
833#ifdef CONFIG_SMP
834 /* AMD dual core looks like HT but isn't really. Hide it from the
835 scheduler. This works around problems with the domain scheduler.
836 Also probably gives slightly better scheduling and disables
837 SMT nice which is harmful on dual core.
838 TBD tune the domain scheduler for dual core. */
839 if (c->x86_vendor == X86_VENDOR_AMD && cpu_has(c, X86_FEATURE_CMP_LEGACY))
840 smp_num_siblings = 1;
841#endif
842}
843
844/* 850/*
845 * find out the number of processor cores on the die 851 * find out the number of processor cores on the die
846 */ 852 */
@@ -1009,7 +1015,6 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
1009 1015
1010 select_idle_routine(c); 1016 select_idle_routine(c);
1011 detect_ht(c); 1017 detect_ht(c);
1012 sched_cmp_hack(c);
1013 1018
1014 /* 1019 /*
1015 * On SMP, boot_cpu_data holds the common feature set between 1020 * On SMP, boot_cpu_data holds the common feature set between