tree 28e60a8b733db213e88b0aee8ef3861a93a6fa48
parent f2ea2750fbe56867bc8e0eb595115b14195a3e5e
author Andi Kleen <[EMAIL PROTECTED]> Sun, 17 Apr 2005 05:25:15 -0700
committer Linus Torvalds <[EMAIL PROTECTED]> Sun, 17 Apr 2005 05:25:15 -0700

[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 <[EMAIL PROTECTED]>
Signed-off-by: Andi Kleen <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>

 i386/kernel/cpu/amd.c    |   13 +++++----
 i386/kernel/cpu/common.c |   28 ++++++++++++++------
 i386/kernel/cpu/intel.c  |   23 ++++++++++++++++
 i386/kernel/cpu/proc.c   |    8 +++++
 i386/kernel/smpboot.c    |   31 +++++++++++++++++++++-
 x86_64/kernel/setup.c    |   64 ++++++++++++++++++++++++++++++++++++-----------
 x86_64/kernel/smpboot.c  |   24 ++++++++++++++++-
 asm-i386/processor.h     |    1 
 asm-i386/smp.h           |    1 
 asm-x86_64/smp.h         |    2 +
 10 files changed, 163 insertions(+), 32 deletions(-)

Index: arch/i386/kernel/cpu/amd.c
===================================================================
--- 360cf103473c058cb6db99fd6a8c6e22dfa74c96/arch/i386/kernel/cpu/amd.c  
(mode:100644 sha1:ae94585d0445130ab1b978d42c0ca5d88b8646d0)
+++ 28e60a8b733db213e88b0aee8ef3861a93a6fa48/arch/i386/kernel/cpu/amd.c  
(mode:100644 sha1:fa10d0a509c7ad5f6712a3beba595e35aef0b642)
@@ -188,6 +188,13 @@
        }
 
        display_cacheinfo(c);
+
+       if (cpuid_eax(0x80000000) >= 0x80000008) {
+               c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
+               if (c->x86_num_cores & (c->x86_num_cores - 1))
+                       c->x86_num_cores = 1;
+       }
+
        detect_ht(c);
 
 #ifdef CONFIG_X86_HT
@@ -199,12 +206,6 @@
        if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
                smp_num_siblings = 1;
 #endif
-
-       if (cpuid_eax(0x80000000) >= 0x80000008) {
-               c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
-               if (c->x86_num_cores & (c->x86_num_cores - 1))
-                       c->x86_num_cores = 1;
-       }
 }
 
 static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
Index: arch/i386/kernel/cpu/common.c
===================================================================
--- 360cf103473c058cb6db99fd6a8c6e22dfa74c96/arch/i386/kernel/cpu/common.c  
(mode:100644 sha1:ebd5d8247faaee440491c513b35bfaee652c80b8)
+++ 28e60a8b733db213e88b0aee8ef3861a93a6fa48/arch/i386/kernel/cpu/common.c  
(mode:100644 sha1:ed4c9c3fe667b6f8922f7a05c7fc13488d397120)
@@ -434,7 +434,7 @@
 void __init detect_ht(struct cpuinfo_x86 *c)
 {
        u32     eax, ebx, ecx, edx;
-       int     index_lsb, index_msb, tmp;
+       int     index_msb, tmp;
        int     cpu = smp_processor_id();
 
        if (!cpu_has(c, X86_FEATURE_HT))
@@ -446,7 +446,6 @@
        if (smp_num_siblings == 1) {
                printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
        } else if (smp_num_siblings > 1 ) {
-               index_lsb = 0;
                index_msb = 31;
 
                if (smp_num_siblings > NR_CPUS) {
@@ -455,21 +454,34 @@
                        return;
                }
                tmp = smp_num_siblings;
-               while ((tmp & 1) == 0) {
-                       tmp >>=1 ;
-                       index_lsb++;
-               }
-               tmp = smp_num_siblings;
                while ((tmp & 0x80000000 ) == 0) {
                        tmp <<=1 ;
                        index_msb--;
                }
-               if (index_lsb != index_msb )
+               if (smp_num_siblings & (smp_num_siblings - 1))
                        index_msb++;
                phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
 
                printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
                       phys_proc_id[cpu]);
+
+               smp_num_siblings = smp_num_siblings / c->x86_num_cores;
+
+               tmp = smp_num_siblings;
+               index_msb = 31;
+               while ((tmp & 0x80000000) == 0) {
+                       tmp <<=1 ;
+                       index_msb--;
+               }
+
+               if (smp_num_siblings & (smp_num_siblings - 1))
+                       index_msb++;
+
+               cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
+
+               if (c->x86_num_cores > 1)
+                       printk(KERN_INFO  "CPU: Processor Core ID: %d\n",
+                              cpu_core_id[cpu]);
        }
 }
 #endif
