diff options
author | Andi Kleen <ak@suse.de> | 2005-04-16 18:25:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:25:15 -0400 |
commit | 3dd9d514846cdca1dcef2e4fce666d85e199e844 (patch) | |
tree | 28e60a8b733db213e88b0aee8ef3861a93a6fa48 /arch | |
parent | f2ea2750fbe56867bc8e0eb595115b14195a3e5e (diff) |
[PATCH] x86_64: add support for Intel dual-core detection and displaying
Appended patch adds the support for Intel dual-core detection and displaying
the core related information in /proc/cpuinfo.
It adds two new fields "core id" and "cpu cores" to x86 /proc/cpuinfo and the
"core id" field for x86_64("cpu cores" field is already present in x86_64).
Number of processor cores in a die is detected using cpuid(4) and this is
documented in IA-32 Intel Architecture Software Developer's Manual (vol 2a)
(http://developer.intel.com/design/pentium4/manuals/index_new.htm#sdm_vol2a)
This patch also adds cpu_core_map similar to cpu_sibling_map.
Slightly hacked by AK.
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/i386/kernel/cpu/amd.c | 13 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/common.c | 28 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/intel.c | 23 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/proc.c | 8 | ||||
-rw-r--r-- | arch/i386/kernel/smpboot.c | 31 | ||||
-rw-r--r-- | arch/x86_64/kernel/setup.c | 64 | ||||
-rw-r--r-- | arch/x86_64/kernel/smpboot.c | 24 |
7 files changed, 159 insertions, 32 deletions
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c index ae94585d044..fa10d0a509c 100644 --- a/arch/i386/kernel/cpu/amd.c +++ b/arch/i386/kernel/cpu/amd.c | |||
@@ -188,6 +188,13 @@ static void __init init_amd(struct cpuinfo_x86 *c) | |||
188 | } | 188 | } |
189 | 189 | ||
190 | display_cacheinfo(c); | 190 | display_cacheinfo(c); |
191 | |||
192 | if (cpuid_eax(0x80000000) >= 0x80000008) { | ||
193 | c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; | ||
194 | if (c->x86_num_cores & (c->x86_num_cores - 1)) | ||
195 | c->x86_num_cores = 1; | ||
196 | } | ||
197 | |||
191 | detect_ht(c); | 198 | detect_ht(c); |
192 | 199 | ||
193 | #ifdef CONFIG_X86_HT | 200 | #ifdef CONFIG_X86_HT |
@@ -199,12 +206,6 @@ static void __init init_amd(struct cpuinfo_x86 *c) | |||
199 | if (cpu_has(c, X86_FEATURE_CMP_LEGACY)) | 206 | if (cpu_has(c, X86_FEATURE_CMP_LEGACY)) |
200 | smp_num_siblings = 1; | 207 | smp_num_siblings = 1; |
201 | #endif | 208 | #endif |
202 | |||
203 | if (cpuid_eax(0x80000000) >= 0x80000008) { | ||
204 | c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; | ||
205 | if (c->x86_num_cores & (c->x86_num_cores - 1)) | ||
206 | c->x86_num_cores = 1; | ||
207 | } | ||
208 | } | 209 | } |
209 | 210 | ||
210 | static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size) | 211 | static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size) |
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index ebd5d8247fa..ed4c9c3fe66 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c | |||
@@ -434,7 +434,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c) | |||
434 | void __init detect_ht(struct cpuinfo_x86 *c) | 434 | void __init detect_ht(struct cpuinfo_x86 *c) |
435 | { | 435 | { |
436 | u32 eax, ebx, ecx, edx; | 436 | u32 eax, ebx, ecx, edx; |
437 | int index_lsb, index_msb, tmp; | 437 | int index_msb, tmp; |
438 | int cpu = smp_processor_id(); | 438 | int cpu = smp_processor_id(); |
439 | 439 | ||
440 | if (!cpu_has(c, X86_FEATURE_HT)) | 440 | if (!cpu_has(c, X86_FEATURE_HT)) |
@@ -446,7 +446,6 @@ void __init detect_ht(struct cpuinfo_x86 *c) | |||
446 | if (smp_num_siblings == 1) { | 446 | if (smp_num_siblings == 1) { |
447 | printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); | 447 | printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); |
448 | } else if (smp_num_siblings > 1 ) { | 448 | } else if (smp_num_siblings > 1 ) { |
449 | index_lsb = 0; | ||
450 | index_msb = 31; | 449 | index_msb = 31; |
451 | 450 | ||
452 | if (smp_num_siblings > NR_CPUS) { | 451 | if (smp_num_siblings > NR_CPUS) { |
@@ -455,21 +454,34 @@ void __init detect_ht(struct cpuinfo_x86 *c) | |||
455 | return; | 454 | return; |
456 | } | 455 | } |
457 | tmp = smp_num_siblings; | 456 | tmp = smp_num_siblings; |
458 | while ((tmp & 1) == 0) { | ||
459 | tmp >>=1 ; | ||
460 | index_lsb++; | ||
461 | } | ||
462 | tmp = smp_num_siblings; | ||
463 | while ((tmp & 0x80000000 ) == 0) { | 457 | while ((tmp & 0x80000000 ) == 0) { |
464 | tmp <<=1 ; | 458 | tmp <<=1 ; |
465 | index_msb--; | 459 | index_msb--; |
466 | } | 460 | } |
467 | if (index_lsb != index_msb ) | 461 | if (smp_num_siblings & (smp_num_siblings - 1)) |
468 | index_msb++; | 462 | index_msb++; |
469 | phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); | 463 | phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); |
470 | 464 | ||
471 | printk(KERN_INFO "CPU: Physical Processor ID: %d\n", | 465 | printk(KERN_INFO "CPU: Physical Processor ID: %d\n", |
472 | phys_proc_id[cpu]); | 466 | phys_proc_id[cpu]); |
467 | |||
468 | smp_num_siblings = smp_num_siblings / c->x86_num_cores; | ||
469 | |||
470 | tmp = smp_num_siblings; | ||
471 | index_msb = 31; | ||
472 | while ((tmp & 0x80000000) == 0) { | ||
473 | tmp <<=1 ; | ||
474 | index_msb--; | ||
475 | } | ||
476 | |||
477 | if (smp_num_siblings & (smp_num_siblings - 1)) | ||
478 | index_msb++; | ||
479 | |||
480 | cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); | ||
481 | |||
482 | if (c->x86_num_cores > 1) | ||
483 | printk(KERN_INFO "CPU: Processor Core ID: %d\n", | ||
484 | cpu_core_id[cpu]); | ||
473 | } | 485 | } |
474 | } | 486 | } |
475 | #endif | 487 | #endif |
diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c index b8d847b850d..121aa2176e6 100644 --- a/arch/i386/kernel/cpu/intel.c +++ b/arch/i386/kernel/cpu/intel.c | |||
@@ -77,6 +77,27 @@ static void __init Intel_errata_workarounds(struct cpuinfo_x86 *c) | |||
77 | } | 77 | } |
78 | 78 | ||
79 | 79 | ||
80 | /* | ||
81 | * find out the number of processor cores on the die | ||
82 | */ | ||
83 | static int __init num_cpu_cores(struct cpuinfo_x86 *c) | ||
84 | { | ||
85 | unsigned int eax; | ||
86 | |||
87 | if (c->cpuid_level < 4) | ||
88 | return 1; | ||
89 | |||
90 | __asm__("cpuid" | ||
91 | : "=a" (eax) | ||
92 | : "0" (4), "c" (0) | ||
93 | : "bx", "dx"); | ||
94 | |||
95 | if (eax & 0x1f) | ||
96 | return ((eax >> 26) + 1); | ||
97 | else | ||
98 | return 1; | ||
99 | } | ||
100 | |||
80 | static void __init init_intel(struct cpuinfo_x86 *c) | 101 | static void __init init_intel(struct cpuinfo_x86 *c) |
81 | { | 102 | { |
82 | unsigned int l2 = 0; | 103 | unsigned int l2 = 0; |
@@ -139,6 +160,8 @@ static void __init init_intel(struct cpuinfo_x86 *c) | |||
139 | if ( p ) | 160 | if ( p ) |
140 | strcpy(c->x86_model_id, p); | 161 | strcpy(c->x86_model_id, p); |
141 | 162 | ||
163 | c->x86_num_cores = num_cpu_cores(c); | ||
164 | |||
142 | detect_ht(c); | 165 | detect_ht(c); |
143 | 166 | ||
144 | /* Work around errata */ | 167 | /* Work around errata */ |
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c index 89a2956ee65..0f1125b15b7 100644 --- a/arch/i386/kernel/cpu/proc.c +++ b/arch/i386/kernel/cpu/proc.c | |||
@@ -129,6 +129,14 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
129 | seq_printf(m, "\nbogomips\t: %lu.%02lu\n\n", | 129 | seq_printf(m, "\nbogomips\t: %lu.%02lu\n\n", |
130 | c->loops_per_jiffy/(500000/HZ), | 130 | c->loops_per_jiffy/(500000/HZ), |
131 | (c->loops_per_jiffy/(5000/HZ)) % 100); | 131 | (c->loops_per_jiffy/(5000/HZ)) % 100); |
132 | |||
133 | #ifdef CONFIG_SMP | ||
134 | /* Put new fields at the end to lower the probability of | ||
135 | breaking user space parsers. */ | ||
136 | seq_printf(m, "core id\t\t: %d\n", cpu_core_id[n]); | ||
137 | seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores); | ||
138 | #endif | ||
139 | |||
132 | return 0; | 140 | return 0; |
133 | } | 141 | } |
134 | 142 | ||
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 332ee7a1d1a..fd36d2f65f8 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c | |||
@@ -62,6 +62,8 @@ static int __initdata smp_b_stepping; | |||
62 | int smp_num_siblings = 1; | 62 | int smp_num_siblings = 1; |
63 | int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */ | 63 | int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */ |
64 | EXPORT_SYMBOL(phys_proc_id); | 64 | EXPORT_SYMBOL(phys_proc_id); |
65 | int cpu_core_id[NR_CPUS]; /* Core ID of each logical CPU */ | ||
66 | EXPORT_SYMBOL(cpu_core_id); | ||
65 | 67 | ||
66 | /* bitmap of online cpus */ | 68 | /* bitmap of online cpus */ |
67 | cpumask_t cpu_online_map; | 69 | cpumask_t cpu_online_map; |
@@ -885,6 +887,7 @@ static int boot_cpu_logical_apicid; | |||
885 | void *xquad_portio; | 887 | void *xquad_portio; |
886 | 888 | ||
887 | cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; | 889 | cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; |
890 | cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned; | ||
888 | 891 | ||
889 | static void __init smp_boot_cpus(unsigned int max_cpus) | 892 | static void __init smp_boot_cpus(unsigned int max_cpus) |
890 | { | 893 | { |
@@ -907,6 +910,9 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
907 | cpus_clear(cpu_sibling_map[0]); | 910 | cpus_clear(cpu_sibling_map[0]); |
908 | cpu_set(0, cpu_sibling_map[0]); | 911 | cpu_set(0, cpu_sibling_map[0]); |
909 | 912 | ||
913 | cpus_clear(cpu_core_map[0]); | ||
914 | cpu_set(0, cpu_core_map[0]); | ||
915 | |||
910 | /* | 916 | /* |
911 | * If we couldn't find an SMP configuration at boot time, | 917 | * If we couldn't find an SMP configuration at boot time, |
912 | * get out of here now! | 918 | * get out of here now! |
@@ -919,6 +925,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
919 | printk(KERN_NOTICE "Local APIC not detected." | 925 | printk(KERN_NOTICE "Local APIC not detected." |
920 | " Using dummy APIC emulation.\n"); | 926 | " Using dummy APIC emulation.\n"); |
921 | map_cpu_to_logical_apicid(); | 927 | map_cpu_to_logical_apicid(); |
928 | cpu_set(0, cpu_sibling_map[0]); | ||
929 | cpu_set(0, cpu_core_map[0]); | ||
922 | return; | 930 | return; |
923 | } | 931 | } |
924 | 932 | ||
@@ -942,6 +950,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
942 | printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n"); | 950 | printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n"); |
943 | smpboot_clear_io_apic_irqs(); | 951 | smpboot_clear_io_apic_irqs(); |
944 | phys_cpu_present_map = physid_mask_of_physid(0); | 952 | phys_cpu_present_map = physid_mask_of_physid(0); |
953 | cpu_set(0, cpu_sibling_map[0]); | ||
954 | cpu_set(0, cpu_core_map[0]); | ||
945 | return; | 955 | return; |
946 | } | 956 | } |
947 | 957 | ||
@@ -955,6 +965,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
955 | printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n"); | 965 | printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n"); |
956 | smpboot_clear_io_apic_irqs(); | 966 | smpboot_clear_io_apic_irqs(); |
957 | phys_cpu_present_map = physid_mask_of_physid(0); | 967 | phys_cpu_present_map = physid_mask_of_physid(0); |
968 | cpu_set(0, cpu_sibling_map[0]); | ||
969 | cpu_set(0, cpu_core_map[0]); | ||
958 | return; | 970 | return; |
959 | } | 971 | } |
960 | 972 | ||
@@ -1035,10 +1047,13 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
1035 | * construct cpu_sibling_map[], so that we can tell sibling CPUs | 1047 | * construct cpu_sibling_map[], so that we can tell sibling CPUs |
1036 | * efficiently. | 1048 | * efficiently. |
1037 | */ | 1049 | */ |
1038 | for (cpu = 0; cpu < NR_CPUS; cpu++) | 1050 | for (cpu = 0; cpu < NR_CPUS; cpu++) { |
1039 | cpus_clear(cpu_sibling_map[cpu]); | 1051 | cpus_clear(cpu_sibling_map[cpu]); |
1052 | cpus_clear(cpu_core_map[cpu]); | ||
1053 | } | ||
1040 | 1054 | ||
1041 | for (cpu = 0; cpu < NR_CPUS; cpu++) { | 1055 | for (cpu = 0; cpu < NR_CPUS; cpu++) { |
1056 | struct cpuinfo_x86 *c = cpu_data + cpu; | ||
1042 | int siblings = 0; | 1057 | int siblings = 0; |
1043 | int i; | 1058 | int i; |
1044 | if (!cpu_isset(cpu, cpu_callout_map)) | 1059 | if (!cpu_isset(cpu, cpu_callout_map)) |
@@ -1048,7 +1063,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
1048 | for (i = 0; i < NR_CPUS; i++) { | 1063 | for (i = 0; i < NR_CPUS; i++) { |
1049 | if (!cpu_isset(i, cpu_callout_map)) | 1064 | if (!cpu_isset(i, cpu_callout_map)) |
1050 | continue; | 1065 | continue; |
1051 | if (phys_proc_id[cpu] == phys_proc_id[i]) { | 1066 | if (cpu_core_id[cpu] == cpu_core_id[i]) { |
1052 | siblings++; | 1067 | siblings++; |
1053 | cpu_set(i, cpu_sibling_map[cpu]); | 1068 | cpu_set(i, cpu_sibling_map[cpu]); |
1054 | } | 1069 | } |
@@ -1060,6 +1075,18 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
1060 | 1075 | ||
1061 | if (siblings != smp_num_siblings) | 1076 | if (siblings != smp_num_siblings) |
1062 | printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings); | 1077 | printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings); |
1078 | |||
1079 | if (c->x86_num_cores > 1) { | ||
1080 | for (i = 0; i < NR_CPUS; i++) { | ||
1081 | if (!cpu_isset(i, cpu_callout_map)) | ||
1082 | continue; | ||
1083 | if (phys_proc_id[cpu] == phys_proc_id[i]) { | ||
1084 | cpu_set(i, cpu_core_map[cpu]); | ||
1085 | } | ||
1086 | } | ||
1087 | } else { | ||
1088 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; | ||
1089 | } | ||
1063 | } | 1090 | } |
1064 | 1091 | ||
1065 | if (nmi_watchdog == NMI_LOCAL_APIC) | 1092 | if (nmi_watchdog == NMI_LOCAL_APIC) |
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 57f619052ba..ef74564eede 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c | |||
@@ -774,7 +774,7 @@ static void __init detect_ht(struct cpuinfo_x86 *c) | |||
774 | { | 774 | { |
775 | #ifdef CONFIG_SMP | 775 | #ifdef CONFIG_SMP |
776 | u32 eax, ebx, ecx, edx; | 776 | u32 eax, ebx, ecx, edx; |
777 | int index_lsb, index_msb, tmp; | 777 | int index_msb, tmp; |
778 | int cpu = smp_processor_id(); | 778 | int cpu = smp_processor_id(); |
779 | 779 | ||
780 | if (!cpu_has(c, X86_FEATURE_HT)) | 780 | if (!cpu_has(c, X86_FEATURE_HT)) |
@@ -786,7 +786,6 @@ static void __init detect_ht(struct cpuinfo_x86 *c) | |||
786 | if (smp_num_siblings == 1) { | 786 | if (smp_num_siblings == 1) { |
787 | printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); | 787 | printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); |
788 | } else if (smp_num_siblings > 1) { | 788 | } else if (smp_num_siblings > 1) { |
789 | index_lsb = 0; | ||
790 | index_msb = 31; | 789 | index_msb = 31; |
791 | /* | 790 | /* |
792 | * At this point we only support two siblings per | 791 | * At this point we only support two siblings per |
@@ -798,21 +797,33 @@ static void __init detect_ht(struct cpuinfo_x86 *c) | |||
798 | return; | 797 | return; |
799 | } | 798 | } |
800 | tmp = smp_num_siblings; | 799 | tmp = smp_num_siblings; |
801 | while ((tmp & 1) == 0) { | ||
802 | tmp >>=1 ; | ||
803 | index_lsb++; | ||
804 | } | ||
805 | tmp = smp_num_siblings; | ||
806 | while ((tmp & 0x80000000 ) == 0) { | 800 | while ((tmp & 0x80000000 ) == 0) { |
807 | tmp <<=1 ; | 801 | tmp <<=1 ; |
808 | index_msb--; | 802 | index_msb--; |
809 | } | 803 | } |
810 | if (index_lsb != index_msb ) | 804 | if (smp_num_siblings & (smp_num_siblings - 1)) |
811 | index_msb++; | 805 | index_msb++; |
812 | phys_proc_id[cpu] = phys_pkg_id(index_msb); | 806 | phys_proc_id[cpu] = phys_pkg_id(index_msb); |
813 | 807 | ||
814 | printk(KERN_INFO "CPU: Physical Processor ID: %d\n", | 808 | printk(KERN_INFO "CPU: Physical Processor ID: %d\n", |
815 | phys_proc_id[cpu]); | 809 | phys_proc_id[cpu]); |
810 | |||
811 | smp_num_siblings = smp_num_siblings / c->x86_num_cores; | ||
812 | |||
813 | tmp = smp_num_siblings; | ||
814 | index_msb = 31; | ||
815 | while ((tmp & 0x80000000) == 0) { | ||
816 | tmp <<=1 ; | ||
817 | index_msb--; | ||
818 | } | ||
819 | if (smp_num_siblings & (smp_num_siblings - 1)) | ||
820 | index_msb++; | ||
821 | |||
822 | cpu_core_id[cpu] = phys_pkg_id(index_msb); | ||
823 | |||
824 | if (c->x86_num_cores > 1) | ||
825 | printk(KERN_INFO "CPU: Processor Core ID: %d\n", | ||
826 | cpu_core_id[cpu]); | ||
816 | } | 827 | } |
817 | #endif | 828 | #endif |
818 | } | 829 | } |
@@ -829,7 +840,28 @@ static void __init sched_cmp_hack(struct cpuinfo_x86 *c) | |||
829 | smp_num_siblings = 1; | 840 | smp_num_siblings = 1; |
830 | #endif | 841 | #endif |
831 | } | 842 | } |
832 | 843 | ||
844 | /* | ||
845 | * find out the number of processor cores on the die | ||
846 | */ | ||
847 | static int __init intel_num_cpu_cores(struct cpuinfo_x86 *c) | ||
848 | { | ||
849 | unsigned int eax; | ||
850 | |||
851 | if (c->cpuid_level < 4) | ||
852 | return 1; | ||
853 | |||
854 | __asm__("cpuid" | ||
855 | : "=a" (eax) | ||
856 | : "0" (4), "c" (0) | ||
857 | : "bx", "dx"); | ||
858 | |||
859 | if (eax & 0x1f) | ||
860 | return ((eax >> 26) + 1); | ||
861 | else | ||
862 | return 1; | ||
863 | } | ||
864 | |||
833 | static void __init init_intel(struct cpuinfo_x86 *c) | 865 | static void __init init_intel(struct cpuinfo_x86 *c) |
834 | { | 866 | { |
835 | /* Cache sizes */ | 867 | /* Cache sizes */ |
@@ -847,6 +879,7 @@ static void __init init_intel(struct cpuinfo_x86 *c) | |||
847 | c->x86_cache_alignment = c->x86_clflush_size * 2; | 879 | c->x86_cache_alignment = c->x86_clflush_size * 2; |
848 | if (c->x86 >= 15) | 880 | if (c->x86 >= 15) |
849 | set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability); | 881 | set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability); |
882 | c->x86_num_cores = intel_num_cpu_cores(c); | ||
850 | } | 883 | } |
851 | 884 | ||
852 | void __init get_cpu_vendor(struct cpuinfo_x86 *c) | 885 | void __init get_cpu_vendor(struct cpuinfo_x86 *c) |
@@ -1153,13 +1186,16 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
1153 | seq_printf(m, " [%d]", i); | 1186 | seq_printf(m, " [%d]", i); |
1154 | } | 1187 | } |
1155 | } | 1188 | } |
1156 | seq_printf(m, "\n"); | ||
1157 | 1189 | ||
1158 | if (c->x86_num_cores > 1) | 1190 | seq_printf(m, "\n"); |
1159 | seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores); | ||
1160 | |||
1161 | seq_printf(m, "\n\n"); | ||
1162 | 1191 | ||
1192 | #ifdef CONFIG_SMP | ||
1193 | /* Put new fields at the end to lower the probability of | ||
1194 | breaking user space parsers. */ | ||
1195 | seq_printf(m, "core id\t\t: %d\n", cpu_core_id[c - cpu_data]); | ||
1196 | seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores); | ||
1197 | #endif | ||
1198 | seq_printf(m, "\n"); | ||
1163 | return 0; | 1199 | return 0; |
1164 | } | 1200 | } |
1165 | 1201 | ||
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index e5714090b00..7e2de8925b0 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c | |||
@@ -58,7 +58,10 @@ | |||
58 | int smp_num_siblings = 1; | 58 | int smp_num_siblings = 1; |
59 | /* Package ID of each logical CPU */ | 59 | /* Package ID of each logical CPU */ |
60 | u8 phys_proc_id[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; | 60 | u8 phys_proc_id[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; |
61 | /* Core ID of each logical CPU */ | ||
62 | u8 cpu_core_id[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; | ||
61 | EXPORT_SYMBOL(phys_proc_id); | 63 | EXPORT_SYMBOL(phys_proc_id); |
64 | EXPORT_SYMBOL(cpu_core_id); | ||
62 | 65 | ||
63 | /* Bitmask of currently online CPUs */ | 66 | /* Bitmask of currently online CPUs */ |
64 | cpumask_t cpu_online_map; | 67 | cpumask_t cpu_online_map; |
@@ -71,6 +74,7 @@ static cpumask_t smp_commenced_mask; | |||
71 | struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; | 74 | struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; |
72 | 75 | ||
73 | cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; | 76 | cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; |
77 | cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned; | ||
74 | 78 | ||
75 | /* | 79 | /* |
76 | * Trampoline 80x86 program as an array. | 80 | * Trampoline 80x86 program as an array. |
@@ -713,6 +717,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
713 | io_apic_irqs = 0; | 717 | io_apic_irqs = 0; |
714 | cpu_online_map = cpumask_of_cpu(0); | 718 | cpu_online_map = cpumask_of_cpu(0); |
715 | cpu_set(0, cpu_sibling_map[0]); | 719 | cpu_set(0, cpu_sibling_map[0]); |
720 | cpu_set(0, cpu_core_map[0]); | ||
716 | phys_cpu_present_map = physid_mask_of_physid(0); | 721 | phys_cpu_present_map = physid_mask_of_physid(0); |
717 | if (APIC_init_uniprocessor()) | 722 | if (APIC_init_uniprocessor()) |
718 | printk(KERN_NOTICE "Local APIC not detected." | 723 | printk(KERN_NOTICE "Local APIC not detected." |
@@ -740,6 +745,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
740 | io_apic_irqs = 0; | 745 | io_apic_irqs = 0; |
741 | cpu_online_map = cpumask_of_cpu(0); | 746 | cpu_online_map = cpumask_of_cpu(0); |
742 | cpu_set(0, cpu_sibling_map[0]); | 747 | cpu_set(0, cpu_sibling_map[0]); |
748 | cpu_set(0, cpu_core_map[0]); | ||
743 | phys_cpu_present_map = physid_mask_of_physid(0); | 749 | phys_cpu_present_map = physid_mask_of_physid(0); |
744 | disable_apic = 1; | 750 | disable_apic = 1; |
745 | goto smp_done; | 751 | goto smp_done; |
@@ -756,6 +762,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
756 | io_apic_irqs = 0; | 762 | io_apic_irqs = 0; |
757 | cpu_online_map = cpumask_of_cpu(0); | 763 | cpu_online_map = cpumask_of_cpu(0); |
758 | cpu_set(0, cpu_sibling_map[0]); | 764 | cpu_set(0, cpu_sibling_map[0]); |
765 | cpu_set(0, cpu_core_map[0]); | ||
759 | phys_cpu_present_map = physid_mask_of_physid(0); | 766 | phys_cpu_present_map = physid_mask_of_physid(0); |
760 | disable_apic = 1; | 767 | disable_apic = 1; |
761 | goto smp_done; | 768 | goto smp_done; |
@@ -833,10 +840,13 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
833 | * Construct cpu_sibling_map[], so that we can tell the | 840 | * Construct cpu_sibling_map[], so that we can tell the |
834 | * sibling CPU efficiently. | 841 | * sibling CPU efficiently. |
835 | */ | 842 | */ |
836 | for (cpu = 0; cpu < NR_CPUS; cpu++) | 843 | for (cpu = 0; cpu < NR_CPUS; cpu++) { |
837 | cpus_clear(cpu_sibling_map[cpu]); | 844 | cpus_clear(cpu_sibling_map[cpu]); |
845 | cpus_clear(cpu_core_map[cpu]); | ||
846 | } | ||
838 | 847 | ||
839 | for (cpu = 0; cpu < NR_CPUS; cpu++) { | 848 | for (cpu = 0; cpu < NR_CPUS; cpu++) { |
849 | struct cpuinfo_x86 *c = cpu_data + cpu; | ||
840 | int siblings = 0; | 850 | int siblings = 0; |
841 | int i; | 851 | int i; |
842 | if (!cpu_isset(cpu, cpu_callout_map)) | 852 | if (!cpu_isset(cpu, cpu_callout_map)) |
@@ -846,7 +856,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
846 | for (i = 0; i < NR_CPUS; i++) { | 856 | for (i = 0; i < NR_CPUS; i++) { |
847 | if (!cpu_isset(i, cpu_callout_map)) | 857 | if (!cpu_isset(i, cpu_callout_map)) |
848 | continue; | 858 | continue; |
849 | if (phys_proc_id[cpu] == phys_proc_id[i]) { | 859 | if (phys_proc_id[cpu] == cpu_core_id[i]) { |
850 | siblings++; | 860 | siblings++; |
851 | cpu_set(i, cpu_sibling_map[cpu]); | 861 | cpu_set(i, cpu_sibling_map[cpu]); |
852 | } | 862 | } |
@@ -862,6 +872,16 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
862 | siblings, cpu, smp_num_siblings); | 872 | siblings, cpu, smp_num_siblings); |
863 | smp_num_siblings = siblings; | 873 | smp_num_siblings = siblings; |
864 | } | 874 | } |
875 | if (c->x86_num_cores > 1) { | ||
876 | for (i = 0; i < NR_CPUS; i++) { | ||
877 | if (!cpu_isset(i, cpu_callout_map)) | ||
878 | continue; | ||
879 | if (phys_proc_id[cpu] == phys_proc_id[i]) { | ||
880 | cpu_set(i, cpu_core_map[cpu]); | ||
881 | } | ||
882 | } | ||
883 | } else | ||
884 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; | ||
865 | } | 885 | } |
866 | 886 | ||
867 | Dprintk("Boot done.\n"); | 887 | Dprintk("Boot done.\n"); |