diff options
author | Andi Kleen <ak@suse.de> | 2005-04-16 15:25:15 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:25:15 -0700 |
commit | 3dd9d514846cdca1dcef2e4fce666d85e199e844 (patch) | |
tree | 28e60a8b733db213e88b0aee8ef3861a93a6fa48 /arch/i386/kernel/cpu | |
parent | f2ea2750fbe56867bc8e0eb595115b14195a3e5e (diff) | |
download | op-kernel-dev-3dd9d514846cdca1dcef2e4fce666d85e199e844.zip op-kernel-dev-3dd9d514846cdca1dcef2e4fce666d85e199e844.tar.gz |
[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/cpu')
-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 |
4 files changed, 58 insertions, 14 deletions
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c index ae94585..fa10d0a 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) } 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 @@ static void __init init_amd(struct cpuinfo_x86 *c) 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) diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index ebd5d82..ed4c9c3 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) 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 @@ void __init detect_ht(struct cpuinfo_x86 *c) 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 @@ void __init detect_ht(struct cpuinfo_x86 *c) 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 diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c index b8d847b..121aa21 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) } +/* + * 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 @@ static void __init init_intel(struct cpuinfo_x86 *c) if ( p ) strcpy(c->x86_model_id, p); + c->x86_num_cores = num_cpu_cores(c); + detect_ht(c); /* Work around errata */ diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c index 89a2956..0f1125b 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) 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; } |