Index: arch/i386/kernel/cpu/intel.c
===================================================================
--- 360cf103473c058cb6db99fd6a8c6e22dfa74c96/arch/i386/kernel/cpu/intel.c  
(mode:100644 sha1:b8d847b850dc66c2b62ea5a37dbc6f2efa1c6a6d)
+++ 28e60a8b733db213e88b0aee8ef3861a93a6fa48/arch/i386/kernel/cpu/intel.c  
(mode:100644 sha1:121aa2176e694a34f1fd06f23e1d903230b2207a)
@@ -77,6 +77,27 @@
 }
 
 
+/*
+ * find out the number of processor cores on the die
+ */
+static int __init num_cpu_cores(struct cpuinfo_x86 *c)
+{
+       unsigned int eax;
+
+       if (c->cpuid_level < 4)
+               return 1;
+
+       __asm__("cpuid"
+               : "=a" (eax)
+               : "0" (4), "c" (0)
+               : "bx", "dx");
+
+       if (eax & 0x1f)
+               return ((eax >> 26) + 1);
+       else
+               return 1;
+}
+
 static void __init init_intel(struct cpuinfo_x86 *c)
 {
        unsigned int l2 = 0;
@@ -139,6 +160,8 @@
        if ( p )
                strcpy(c->x86_model_id, p);
        
+       c->x86_num_cores = num_cpu_cores(c);
+
        detect_ht(c);
 
        /* Work around errata */
Index: arch/i386/kernel/cpu/proc.c
===================================================================
--- 360cf103473c058cb6db99fd6a8c6e22dfa74c96/arch/i386/kernel/cpu/proc.c  
(mode:100644 sha1:89a2956ee657b920ceb3d3f2319a0fa5ffadcc30)
+++ 28e60a8b733db213e88b0aee8ef3861a93a6fa48/arch/i386/kernel/cpu/proc.c  
(mode:100644 sha1:0f1125b15b76a8b6e903bcb566132b1095051cb8)
@@ -129,6 +129,14 @@
        seq_printf(m, "\nbogomips\t: %lu.%02lu\n\n",
                     c->loops_per_jiffy/(500000/HZ),
                     (c->loops_per_jiffy/(5000/HZ)) % 100);
+
+#ifdef CONFIG_SMP
+       /* Put new fields at the end to lower the probability of
+          breaking user space parsers. */
+       seq_printf(m, "core id\t\t: %d\n", cpu_core_id[n]);
+       seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores);
+#endif
+
        return 0;
 }
 
Index: arch/i386/kernel/smpboot.c
===================================================================
--- 360cf103473c058cb6db99fd6a8c6e22dfa74c96/arch/i386/kernel/smpboot.c  
(mode:100644 sha1:332ee7a1d1a111643610c2517335f1e6cd7f6423)
+++ 28e60a8b733db213e88b0aee8ef3861a93a6fa48/arch/i386/kernel/smpboot.c  
(mode:100644 sha1:fd36d2f65f885e73a61c9fb131bcb1bf2a7e4aea)
@@ -62,6 +62,8 @@
 int smp_num_siblings = 1;
 int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
 EXPORT_SYMBOL(phys_proc_id);
+int cpu_core_id[NR_CPUS]; /* Core ID of each logical CPU */
+EXPORT_SYMBOL(cpu_core_id);
 
 /* bitmap of online cpus */
 cpumask_t cpu_online_map;
@@ -885,6 +887,7 @@
 void *xquad_portio;
 
 cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
+cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
 
 static void __init smp_boot_cpus(unsigned int max_cpus)
 {
@@ -907,6 +910,9 @@
        cpus_clear(cpu_sibling_map[0]);
        cpu_set(0, cpu_sibling_map[0]);
 
+       cpus_clear(cpu_core_map[0]);
+       cpu_set(0, cpu_core_map[0]);
+
        /*
         * If we couldn't find an SMP configuration at boot time,
         * get out of here now!
@@ -919,6 +925,8 @@
                        printk(KERN_NOTICE "Local APIC not detected."
                                           " Using dummy APIC emulation.\n");
                map_cpu_to_logical_apicid();
+               cpu_set(0, cpu_sibling_map[0]);
+               cpu_set(0, cpu_core_map[0]);
                return;
        }
 
@@ -942,6 +950,8 @@
                printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell 
your hw vendor)\n");
                smpboot_clear_io_apic_irqs();
                phys_cpu_present_map = physid_mask_of_physid(0);
+               cpu_set(0, cpu_sibling_map[0]);
+               cpu_set(0, cpu_core_map[0]);
                return;
        }
 
@@ -955,6 +965,8 @@
                printk(KERN_INFO "SMP mode deactivated, forcing use of dummy 
APIC emulation.\n");
                smpboot_clear_io_apic_irqs();
                phys_cpu_present_map = physid_mask_of_physid(0);
+               cpu_set(0, cpu_sibling_map[0]);
+               cpu_set(0, cpu_core_map[0]);
                return;
        }
 
@@ -1035,10 +1047,13 @@
         * construct cpu_sibling_map[], so that we can tell sibling CPUs
         * efficiently.
         */
-       for (cpu = 0; cpu < NR_CPUS; cpu++)
+       for (cpu = 0; cpu < NR_CPUS; cpu++) {
                cpus_clear(cpu_sibling_map[cpu]);
+               cpus_clear(cpu_core_map[cpu]);
+       }
 
        for (cpu = 0; cpu < NR_CPUS; cpu++) {
+               struct cpuinfo_x86 *c = cpu_data + cpu;
                int siblings = 0;
                int i;
                if (!cpu_isset(cpu, cpu_callout_map))
@@ -1048,7 +1063,7 @@
                        for (i = 0; i < NR_CPUS; i++) {
                                if (!cpu_isset(i, cpu_callout_map))
                                        continue;
-                               if (phys_proc_id[cpu] == phys_proc_id[i]) {
+                               if (cpu_core_id[cpu] == cpu_core_id[i]) {
                                        siblings++;
                                        cpu_set(i, cpu_sibling_map[cpu]);
                                }
@@ -1060,6 +1075,18 @@
 
                if (siblings != smp_num_siblings)
                        printk(KERN_WARNING "WARNING: %d siblings found for 
CPU%d, should be %d\n", siblings, cpu, smp_num_siblings);
+
+               if (c->x86_num_cores > 1) {
+                       for (i = 0; i < NR_CPUS; i++) {
+                               if (!cpu_isset(i, cpu_callout_map))
+                                       continue;
+                               if (phys_proc_id[cpu] == phys_proc_id[i]) {
+                                       cpu_set(i, cpu_core_map[cpu]);
+                               }
+                       }
+               } else {
+                       cpu_core_map[cpu] = cpu_sibling_map[cpu];
+               }
        }
 
        if (nmi_watchdog == NMI_LOCAL_APIC)
Index: arch/x86_64/kernel/setup.c
===================================================================
--- 360cf103473c058cb6db99fd6a8c6e22dfa74c96/arch/x86_64/kernel/setup.c  
(mode:100644 sha1:57f619052badd62e28b29e0ed0bef1bfa49ba7ed)
+++ 28e60a8b733db213e88b0aee8ef3861a93a6fa48/arch/x86_64/kernel/setup.c  
(mode:100644 sha1:ef74564eedebc170c86c823a15715c746bccbe0f)
@@ -774,7 +774,7 @@
 {
 #ifdef CONFIG_SMP
        u32     eax, ebx, ecx, edx;
-       int     index_lsb, index_msb, tmp;
+       int     index_msb, tmp;
        int     cpu = smp_processor_id();
        
        if (!cpu_has(c, X86_FEATURE_HT))
@@ -786,7 +786,6 @@
        if (smp_num_siblings == 1) {
                printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
        } else if (smp_num_siblings > 1) {
-               index_lsb = 0;
                index_msb = 31;
                /*
                 * At this point we only support two siblings per
@@ -798,21 +797,33 @@
                        return;
                }
                tmp = smp_num_siblings;
-               while ((tmp & 1) == 0) {
-                       tmp >>=1 ;
-                       index_lsb++;
-               }
-               tmp = smp_num_siblings;
                while ((tmp & 0x80000000 ) == 0) {
                        tmp <<=1 ;
                        index_msb--;
                }
-               if (index_lsb != index_msb )
+               if (smp_num_siblings & (smp_num_siblings - 1))
                        index_msb++;
                phys_proc_id[cpu] = phys_pkg_id(index_msb);
                
                printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
                       phys_proc_id[cpu]);
+
+               smp_num_siblings = smp_num_siblings / c->x86_num_cores;
+
+               tmp = smp_num_siblings;
+               index_msb = 31;
+               while ((tmp & 0x80000000) == 0) {
+                       tmp <<=1 ;
+                       index_msb--;
+               }
+               if (smp_num_siblings & (smp_num_siblings - 1))
+                       index_msb++;
+
+               cpu_core_id[cpu] = phys_pkg_id(index_msb);
+
+               if (c->x86_num_cores > 1)
+                       printk(KERN_INFO  "CPU: Processor Core ID: %d\n",
+                              cpu_core_id[cpu]);
        }
 #endif
 }
@@ -829,7 +840,28 @@
                smp_num_siblings = 1;
 #endif
 }
-       
+
+/*
+ * find out the number of processor cores on the die
+ */
+static int __init intel_num_cpu_cores(struct cpuinfo_x86 *c)
+{
+       unsigned int eax;
+
+       if (c->cpuid_level < 4)
+               return 1;
+
+       __asm__("cpuid"
+               : "=a" (eax)
+               : "0" (4), "c" (0)
+               : "bx", "dx");
+
+       if (eax & 0x1f)
+               return ((eax >> 26) + 1);
+       else
+               return 1;
+}
+
 static void __init init_intel(struct cpuinfo_x86 *c)
 {
        /* Cache sizes */
@@ -847,6 +879,7 @@
                c->x86_cache_alignment = c->x86_clflush_size * 2;
        if (c->x86 >= 15)
                set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
+       c->x86_num_cores = intel_num_cpu_cores(c);
 }
 
 void __init get_cpu_vendor(struct cpuinfo_x86 *c)
@@ -1153,13 +1186,16 @@
                                        seq_printf(m, " [%d]", i);
                        }
        }
-       seq_printf(m, "\n");
 
-       if (c->x86_num_cores > 1)
-               seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores);
-
-       seq_printf(m, "\n\n"); 
+       seq_printf(m, "\n");
 
+#ifdef CONFIG_SMP
+       /* Put new fields at the end to lower the probability of
+          breaking user space parsers. */
+       seq_printf(m, "core id\t\t: %d\n", cpu_core_id[c - cpu_data]);
+       seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores);
+#endif
+       seq_printf(m, "\n");
        return 0;
 }
 
Index: arch/x86_64/kernel/smpboot.c
===================================================================
--- 360cf103473c058cb6db99fd6a8c6e22dfa74c96/arch/x86_64/kernel/smpboot.c  
(mode:100644 sha1:e5714090b00d165e421304b06889e4532d94cf81)
+++ 28e60a8b733db213e88b0aee8ef3861a93a6fa48/arch/x86_64/kernel/smpboot.c  
(mode:100644 sha1:7e2de8925b0f5430109fbc9c682be38872079e1e)
@@ -58,7 +58,10 @@
 int smp_num_siblings = 1;
 /* Package ID of each logical CPU */
 u8 phys_proc_id[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
+/* Core ID of each logical CPU */
+u8 cpu_core_id[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
 EXPORT_SYMBOL(phys_proc_id);
+EXPORT_SYMBOL(cpu_core_id);
 
 /* Bitmask of currently online CPUs */
 cpumask_t cpu_online_map;
@@ -71,6 +74,7 @@
 struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
 
 cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
+cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
 
 /*
  * Trampoline 80x86 program as an array.
@@ -713,6 +717,7 @@
                io_apic_irqs = 0;
                cpu_online_map = cpumask_of_cpu(0);
                cpu_set(0, cpu_sibling_map[0]);
+               cpu_set(0, cpu_core_map[0]);
                phys_cpu_present_map = physid_mask_of_physid(0);
                if (APIC_init_uniprocessor())
                        printk(KERN_NOTICE "Local APIC not detected."
@@ -740,6 +745,7 @@
                io_apic_irqs = 0;
                cpu_online_map = cpumask_of_cpu(0);
                cpu_set(0, cpu_sibling_map[0]);
+               cpu_set(0, cpu_core_map[0]);
                phys_cpu_present_map = physid_mask_of_physid(0);
                disable_apic = 1;
                goto smp_done;
@@ -756,6 +762,7 @@
                io_apic_irqs = 0;
                cpu_online_map = cpumask_of_cpu(0);
                cpu_set(0, cpu_sibling_map[0]);
+               cpu_set(0, cpu_core_map[0]);
                phys_cpu_present_map = physid_mask_of_physid(0);
                disable_apic = 1;
                goto smp_done;
@@ -833,10 +840,13 @@
         * Construct cpu_sibling_map[], so that we can tell the
         * sibling CPU efficiently.
         */
-       for (cpu = 0; cpu < NR_CPUS; cpu++)
+       for (cpu = 0; cpu < NR_CPUS; cpu++) {
                cpus_clear(cpu_sibling_map[cpu]);
+               cpus_clear(cpu_core_map[cpu]);
+       }
 
        for (cpu = 0; cpu < NR_CPUS; cpu++) {
+               struct cpuinfo_x86 *c = cpu_data + cpu;
                int siblings = 0;
                int i;
                if (!cpu_isset(cpu, cpu_callout_map))
@@ -846,7 +856,7 @@
                        for (i = 0; i < NR_CPUS; i++) {
                                if (!cpu_isset(i, cpu_callout_map))
                                        continue;
-                               if (phys_proc_id[cpu] == phys_proc_id[i]) {
+                               if (phys_proc_id[cpu] == cpu_core_id[i]) {
                                        siblings++;
                                        cpu_set(i, cpu_sibling_map[cpu]);
                                }
@@ -862,6 +872,16 @@
                               siblings, cpu, smp_num_siblings);
                        smp_num_siblings = siblings;
                }       
+               if (c->x86_num_cores > 1) {
+                       for (i = 0; i < NR_CPUS; i++) {
+                               if (!cpu_isset(i, cpu_callout_map))
+                                       continue;
+                               if (phys_proc_id[cpu] == phys_proc_id[i]) {
+                                       cpu_set(i, cpu_core_map[cpu]);
+                               }
+                       }
+               } else
+                       cpu_core_map[cpu] = cpu_sibling_map[cpu];
        }
 
        Dprintk("Boot done.\n");
Index: include/asm-i386/processor.h
===================================================================
--- 360cf103473c058cb6db99fd6a8c6e22dfa74c96/include/asm-i386/processor.h  
(mode:100644 sha1:7149784ed40bbde077e6ff0dbc68fc8cabead1b6)
+++ 28e60a8b733db213e88b0aee8ef3861a93a6fa48/include/asm-i386/processor.h  
(mode:100644 sha1:359bb0151742b6c2c36becf4c4da74f03af9f222)
@@ -98,6 +98,7 @@
 #endif
 
 extern int phys_proc_id[NR_CPUS];
+extern int cpu_core_id[NR_CPUS];
 extern char ignore_fpu_irq;
 
 extern void identify_cpu(struct cpuinfo_x86 *);
Index: include/asm-i386/smp.h
===================================================================
--- 360cf103473c058cb6db99fd6a8c6e22dfa74c96/include/asm-i386/smp.h  
(mode:100644 sha1:dd1491225d5191f90935f564696f1bbaf904e538)
+++ 28e60a8b733db213e88b0aee8ef3861a93a6fa48/include/asm-i386/smp.h  
(mode:100644 sha1:e03a206dfa36fbde0d15ac5a65f8eea1e7fa7503)
@@ -35,6 +35,7 @@
 extern int pic_mode;
 extern int smp_num_siblings;
 extern cpumask_t cpu_sibling_map[];
+extern cpumask_t cpu_core_map[];
 
 extern void smp_flush_tlb(void);
 extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs);
Index: include/asm-x86_64/smp.h
===================================================================
--- 360cf103473c058cb6db99fd6a8c6e22dfa74c96/include/asm-x86_64/smp.h  
(mode:100644 sha1:fe523e3e2ff42cceeb9388a17557ab8168a0b1d9)
+++ 28e60a8b733db213e88b0aee8ef3861a93a6fa48/include/asm-x86_64/smp.h  
(mode:100644 sha1:f5eaa1ab48ff20f11eed67bf1698d121e5e18b5a)
@@ -48,7 +48,9 @@
 extern void zap_low_mappings(void);
 void smp_stop_cpu(void);
 extern cpumask_t cpu_sibling_map[NR_CPUS];
+extern cpumask_t cpu_core_map[NR_CPUS];
 extern u8 phys_proc_id[NR_CPUS];
+extern u8 cpu_core_id[NR_CPUS];
 
 #define SMP_TRAMPOLINE_BASE 0x6000
 
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to