aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64
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/x86_64
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/x86_64')
-rw-r--r--arch/x86_64/kernel/setup.c64
-rw-r--r--arch/x86_64/kernel/smpboot.c24
2 files changed, 72 insertions, 16 deletions
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 57f619052bad..ef74564eedeb 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 */
847static 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
833static void __init init_intel(struct cpuinfo_x86 *c) 865static 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
852void __init get_cpu_vendor(struct cpuinfo_x86 *c) 885void __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 e5714090b00d..7e2de8925b0f 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -58,7 +58,10 @@
58int smp_num_siblings = 1; 58int smp_num_siblings = 1;
59/* Package ID of each logical CPU */ 59/* Package ID of each logical CPU */
60u8 phys_proc_id[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; 60u8 phys_proc_id[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
61/* Core ID of each logical CPU */
62u8 cpu_core_id[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
61EXPORT_SYMBOL(phys_proc_id); 63EXPORT_SYMBOL(phys_proc_id);
64EXPORT_SYMBOL(cpu_core_id);
62 65
63/* Bitmask of currently online CPUs */ 66/* Bitmask of currently online CPUs */
64cpumask_t cpu_online_map; 67cpumask_t cpu_online_map;
@@ -71,6 +74,7 @@ static cpumask_t smp_commenced_mask;
71struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; 74struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
72 75
73cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned; 76cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
77cpumask_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");