aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2005-04-16 18:25:15 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:25:15 -0400
commit3dd9d514846cdca1dcef2e4fce666d85e199e844 (patch)
tree28e60a8b733db213e88b0aee8ef3861a93a6fa48 /arch/i386/kernel
parentf2ea2750fbe56867bc8e0eb595115b14195a3e5e (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/i386/kernel')
-rw-r--r--arch/i386/kernel/cpu/amd.c13
-rw-r--r--arch/i386/kernel/cpu/common.c28
-rw-r--r--arch/i386/kernel/cpu/intel.c23
-rw-r--r--arch/i386/kernel/cpu/proc.c8
-rw-r--r--arch/i386/kernel/smpboot.c31
5 files changed, 87 insertions, 16 deletions
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index ae94585d0445..fa10d0a509c7 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
210static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size) 211static 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 ebd5d8247faa..ed4c9c3fe667 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)
434void __init detect_ht(struct cpuinfo_x86 *c) 434void __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 b8d847b850dc..121aa2176e69 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 */
83static 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
80static void __init init_intel(struct cpuinfo_x86 *c) 101static 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 89a2956ee657..0f1125b15b76 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 332ee7a1d1a1..fd36d2f65f88 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -62,6 +62,8 @@ static int __initdata smp_b_stepping;
62int smp_num_siblings = 1; 62int smp_num_siblings = 1;
63int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */ 63int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
64EXPORT_SYMBOL(phys_proc_id); 64EXPORT_SYMBOL(phys_proc_id);
65int cpu_core_id[NR_CPUS]; /* Core ID of each logical CPU */
66EXPORT_SYMBOL(cpu_core_id);
65 67
66/* bitmap of online cpus */ 68/* bitmap of online cpus */
67cpumask_t cpu_online_map; 69cpumask_t cpu_online_map;
@@ -885,6 +887,7 @@ static int boot_cpu_logical_apicid;
885void *xquad_portio; 887void *xquad_portio;
886 888
887cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; 889cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
890cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
888 891
889static void __init smp_boot_cpus(unsigned int max_cpus) 892static 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)