diff options
author | Andi Kleen <ak@suse.de> | 2005-04-16 18:25:16 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:25:16 -0400 |
commit | 635186447d0e6f3b35895fda993a266a1315d2a7 (patch) | |
tree | 7d92e2b57c66f076908a5739056d823a4bde0121 /arch/x86_64/kernel/setup.c | |
parent | 3dd9d514846cdca1dcef2e4fce666d85e199e844 (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/kernel/setup.c')
-rw-r--r-- | arch/x86_64/kernel/setup.c | 71 |
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 | */ | ||
723 | static 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 | ||
749 | static void __init amd_detect_cmp(struct cpuinfo_x86 *c) | ||
750 | { | ||
751 | } | ||
752 | #endif | ||
718 | 753 | ||
719 | static int __init init_amd(struct cpuinfo_x86 *c) | 754 | static 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 | ||
831 | static 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 |